Import clang r309604 from branches/release_50

This commit is contained in:
joerg 2017-08-01 19:34:09 +00:00
parent 51efcbbd66
commit db05eb1cc8
2794 changed files with 172166 additions and 36287 deletions

View File

@ -42,7 +42,7 @@ if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR )
list(GET CONFIG_OUTPUT 3 INCLUDE_DIR)
list(GET CONFIG_OUTPUT 4 LLVM_OBJ_ROOT)
list(GET CONFIG_OUTPUT 5 MAIN_SRC_DIR)
list(GET CONFIG_OUTPUT 6 LLVM_CMAKE_PATH)
list(GET CONFIG_OUTPUT 6 LLVM_CONFIG_CMAKE_PATH)
if(NOT MSVC_IDE)
set(LLVM_ENABLE_ASSERTIONS ${ENABLE_ASSERTIONS}
@ -57,6 +57,10 @@ if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR )
set(LLVM_BINARY_DIR ${LLVM_OBJ_ROOT} CACHE PATH "Path to LLVM build tree")
set(LLVM_MAIN_SRC_DIR ${MAIN_SRC_DIR} CACHE PATH "Path to LLVM source tree")
# Normalize LLVM_CMAKE_PATH. --cmakedir might contain backslashes.
# CMake assumes slashes as PATH.
file(TO_CMAKE_PATH ${LLVM_CONFIG_CMAKE_PATH} LLVM_CMAKE_PATH)
find_program(LLVM_TABLEGEN_EXE "llvm-tblgen" ${LLVM_TOOLS_BINARY_DIR}
NO_DEFAULT_PATH)
@ -78,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)
@ -181,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)
@ -325,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)
@ -356,6 +359,10 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
PATTERN "*.inc"
PATTERN "*.h"
)
install(PROGRAMS utils/bash-autocomplete.sh
DESTINATION share/clang
)
endif()
add_definitions( -D_GNU_SOURCE )
@ -364,29 +371,25 @@ 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)
add_definitions(-DCLANG_ENABLE_ARCMT)
add_definitions(-DCLANG_ENABLE_OBJC_REWRITER)
endif()
if(CLANG_ENABLE_STATIC_ANALYZER)
add_definitions(-DCLANG_ENABLE_STATIC_ANALYZER)
set(CLANG_ENABLE_OBJC_REWRITER ON)
endif()
# Clang version information
@ -415,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)
@ -515,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)
@ -531,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)
@ -579,10 +579,17 @@ if (CLANG_ENABLE_BOOTSTRAP)
add_dependencies(clang-bootstrap-deps compiler-rt)
endif()
set(C_COMPILER "clang")
set(CXX_COMPILER "clang++")
if(WIN32)
set(C_COMPILER "clang-cl.exe")
set(CXX_COMPILER "clang-cl.exe")
endif()
set(COMPILER_OPTIONS
-DCMAKE_CXX_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang++
-DCMAKE_C_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang
-DCMAKE_ASM_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang)
-DCMAKE_CXX_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/${CXX_COMPILER}
-DCMAKE_C_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/${C_COMPILER}
-DCMAKE_ASM_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/${C_COMPILER})
if(BOOTSTRAP_LLVM_BUILD_INSTRUMENTED)
add_dependencies(clang-bootstrap-deps llvm-profdata)
@ -696,3 +703,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)

View File

@ -20,13 +20,5 @@ The available modules are:
Bindings for the Clang indexing library.
"""
# Python 3 uses unicode for strings. The bindings, in particular the interaction
# with ctypes, need modifying to handle conversions between unicode and
# c-strings.
import sys
if sys.version_info[0] != 2:
raise Exception("Only Python 2 is supported.")
__all__ = ['cindex']

View File

@ -67,6 +67,60 @@ import collections
import clang.enumerations
import sys
if sys.version_info[0] == 3:
# Python 3 strings are unicode, translate them to/from utf8 for C-interop.
class c_interop_string(c_char_p):
def __init__(self, p=None):
if p is None:
p = ""
if isinstance(p, str):
p = p.encode("utf8")
super(c_char_p, self).__init__(p)
def __str__(self):
return self.value
@property
def value(self):
if super(c_char_p, self).value is None:
return None
return super(c_char_p, self).value.decode("utf8")
@classmethod
def from_param(cls, param):
if isinstance(param, str):
return cls(param)
if isinstance(param, bytes):
return cls(param)
raise TypeError("Cannot convert '{}' to '{}'".format(type(param).__name__, cls.__name__))
@staticmethod
def to_python_string(x, *args):
return x.value
def b(x):
if isinstance(x, bytes):
return x
return x.encode('utf8')
xrange = range
elif sys.version_info[0] == 2:
# Python 2 strings are utf8 byte strings, no translation is needed for
# C-interop.
c_interop_string = c_char_p
def _to_python_string(x, *args):
return x
c_interop_string.to_python_string = staticmethod(_to_python_string)
def b(x):
return x
# ctypes doesn't implicitly convert c_void_p to the appropriate wrapper
# object. This is a problem, because it means that from_parameter will see an
# integer and pass the wrong value on platforms where int != void*. Work around
@ -157,6 +211,7 @@ class _CXString(Structure):
assert isinstance(res, _CXString)
return conf.lib.clang_getCString(res)
class SourceLocation(Structure):
"""
A SourceLocation represents a particular location within a source file.
@ -596,7 +651,7 @@ class CursorKind(BaseEnumeration):
@staticmethod
def get_all_kinds():
"""Return all CursorKind enumeration instances."""
return filter(None, CursorKind._kinds)
return [x for x in CursorKind._kinds if not x is None]
def is_declaration(self):
"""Test if this is a declaration kind."""
@ -727,7 +782,7 @@ CursorKind.CONVERSION_FUNCTION = CursorKind(26)
# A C++ template type parameter
CursorKind.TEMPLATE_TYPE_PARAMETER = CursorKind(27)
# A C++ non-type template paramater.
# A C++ non-type template parameter.
CursorKind.TEMPLATE_NON_TYPE_PARAMETER = CursorKind(28)
# A C++ template template parameter.
@ -1312,6 +1367,30 @@ TemplateArgumentKind.DECLARATION = TemplateArgumentKind(2)
TemplateArgumentKind.NULLPTR = TemplateArgumentKind(3)
TemplateArgumentKind.INTEGRAL = TemplateArgumentKind(4)
### Exception Specification Kinds ###
class ExceptionSpecificationKind(BaseEnumeration):
"""
An ExceptionSpecificationKind describes the kind of exception specification
that a function has.
"""
# The required BaseEnumeration declarations.
_kinds = []
_name_map = None
def __repr__(self):
return 'ExceptionSpecificationKind.{}'.format(self.name)
ExceptionSpecificationKind.NONE = ExceptionSpecificationKind(0)
ExceptionSpecificationKind.DYNAMIC_NONE = ExceptionSpecificationKind(1)
ExceptionSpecificationKind.DYNAMIC = ExceptionSpecificationKind(2)
ExceptionSpecificationKind.MS_ANY = ExceptionSpecificationKind(3)
ExceptionSpecificationKind.BASIC_NOEXCEPT = ExceptionSpecificationKind(4)
ExceptionSpecificationKind.COMPUTED_NOEXCEPT = ExceptionSpecificationKind(5)
ExceptionSpecificationKind.UNEVALUATED = ExceptionSpecificationKind(6)
ExceptionSpecificationKind.UNINSTANTIATED = ExceptionSpecificationKind(7)
ExceptionSpecificationKind.UNPARSED = ExceptionSpecificationKind(8)
### Cursors ###
class Cursor(Structure):
@ -1399,6 +1478,11 @@ class Cursor(Structure):
"""
return conf.lib.clang_CXXMethod_isVirtual(self)
def is_scoped_enum(self):
"""Returns True if the cursor refers to a scoped enum declaration.
"""
return conf.lib.clang_EnumDecl_isScoped(self)
def get_definition(self):
"""
If the cursor is a reference to a declaration or a declaration of
@ -1531,6 +1615,18 @@ class Cursor(Structure):
return self._result_type
@property
def exception_specification_kind(self):
'''
Retrieve the exception specification kind, which is one of the values
from the ExceptionSpecificationKind enumeration.
'''
if not hasattr(self, '_exception_specification_kind'):
exc_kind = conf.lib.clang_getCursorExceptionSpecificationType(self)
self._exception_specification_kind = ExceptionSpecificationKind.from_id(exc_kind)
return self._exception_specification_kind
@property
def underlying_typedef_type(self):
"""Return the underlying type of a typedef declaration.
@ -1887,6 +1983,7 @@ TypeKind.OBJCID = TypeKind(27)
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)
@ -1907,6 +2004,47 @@ TypeKind.DEPENDENTSIZEDARRAY = TypeKind(116)
TypeKind.MEMBERPOINTER = TypeKind(117)
TypeKind.AUTO = TypeKind(118)
TypeKind.ELABORATED = TypeKind(119)
TypeKind.PIPE = TypeKind(120)
TypeKind.OCLIMAGE1DRO = TypeKind(121)
TypeKind.OCLIMAGE1DARRAYRO = TypeKind(122)
TypeKind.OCLIMAGE1DBUFFERRO = TypeKind(123)
TypeKind.OCLIMAGE2DRO = TypeKind(124)
TypeKind.OCLIMAGE2DARRAYRO = TypeKind(125)
TypeKind.OCLIMAGE2DDEPTHRO = TypeKind(126)
TypeKind.OCLIMAGE2DARRAYDEPTHRO = TypeKind(127)
TypeKind.OCLIMAGE2DMSAARO = TypeKind(128)
TypeKind.OCLIMAGE2DARRAYMSAARO = TypeKind(129)
TypeKind.OCLIMAGE2DMSAADEPTHRO = TypeKind(130)
TypeKind.OCLIMAGE2DARRAYMSAADEPTHRO = TypeKind(131)
TypeKind.OCLIMAGE3DRO = TypeKind(132)
TypeKind.OCLIMAGE1DWO = TypeKind(133)
TypeKind.OCLIMAGE1DARRAYWO = TypeKind(134)
TypeKind.OCLIMAGE1DBUFFERWO = TypeKind(135)
TypeKind.OCLIMAGE2DWO = TypeKind(136)
TypeKind.OCLIMAGE2DARRAYWO = TypeKind(137)
TypeKind.OCLIMAGE2DDEPTHWO = TypeKind(138)
TypeKind.OCLIMAGE2DARRAYDEPTHWO = TypeKind(139)
TypeKind.OCLIMAGE2DMSAAWO = TypeKind(140)
TypeKind.OCLIMAGE2DARRAYMSAAWO = TypeKind(141)
TypeKind.OCLIMAGE2DMSAADEPTHWO = TypeKind(142)
TypeKind.OCLIMAGE2DARRAYMSAADEPTHWO = TypeKind(143)
TypeKind.OCLIMAGE3DWO = TypeKind(144)
TypeKind.OCLIMAGE1DRW = TypeKind(145)
TypeKind.OCLIMAGE1DARRAYRW = TypeKind(146)
TypeKind.OCLIMAGE1DBUFFERRW = TypeKind(147)
TypeKind.OCLIMAGE2DRW = TypeKind(148)
TypeKind.OCLIMAGE2DARRAYRW = TypeKind(149)
TypeKind.OCLIMAGE2DDEPTHRW = TypeKind(150)
TypeKind.OCLIMAGE2DARRAYDEPTHRW = TypeKind(151)
TypeKind.OCLIMAGE2DMSAARW = TypeKind(152)
TypeKind.OCLIMAGE2DARRAYMSAARW = TypeKind(153)
TypeKind.OCLIMAGE2DMSAADEPTHRW = TypeKind(154)
TypeKind.OCLIMAGE2DARRAYMSAADEPTHRW = TypeKind(155)
TypeKind.OCLIMAGE3DRW = TypeKind(156)
TypeKind.OCLSAMPLER = TypeKind(157)
TypeKind.OCLEVENT = TypeKind(158)
TypeKind.OCLQUEUE = TypeKind(159)
TypeKind.OCLRESERVEID = TypeKind(160)
class RefQualifierKind(BaseEnumeration):
"""Describes a specific ref-qualifier of a type."""
@ -2065,6 +2203,12 @@ class Type(Structure):
return conf.lib.clang_isFunctionTypeVariadic(self)
def get_address_space(self):
return conf.lib.clang_getAddressSpace(self)
def get_typedef_name(self):
return conf.lib.clang_getTypedefName(self)
def is_pod(self):
"""Determine whether this Type represents plain old data (POD)."""
return conf.lib.clang_isPODType(self)
@ -2127,7 +2271,7 @@ class Type(Structure):
"""
Retrieve the offset of a field in the record.
"""
return conf.lib.clang_Type_getOffsetOf(self, c_char_p(fieldname))
return conf.lib.clang_Type_getOffsetOf(self, fieldname)
def get_ref_qualifier(self):
"""
@ -2151,6 +2295,14 @@ class Type(Structure):
callbacks['fields_visit'](visitor), fields)
return iter(fields)
def get_exception_specification_kind(self):
"""
Return the kind of the exception specification; a value from
the ExceptionSpecificationKind enumeration.
"""
return ExceptionSpecificationKind.from_id(
conf.lib.clang.getExceptionSpecificationType(self))
@property
def spelling(self):
"""Retrieve the spelling of this Type."""
@ -2238,7 +2390,7 @@ class CompletionChunk:
def spelling(self):
if self.__kindNumber in SpellingCache:
return SpellingCache[self.__kindNumber]
return conf.lib.clang_getCompletionChunkText(self.cs, self.key).spelling
return conf.lib.clang_getCompletionChunkText(self.cs, self.key)
# We do not use @CachedProperty here, as the manual implementation is
# apparently still significantly faster. Please profile carefully if you
@ -2344,7 +2496,7 @@ class CompletionString(ClangObject):
return " | ".join([str(a) for a in self]) \
+ " || Priority: " + str(self.priority) \
+ " || Availability: " + str(self.availability) \
+ " || Brief comment: " + str(self.briefComment.spelling)
+ " || Brief comment: " + str(self.briefComment)
availabilityKinds = {
0: CompletionChunk.Kind("Available"),
@ -2541,7 +2693,7 @@ class TranslationUnit(ClangObject):
args_array = None
if len(args) > 0:
args_array = (c_char_p * len(args))(* args)
args_array = (c_char_p * len(args))(*[b(x) for x in args])
unsaved_array = None
if len(unsaved_files) > 0:
@ -2550,8 +2702,8 @@ class TranslationUnit(ClangObject):
if hasattr(contents, "read"):
contents = contents.read()
unsaved_array[i].name = name
unsaved_array[i].contents = contents
unsaved_array[i].name = b(name)
unsaved_array[i].contents = b(contents)
unsaved_array[i].length = len(contents)
ptr = conf.lib.clang_parseTranslationUnit(index, filename, args_array,
@ -2796,8 +2948,8 @@ class TranslationUnit(ClangObject):
print(value)
if not isinstance(value, str):
raise TypeError('Unexpected unsaved file contents.')
unsaved_files_array[i].name = name
unsaved_files_array[i].contents = value
unsaved_files_array[i].name = b(name)
unsaved_files_array[i].contents = b(value)
unsaved_files_array[i].length = len(value)
ptr = conf.lib.clang_codeCompleteAt(self, path, line, column,
unsaved_files_array, len(unsaved_files), options)
@ -2832,7 +2984,7 @@ class File(ClangObject):
@property
def name(self):
"""Return the complete file and path name of the file."""
return conf.lib.clang_getCString(conf.lib.clang_getFileName(self))
return conf.lib.clang_getFileName(self)
@property
def time(self):
@ -3063,7 +3215,7 @@ functionList = [
[c_object_p]),
("clang_CompilationDatabase_fromDirectory",
[c_char_p, POINTER(c_uint)],
[c_interop_string, POINTER(c_uint)],
c_object_p,
CompilationDatabase.from_result),
@ -3073,7 +3225,7 @@ functionList = [
CompileCommands.from_result),
("clang_CompilationDatabase_getCompileCommands",
[c_object_p, c_char_p],
[c_object_p, c_interop_string],
c_object_p,
CompileCommands.from_result),
@ -3108,7 +3260,7 @@ functionList = [
c_uint),
("clang_codeCompleteAt",
[TranslationUnit, c_char_p, c_int, c_int, c_void_p, c_int, c_int],
[TranslationUnit, c_interop_string, c_int, c_int, c_void_p, c_int, c_int],
POINTER(CCRStructure)),
("clang_codeCompleteGetDiagnostic",
@ -3124,7 +3276,7 @@ functionList = [
c_object_p),
("clang_createTranslationUnit",
[Index, c_char_p],
[Index, c_interop_string],
c_object_p),
("clang_CXXConstructor_isConvertingConstructor",
@ -3167,6 +3319,10 @@ functionList = [
[Cursor],
bool),
("clang_EnumDecl_isScoped",
[Cursor],
bool),
("clang_defaultDiagnosticDisplayOptions",
[],
c_uint),
@ -3214,7 +3370,8 @@ functionList = [
("clang_formatDiagnostic",
[Diagnostic, c_uint],
_CXString),
_CXString,
_CXString.from_result),
("clang_getArgType",
[Type, c_uint],
@ -3254,7 +3411,8 @@ functionList = [
("clang_getCompletionBriefComment",
[c_void_p],
_CXString),
_CXString,
_CXString.from_result),
("clang_getCompletionChunkCompletionString",
[c_void_p, c_int],
@ -3266,7 +3424,8 @@ functionList = [
("clang_getCompletionChunkText",
[c_void_p, c_int],
_CXString),
_CXString,
_CXString.from_result),
("clang_getCompletionPriority",
[c_void_p],
@ -3274,7 +3433,8 @@ functionList = [
("clang_getCString",
[_CXString],
c_char_p),
c_interop_string,
c_interop_string.to_python_string),
("clang_getCursor",
[TranslationUnit, SourceLocation],
@ -3421,12 +3581,13 @@ functionList = [
Type.from_result),
("clang_getFile",
[TranslationUnit, c_char_p],
[TranslationUnit, c_interop_string],
c_object_p),
("clang_getFileName",
[File],
_CXString), # TODO go through _CXString.from_result?
_CXString,
_CXString.from_result),
("clang_getFileTime",
[File],
@ -3550,7 +3711,8 @@ functionList = [
("clang_getTUResourceUsageName",
[c_uint],
c_char_p),
c_interop_string,
c_interop_string.to_python_string),
("clang_getTypeDeclaration",
[Type],
@ -3562,6 +3724,11 @@ functionList = [
Type,
Type.from_result),
("clang_getTypedefName",
[Type],
_CXString,
_CXString.from_result),
("clang_getTypeKindSpelling",
[c_uint],
_CXString,
@ -3645,7 +3812,7 @@ functionList = [
bool),
("clang_parseTranslationUnit",
[Index, c_char_p, c_void_p, c_int, c_void_p, c_int, c_int],
[Index, c_interop_string, c_void_p, c_int, c_void_p, c_int, c_int],
c_object_p),
("clang_reparseTranslationUnit",
@ -3653,7 +3820,7 @@ functionList = [
c_int),
("clang_saveTranslationUnit",
[TranslationUnit, c_char_p, c_uint],
[TranslationUnit, c_interop_string, c_uint],
c_int),
("clang_tokenize",
@ -3725,7 +3892,7 @@ functionList = [
Type.from_result),
("clang_Type_getOffsetOf",
[Type, c_char_p],
[Type, c_interop_string],
c_longlong),
("clang_Type_getSizeOf",
@ -3784,7 +3951,8 @@ def register_functions(lib, ignore_errors):
def register(item):
return register_function(lib, item, ignore_errors)
map(register, functionList)
for f in functionList:
register(f)
class Config:
library_path = None

View File

@ -255,6 +255,22 @@ def test_is_virtual_method():
assert foo.is_virtual_method()
assert not bar.is_virtual_method()
def test_is_scoped_enum():
"""Ensure Cursor.is_scoped_enum works."""
source = 'class X {}; enum RegularEnum {}; enum class ScopedEnum {};'
tu = get_tu(source, lang='cpp')
cls = get_cursor(tu, 'X')
regular_enum = get_cursor(tu, 'RegularEnum')
scoped_enum = get_cursor(tu, 'ScopedEnum')
assert cls is not None
assert regular_enum is not None
assert scoped_enum is not None
assert not cls.is_scoped_enum()
assert not regular_enum.is_scoped_enum()
assert scoped_enum.is_scoped_enum()
def test_underlying_type():
tu = get_tu('typedef int foo;')
typedef = get_cursor(tu, 'foo')

View File

@ -59,9 +59,12 @@ int SOME_DEFINE;
assert spellings[-1] == 'y'
def test_unsaved_files_2():
import StringIO
try:
from StringIO import StringIO
except:
from io import StringIO
tu = TranslationUnit.from_source('fake.c', unsaved_files = [
('fake.c', StringIO.StringIO('int x;'))])
('fake.c', StringIO('int x;'))])
spellings = [c.spelling for c in tu.cursor.get_children()]
assert spellings[-1] == 'x'

View File

@ -37,37 +37,44 @@ def test_a_struct():
assert not fields[0].type.is_const_qualified()
assert fields[0].type.kind == TypeKind.INT
assert fields[0].type.get_canonical().kind == TypeKind.INT
assert fields[0].type.get_typedef_name() == ''
assert fields[1].spelling == 'b'
assert not fields[1].type.is_const_qualified()
assert fields[1].type.kind == TypeKind.TYPEDEF
assert fields[1].type.get_canonical().kind == TypeKind.INT
assert fields[1].type.get_declaration().spelling == 'I'
assert fields[1].type.get_typedef_name() == 'I'
assert fields[2].spelling == 'c'
assert not fields[2].type.is_const_qualified()
assert fields[2].type.kind == TypeKind.LONG
assert fields[2].type.get_canonical().kind == TypeKind.LONG
assert fields[2].type.get_typedef_name() == ''
assert fields[3].spelling == 'd'
assert not fields[3].type.is_const_qualified()
assert fields[3].type.kind == TypeKind.ULONG
assert fields[3].type.get_canonical().kind == TypeKind.ULONG
assert fields[3].type.get_typedef_name() == ''
assert fields[4].spelling == 'e'
assert not fields[4].type.is_const_qualified()
assert fields[4].type.kind == TypeKind.LONG
assert fields[4].type.get_canonical().kind == TypeKind.LONG
assert fields[4].type.get_typedef_name() == ''
assert fields[5].spelling == 'f'
assert fields[5].type.is_const_qualified()
assert fields[5].type.kind == TypeKind.INT
assert fields[5].type.get_canonical().kind == TypeKind.INT
assert fields[5].type.get_typedef_name() == ''
assert fields[6].spelling == 'g'
assert not fields[6].type.is_const_qualified()
assert fields[6].type.kind == TypeKind.POINTER
assert fields[6].type.get_pointee().kind == TypeKind.INT
assert fields[6].type.get_typedef_name() == ''
assert fields[7].spelling == 'h'
assert not fields[7].type.is_const_qualified()
@ -75,6 +82,7 @@ def test_a_struct():
assert fields[7].type.get_pointee().kind == TypeKind.POINTER
assert fields[7].type.get_pointee().get_pointee().kind == TypeKind.POINTER
assert fields[7].type.get_pointee().get_pointee().get_pointee().kind == TypeKind.INT
assert fields[7].type.get_typedef_name() == ''
def test_references():
"""Ensure that a Type maintains a reference to a TranslationUnit."""
@ -404,3 +412,12 @@ def test_decay():
assert a.kind == TypeKind.INCOMPLETEARRAY
assert a.element_type.kind == TypeKind.INT
assert a.get_canonical().kind == TypeKind.INCOMPLETEARRAY
def test_addrspace():
"""Ensure the address space can be queried"""
tu = get_tu('__attribute__((address_space(2))) int testInteger = 3;', 'c')
testInteger = get_cursor(tu, 'testInteger')
assert testInteger is not None, "Could not find testInteger."
assert testInteger.type.get_address_space() == 2

View File

@ -0,0 +1,27 @@
import clang.cindex
from clang.cindex import ExceptionSpecificationKind
from .util import get_tu
def find_function_declarations(node, declarations=[]):
if node.kind == clang.cindex.CursorKind.FUNCTION_DECL:
declarations.append((node.spelling, node.exception_specification_kind))
for child in node.get_children():
declarations = find_function_declarations(child, declarations)
return declarations
def test_exception_specification_kind():
source = """int square1(int x);
int square2(int x) noexcept;
int square3(int x) noexcept(noexcept(x * x));"""
tu = get_tu(source, lang='cpp', flags=['-std=c++14'])
declarations = find_function_declarations(tu.cursor)
expected = [
('square1', ExceptionSpecificationKind.NONE),
('square2', ExceptionSpecificationKind.BASIC_NOEXCEPT),
('square3', ExceptionSpecificationKind.COMPUTED_NOEXCEPT)
]
assert declarations == expected

View 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)

View File

@ -13,6 +13,7 @@ set(CLANG_LINKS_TO_CREATE clang++ cc c++ CACHE STRING "")
set(CMAKE_MACOSX_RPATH ON CACHE BOOL "")
set(LLVM_ENABLE_ZLIB ON CACHE BOOL "")
set(LLVM_ENABLE_BACKTRACES OFF CACHE BOOL "")
set(LLVM_ENABLE_MODULES ON CACHE BOOL "")
set(LLVM_EXTERNALIZE_DEBUGINFO ON CACHE BOOL "")
set(CLANG_PLUGIN_SUPPORT OFF CACHE BOOL "")
set(BUG_REPORT_URL "http://developer.apple.com/bugreporter/" CACHE STRING "")
@ -28,8 +29,10 @@ set(LLVM_BUILD_TESTS ON CACHE BOOL "")
set(LLVM_ENABLE_LTO ON CACHE BOOL "")
set(CMAKE_C_FLAGS "-fno-stack-protector -fno-common -Wno-profile-instr-unprofiled" CACHE STRING "")
set(CMAKE_CXX_FLAGS "-fno-stack-protector -fno-common -Wno-profile-instr-unprofiled" 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 "")
if(LLVM_ENABLE_LTO AND NOT LLVM_ENABLE_LTO STREQUAL "THIN")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -gline-tables-only -DNDEBUG" CACHE STRING "")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -gline-tables-only -DNDEBUG" CACHE STRING "")
endif()
set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "")
set(LIBCXX_INSTALL_LIBRARY OFF CACHE BOOL "")

View File

@ -0,0 +1,50 @@
set(LLVM_TARGETS_TO_BUILD ARM;X86 CACHE STRING "")
# Builtins
set(LLVM_BUILTIN_TARGETS "armv7m-none-eabi;armv6m-none-eabi;armv7em-none-eabi" CACHE STRING "Builtin Targets")
set(BUILTINS_armv6m-none-eabi_CMAKE_SYSROOT ${BAREMETAL_ARMV6M_SYSROOT} CACHE STRING "armv6m-none-eabi Sysroot")
set(BUILTINS_armv6m-none-eabi_CMAKE_SYSTEM_NAME Generic CACHE STRING "armv6m-none-eabi System Name")
set(BUILTINS_armv6m-none-eabi_COMPILER_RT_BAREMETAL_BUILD ON CACHE BOOL "armv6m-none-eabi Baremetal build")
set(BUILTINS_armv6m-none-eabi_COMPILER_RT_OS_DIR "baremetal" CACHE STRING "armv6m-none-eabi os dir")
set(BUILTINS_armv7m-none-eabi_CMAKE_SYSROOT ${BAREMETAL_ARMV7M_SYSROOT} CACHE STRING "armv7m-none-eabi Sysroot")
set(BUILTINS_armv7m-none-eabi_CMAKE_SYSTEM_NAME Generic CACHE STRING "armv7m-none-eabi System Name")
set(BUILTINS_armv7m-none-eabi_COMPILER_RT_BAREMETAL_BUILD ON CACHE BOOL "armv7m-none-eabi Baremetal build")
set(BUILTINS_armv7m-none-eabi_CMAKE_C_FLAGS "-mfpu=fp-armv8" CACHE STRING "armv7m-none-eabi C Flags")
set(BUILTINS_armv7m-none-eabi_CMAKE_ASM_FLAGS "-mfpu=fp-armv8" CACHE STRING "armv7m-none-eabi ASM Flags")
set(BUILTINS_armv7m-none-eabi_COMPILER_RT_OS_DIR "baremetal" CACHE STRING "armv7m-none-eabi os dir")
set(BUILTINS_armv7em-none-eabi_CMAKE_SYSROOT ${BAREMETAL_ARMV7EM_SYSROOT} CACHE STRING "armv7em-none-eabi Sysroot")
set(BUILTINS_armv7em-none-eabi_CMAKE_SYSTEM_NAME Generic CACHE STRING "armv7em-none-eabi System Name")
set(BUILTINS_armv7em-none-eabi_COMPILER_RT_BAREMETAL_BUILD ON CACHE BOOL "armv7em-none-eabi Baremetal build")
set(BUILTINS_armv7em-none-eabi_CMAKE_C_FLAGS "-mfpu=fp-armv8" CACHE STRING "armv7em-none-eabi C Flags")
set(BUILTINS_armv7em-none-eabi_CMAKE_ASM_FLAGS "-mfpu=fp-armv8" CACHE STRING "armv7em-none-eabi ASM Flags")
set(BUILTINS_armv7em-none-eabi_COMPILER_RT_OS_DIR "baremetal" CACHE STRING "armv7em-none-eabi os dir")
set(LLVM_INSTALL_TOOLCHAIN_ONLY ON CACHE BOOL "")
set(LLVM_TOOLCHAIN_TOOLS
llc
llvm-ar
llvm-cxxfilt
llvm-dwarfdump
llvm-dsymutil
llvm-nm
llvm-objdump
llvm-ranlib
llvm-readobj
llvm-size
llvm-symbolizer
opt
CACHE STRING "")
set(LLVM_DISTRIBUTION_COMPONENTS
clang
lld
clang-headers
builtins-armv6m-none-eabi
builtins-armv7m-none-eabi
builtins-armv7em-none-eabi
runtimes
${LLVM_TOOLCHAIN_TOOLS}
CACHE STRING "")

View File

@ -29,6 +29,13 @@ set(CLANG_BOOTSTRAP_TARGETS
# Setup the bootstrap build.
set(CLANG_ENABLE_BOOTSTRAP ON CACHE BOOL "")
set(CLANG_BOOTSTRAP_CMAKE_ARGS
-C ${CMAKE_CURRENT_LIST_DIR}/DistributionExample-stage2.cmake
CACHE STRING "")
if(STAGE2_CACHE_FILE)
set(CLANG_BOOTSTRAP_CMAKE_ARGS
-C ${STAGE2_CACHE_FILE}
CACHE STRING "")
else()
set(CLANG_BOOTSTRAP_CMAKE_ARGS
-C ${CMAKE_CURRENT_LIST_DIR}/DistributionExample-stage2.cmake
CACHE STRING "")
endif()

View File

@ -0,0 +1,85 @@
# This file sets up a CMakeCache for the second stage of a Fuchsia toolchain
# build.
set(LLVM_TARGETS_TO_BUILD X86;ARM;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_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;aarch64-fuchsia" CACHE STRING "")
foreach(target x86_64;aarch64)
set(BUILTINS_${target}-fuchsia_CMAKE_SYSROOT ${FUCHSIA_${target}_SYSROOT} CACHE PATH "")
set(BUILTINS_${target}-fuchsia_CMAKE_SYSTEM_NAME Fuchsia CACHE STRING "")
endforeach()
if(NOT APPLE)
list(APPEND LLVM_BUILTIN_TARGETS "default")
endif()
set(LLVM_RUNTIME_TARGETS "default;x86_64-fuchsia;aarch64-fuchsia" CACHE STRING "")
foreach(target x86_64;aarch64)
set(RUNTIMES_${target}-fuchsia_CMAKE_BUILD_WITH_INSTALL_RPATH ON CACHE BOOL "")
set(RUNTIMES_${target}-fuchsia_CMAKE_SYSROOT ${FUCHSIA_${target}_SYSROOT} CACHE PATH "")
set(RUNTIMES_${target}-fuchsia_CMAKE_SYSTEM_NAME Fuchsia CACHE STRING "")
set(RUNTIMES_${target}-fuchsia_UNIX 1 CACHE BOOL "")
set(RUNTIMES_${target}-fuchsia_LLVM_ENABLE_LIBCXX ON CACHE BOOL "")
set(RUNTIMES_${target}-fuchsia_LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "")
set(RUNTIMES_${target}-fuchsia_LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "")
set(RUNTIMES_${target}-fuchsia_LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "")
set(RUNTIMES_${target}-fuchsia_LIBCXX_USE_COMPILER_RT ON CACHE BOOL "")
endforeach()
# Setup toolchain.
set(LLVM_INSTALL_TOOLCHAIN_ONLY ON CACHE BOOL "")
set(LLVM_TOOLCHAIN_TOOLS
llc
llvm-ar
llvm-cov
llvm-cxxfilt
llvm-dwarfdump
llvm-dsymutil
llvm-lib
llvm-nm
llvm-objdump
llvm-profdata
llvm-ranlib
llvm-readelf
llvm-readobj
llvm-size
llvm-symbolizer
opt
CACHE STRING "")
set(LLVM_DISTRIBUTION_COMPONENTS
clang
lld
lldb
liblldb
LTO
clang-format
clang-headers
clang-tidy
clangd
builtins
runtimes
${LLVM_TOOLCHAIN_TOOLS}
CACHE STRING "")

View File

@ -0,0 +1,52 @@
# 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 "")
foreach(target x86_64;aarch64)
if(FUCHSIA_${target}_SYSROOT)
list(APPEND EXTRA_ARGS -DFUCHSIA_${target}_SYSROOT=${FUCHSIA_${target}_SYSROOT})
endif()
endforeach()
# 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 "")

View File

@ -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

View File

@ -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@")

View 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

View File

@ -2258,16 +2258,13 @@ non-block type [*]_. Equivalent to the following code:
.. code-block:: objc
id objc_storeStrong(id *object, id value) {
value = [value retain];
void objc_storeStrong(id *object, id value) {
id oldValue = *object;
value = [value retain];
*object = value;
[oldValue release];
return value;
}
Always returns ``value``.
.. [*] This does not imply that a ``__strong`` object of block type is an
invalid argument to this function. Rather it implies that an ``objc_retain``
and not an ``objc_retainBlock`` operation will be emitted if the argument is

View File

@ -856,15 +856,15 @@ mentioned above, call:
.. code-block:: c
_Block_object_assign(&dst->target, src->target, BLOCK_FIELD_<appropo>);
_Block_object_assign(&dst->target, src->target, BLOCK_FIELD_<apropos>);
in the copy helper and:
.. code-block:: c
_Block_object_dispose(->target, BLOCK_FIELD_<appropo>);
_Block_object_dispose(->target, BLOCK_FIELD_<apropos>);
in the dispose helper where ``<appropo>`` is:
in the dispose helper where ``<apropos>`` is:
.. code-block:: c
@ -888,7 +888,7 @@ and functions are generated in the same manner.
Under ObjC we allow ``__weak`` as an attribute on ``__block`` variables, and
this causes the addition of ``BLOCK_FIELD_IS_WEAK`` orred onto the
``BLOCK_FIELD_IS_BYREF`` flag when copying the ``block_byref`` structure in the
``Block`` copy helper, and onto the ``BLOCK_FIELD_<appropo>`` field within the
``Block`` copy helper, and onto the ``BLOCK_FIELD_<apropos>`` field within the
``block_byref`` copy/dispose helper calls.
The prototypes, and summary, of the helper functions are:

View File

@ -91,8 +91,8 @@ endif()
endif()
if (LLVM_ENABLE_SPHINX)
include(AddSphinxTarget)
if (SPHINX_FOUND)
include(AddSphinxTarget)
if (${SPHINX_OUTPUT_HTML})
add_sphinx_target(html clang)
add_custom_command(TARGET docs-clang-html POST_BUILD

File diff suppressed because it is too large Load Diff

View File

@ -120,6 +120,18 @@ entity.
It operates on the current, potentially unsaved buffer and does not create
or save any files. To revert a formatting, just undo.
An alternative option is to format changes when saving a file and thus to
have a zero-effort integration into the coding workflow. To do this, add this to
your `.vimrc`:
.. code-block:: vim
function! Formatonsave()
let l:formatdiff = 1
pyf ~/llvm/tools/clang/tools/clang-format/clang-format.py
endfunction
autocmd BufWritePre *.h,*.cc,*.cpp call Formatonsave()
Emacs Integration
=================
@ -162,8 +174,9 @@ Download the latest Visual Studio extension from the `alpha build site
Script for patch reformatting
=============================
The python script `clang/tools/clang-format-diff.py` parses the output of
a unified diff and reformats all contained lines with :program:`clang-format`.
The python script `clang/tools/clang-format/clang-format-diff.py` parses the
output of a unified diff and reformats all contained lines with
:program:`clang-format`.
.. code-block:: console

File diff suppressed because it is too large Load Diff

View File

@ -437,12 +437,17 @@ export this information, every DSO implements
.. code-block:: none
void __cfi_check(uint64 CallSiteTypeId, void *TargetAddr)
void __cfi_check(uint64 CallSiteTypeId, void *TargetAddr, void *DiagData)
This function provides external modules with access to CFI checks for the
targets inside this DSO. For each known ``CallSiteTypeId``, this function
performs an ``llvm.type.test`` with the corresponding type identifier. It
aborts if the type is unknown, or if the check fails.
This function provides external modules with access to CFI checks for
the targets inside this DSO. For each known ``CallSiteTypeId``, this
function performs an ``llvm.type.test`` with the corresponding type
identifier. It reports an error if the type is unknown, or if the
check fails. Depending on the values of compiler flags
``-fsanitize-trap`` and ``-fsanitize-recover``, this function may
print an error, abort and/or return to the caller. ``DiagData`` is an
opaque pointer to the diagnostic information about the error, or
``null`` if the caller does not provide this information.
The basic implementation is a large switch statement over all values
of CallSiteTypeId supported by this DSO, and each case is similar to
@ -452,11 +457,10 @@ CFI Shadow
----------
To route CFI checks to the target DSO's __cfi_check function, a
mapping from possible virtual / indirect call targets to
the corresponding __cfi_check functions is maintained. This mapping is
mapping from possible virtual / indirect call targets to the
corresponding __cfi_check functions is maintained. This mapping is
implemented as a sparse array of 2 bytes for every possible page (4096
bytes) of memory. The table is kept readonly (FIXME: not yet) most of
the time.
bytes) of memory. The table is kept readonly most of the time.
There are 3 types of shadow values:
@ -481,14 +485,24 @@ them.
CFI_SlowPath
------------
The slow path check is implemented in compiler-rt library as
The slow path check is implemented in a runtime support library as
.. code-block:: none
void __cfi_slowpath(uint64 CallSiteTypeId, void *TargetAddr)
void __cfi_slowpath_diag(uint64 CallSiteTypeId, void *TargetAddr, void *DiagData)
This functions loads a shadow value for ``TargetAddr``, finds the
address of __cfi_check as described above and calls that.
These functions loads a shadow value for ``TargetAddr``, finds the
address of ``__cfi_check`` as described above and calls
that. ``DiagData`` is an opaque pointer to diagnostic data which is
passed verbatim to ``__cfi_check``, and ``__cfi_slowpath`` passes
``nullptr`` instead.
Compiler-RT library contains reference implementations of slowpath
functions, but they have unresolvable issues with correctness and
performance in the handling of dlopen(). It is recommended that
platforms provide their own implementations, usually as part of libc
or libdl.
Position-independent executable requirement
-------------------------------------------
@ -498,12 +512,100 @@ In non-PIE executables the address of an external function (taken from
the main executable) is the address of that functions 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 +642,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

View File

@ -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."

View File

@ -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.

View File

@ -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++
@ -780,14 +780,14 @@ Use ``__has_feature(cxx_variadic_templates)`` or
``__has_extension(cxx_variadic_templates)`` to determine if support for
variadic templates is enabled.
C++1y
C++14
-----
The features listed below are part of the committee draft for the C++1y
standard. As a result, all these features are enabled with the ``-std=c++1y``
or ``-std=gnu++1y`` option when compiling C++ code.
The features listed below are part of the C++14 standard. As a result, all
these features are enabled with the ``-std=C++14`` or ``-std=gnu++14`` option
when compiling C++ code.
C++1y binary literals
C++14 binary literals
^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_binary_literals)`` or
@ -795,37 +795,37 @@ Use ``__has_feature(cxx_binary_literals)`` or
binary literals (for instance, ``0b10010``) are recognized. Clang supports this
feature as an extension in all language modes.
C++1y contextual conversions
C++14 contextual conversions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_contextual_conversions)`` or
``__has_extension(cxx_contextual_conversions)`` to determine if the C++1y rules
``__has_extension(cxx_contextual_conversions)`` to determine if the C++14 rules
are used when performing an implicit conversion for an array bound in a
*new-expression*, the operand of a *delete-expression*, an integral constant
expression, or a condition in a ``switch`` statement.
C++1y decltype(auto)
C++14 decltype(auto)
^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_decltype_auto)`` or
``__has_extension(cxx_decltype_auto)`` to determine if support
for the ``decltype(auto)`` placeholder type is enabled.
C++1y default initializers for aggregates
C++14 default initializers for aggregates
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_aggregate_nsdmi)`` or
``__has_extension(cxx_aggregate_nsdmi)`` to determine if support
for default initializers in aggregate members is enabled.
C++1y digit separators
C++14 digit separators
^^^^^^^^^^^^^^^^^^^^^^
Use ``__cpp_digit_separators`` to determine if support for digit separators
using single quotes (for instance, ``10'000``) is enabled. At this time, there
is no corresponding ``__has_feature`` name
C++1y generalized lambda capture
C++14 generalized lambda capture
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_init_captures)`` or
@ -833,7 +833,7 @@ Use ``__has_feature(cxx_init_captures)`` or
lambda captures with explicit initializers is enabled
(for instance, ``[n(0)] { return ++n; }``).
C++1y generic lambdas
C++14 generic lambdas
^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_generic_lambdas)`` or
@ -841,7 +841,7 @@ Use ``__has_feature(cxx_generic_lambdas)`` or
(polymorphic) lambdas is enabled
(for instance, ``[] (auto x) { return x + 1; }``).
C++1y relaxed constexpr
C++14 relaxed constexpr
^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_relaxed_constexpr)`` or
@ -849,7 +849,7 @@ Use ``__has_feature(cxx_relaxed_constexpr)`` or
declarations, local variable modification, and control flow constructs
are permitted in ``constexpr`` functions.
C++1y return type deduction
C++14 return type deduction
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_return_type_deduction)`` or
@ -857,7 +857,7 @@ Use ``__has_feature(cxx_return_type_deduction)`` or
for return type deduction for functions (using ``auto`` as a return type)
is enabled.
C++1y runtime-sized arrays
C++14 runtime-sized arrays
^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_runtime_array)`` or
@ -866,7 +866,7 @@ for arrays of runtime bound (a restricted form of variable-length arrays)
is enabled.
Clang's implementation of this feature is incomplete.
C++1y variable templates
C++14 variable templates
^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_variable_templates)`` or
@ -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)
@ -1270,6 +1271,87 @@ Further examples of these attributes are available in the static analyzer's `lis
Query for these features with ``__has_attribute(ns_consumed)``,
``__has_attribute(ns_returns_retained)``, etc.
Objective-C @available
----------------------
It is possible to use the newest SDK but still build a program that can run on
older versions of macOS and iOS by passing ``-mmacosx-version-min=`` /
``-miphoneos-version-min=``.
Before LLVM 5.0, when calling a function that exists only in the OS that's
newer than the target OS (as determined by the minimum deployment version),
programmers had to carefully check if the function exists at runtime, using
null checks for weakly-linked C functions, ``+class`` for Objective-C classes,
and ``-respondsToSelector:`` or ``+instancesRespondToSelector:`` for
Objective-C methods. If such a check was missed, the program would compile
fine, run fine on newer systems, but crash on older systems.
As of LLVM 5.0, ``-Wunguarded-availability`` uses the `availability attributes
<http://clang.llvm.org/docs/AttributeReference.html#availability>`_ together
with the new ``@available()`` keyword to assist with this issue.
When a method that's introduced in the OS newer than the target OS is called, a
-Wunguarded-availability warning is emitted if that call is not guarded:
.. code-block:: objc
void my_fun(NSSomeClass* var) {
// If fancyNewMethod was added in e.g. macOS 10.12, but the code is
// built with -mmacosx-version-min=10.11, then this unconditional call
// will emit a -Wunguarded-availability warning:
[var fancyNewMethod];
}
To fix the warning and to avoid the crash on macOS 10.11, wrap it in
``if(@available())``:
.. code-block:: objc
void my_fun(NSSomeClass* var) {
if (@available(macOS 10.12, *)) {
[var fancyNewMethod];
} else {
// Put fallback behavior for old macOS versions (and for non-mac
// platforms) here.
}
}
The ``*`` is required and means that platforms not explicitly listed will take
the true branch, and the compiler will emit ``-Wunguarded-availability``
warnings for unlisted platforms based on those platform's deployment target.
More than one platform can be listed in ``@available()``:
.. code-block:: objc
void my_fun(NSSomeClass* var) {
if (@available(macOS 10.12, iOS 10, *)) {
[var fancyNewMethod];
}
}
If the caller of ``my_fun()`` already checks that ``my_fun()`` is only called
on 10.12, then add an `availability attribute
<http://clang.llvm.org/docs/AttributeReference.html#availability>`_ to it,
which will also suppress the warning and require that calls to my_fun() are
checked:
.. code-block:: objc
API_AVAILABLE(macos(10.12)) void my_fun(NSSomeClass* var) {
[var fancyNewMethod]; // Now ok.
}
``@available()`` is only available in Objective-C code. To use the feature
in C and C++ code, use the ``__builtin_available()`` spelling instead.
If existing code uses null checks or ``-respondsToSelector:``, it should
be changed to use ``@available()`` (or ``__builtin_available``) instead.
``-Wunguarded-availability`` is disabled by default, but
``-Wunguarded-availability-new``, which only emits this warning for APIs
that have been introduced in macOS >= 10.13, iOS >= 11, watchOS >= 4 and
tvOS >= 11, is enabled by default.
.. _langext-overloading:
Objective-C++ ABI: protocol-qualifier mangling of parameters
------------------------------------------------------------
@ -1286,8 +1368,6 @@ parameters of protocol-qualified type.
Query the presence of this new mangling with
``__has_feature(objc_protocol_qualifier_mangling)``.
.. _langext-overloading:
Initializer lists for complex numbers in C
==========================================
@ -1780,7 +1860,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 +2392,253 @@ 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.
Specifying an attribute for multiple declarations (#pragma clang attribute)
===========================================================================
The ``#pragma clang attribute`` directive can be used to apply an attribute to
multiple declarations. The ``#pragma clang attribute push`` variation of the
directive pushes a new attribute to the attribute stack. The declarations that
follow the pragma receive the attributes that are on the attribute stack, until
the stack is cleared using a ``#pragma clang attribute pop`` directive. Multiple
push directives can be nested inside each other.
The attributes that are used in the ``#pragma clang attribute`` directives
can be written using the GNU-style syntax:
.. code-block:: c++
#pragma clang attribute push(__attribute__((annotate("custom"))), apply_to = function)
void function(); // The function now has the annotate("custom") attribute
#pragma clang attribute pop
The attributes can also be written using the C++11 style syntax:
.. code-block:: c++
#pragma clang attribute push([[noreturn]], apply_to = function)
void function(); // The function now has the [[noreturn]] attribute
#pragma clang attribute pop
The ``__declspec`` style syntax is also supported:
.. code-block:: c++
#pragma clang attribute push(__declspec(dllexport), apply_to = function)
void function(); // The function now has the __declspec(dllexport) attribute
#pragma clang attribute pop
A single push directive accepts only one attribute regardless of the syntax
used.
Subject Match Rules
-------------------
The set of declarations that receive a single attribute from the attribute stack
depends on the subject match rules that were specified in the pragma. Subject
match rules are specified after the attribute. The compiler expects an
identifier that corresponds to the subject set specifier. The ``apply_to``
specifier is currently the only supported subject set specifier. It allows you
to specify match rules that form a subset of the attribute's allowed subject
set, i.e. the compiler doesn't require all of the attribute's subjects. For
example, an attribute like ``[[nodiscard]]`` whose subject set includes
``enum``, ``record`` and ``hasType(functionType)``, requires the presence of at
least one of these rules after ``apply_to``:
.. code-block:: c++
#pragma clang attribute push([[nodiscard]], apply_to = enum)
enum Enum1 { A1, B1 }; // The enum will receive [[nodiscard]]
struct Record1 { }; // The struct will *not* receive [[nodiscard]]
#pragma clang attribute pop
#pragma clang attribute push([[nodiscard]], apply_to = any(record, enum))
enum Enum2 { A2, B2 }; // The enum will receive [[nodiscard]]
struct Record2 { }; // The struct *will* receive [[nodiscard]]
#pragma clang attribute pop
// This is an error, since [[nodiscard]] can't be applied to namespaces:
#pragma clang attribute push([[nodiscard]], apply_to = any(record, namespace))
#pragma clang attribute pop
Multiple match rules can be specified using the ``any`` match rule, as shown
in the example above. The ``any`` rule applies attributes to all declarations
that are matched by at least one of the rules in the ``any``. It doesn't nest
and can't be used inside the other match rules. Redundant match rules or rules
that conflict with one another should not be used inside of ``any``.
Clang supports the following match rules:
- ``function``: Can be used to apply attributes to functions. This includes C++
member functions, static functions, operators, and constructors/destructors.
- ``function(is_member)``: Can be used to apply attributes to C++ member
functions. This includes members like static functions, operators, and
constructors/destructors.
- ``hasType(functionType)``: Can be used to apply attributes to functions, C++
member functions, and variables/fields whose type is a function pointer. It
does not apply attributes to Objective-C methods or blocks.
- ``type_alias``: Can be used to apply attributes to ``typedef`` declarations
and C++11 type aliases.
- ``record``: Can be used to apply attributes to ``struct``, ``class``, and
``union`` declarations.
- ``record(unless(is_union))``: Can be used to apply attributes only to
``struct`` and ``class`` declarations.
- ``enum``: Can be be used to apply attributes to enumeration declarations.
- ``enum_constant``: Can be used to apply attributes to enumerators.
- ``variable``: Can be used to apply attributes to variables, including
local variables, parameters, global variables, and static member variables.
It does not apply attributes to instance member variables or Objective-C
ivars.
- ``variable(is_thread_local)``: Can be used to apply attributes to thread-local
variables only.
- ``variable(is_global)``: Can be used to apply attributes to global variables
only.
- ``variable(is_parameter)``: Can be used to apply attributes to parameters
only.
- ``variable(unless(is_parameter))``: Can be used to apply attributes to all
the variables that are not parameters.
- ``field``: Can be used to apply attributes to non-static member variables
in a record. This includes Objective-C ivars.
- ``namespace``: Can be used to apply attributes to ``namespace`` declarations.
- ``objc_interface``: Can be used to apply attributes to ``@interface``
declarations.
- ``objc_protocol``: Can be used to apply attributes to ``@protocol``
declarations.
- ``objc_category``: Can be used to apply attributes to category declarations,
including class extensions.
- ``objc_method``: Can be used to apply attributes to Objective-C methods,
including instance and class methods. Implicit methods like implicit property
getters and setters do not receive the attribute.
- ``objc_method(is_instance)``: Can be used to apply attributes to Objective-C
instance methods.
- ``objc_property``: Can be used to apply attributes to ``@property``
declarations.
- ``block``: Can be used to apply attributes to block declarations. This does
not include variables/fields of block pointer type.
The use of ``unless`` in match rules is currently restricted to a strict set of
sub-rules that are used by the supported attributes. That means that even though
``variable(unless(is_parameter))`` is a valid match rule,
``variable(unless(is_thread_local))`` is not.
Supported Attributes
--------------------
Not all attributes can be used with the ``#pragma clang attribute`` directive.
Notably, statement attributes like ``[[fallthrough]]`` or type attributes
like ``address_space`` aren't supported by this directive. You can determine
whether or not an attribute is supported by the pragma by referring to the
:doc:`individual documentation for that attribute <AttributeReference>`.
The attributes are applied to all matching declarations individually, even when
the attribute is semantically incorrect. The attributes that aren't applied to
any declaration are not verified semantically.
Specifying section names for global objects (#pragma clang section)
===================================================================
The ``#pragma clang section`` directive provides a means to assign section-names
to global variables, functions and static variables.
The section names can be specified as:
.. code-block:: c++
#pragma clang section bss="myBSS" data="myData" rodata="myRodata" text="myText"
The section names can be reverted back to default name by supplying an empty
string to the section kind, for example:
.. code-block:: c++
#pragma clang section bss="" data="" text="" rodata=""
The ``#pragma clang section`` directive obeys the following rules:
* The pragma applies to all global variable, statics and function declarations
from the pragma to the end of the translation unit.
* The pragma clang section is enabled automatically, without need of any flags.
* This feature is only defined to work sensibly for ELF targets.
* If section name is specified through _attribute_((section("myname"))), then
the attribute name gains precedence.
* Global variables that are initialized to zero will be placed in the named
bss section, if one is present.
* The ``#pragma clang section`` directive does not does try to infer section-kind
from the name. For example, naming a section "``.bss.mySec``" does NOT mean
it will be a bss section name.
* The decision about which section-kind applies to each global is taken in the back-end.
Once the section-kind is known, appropriate section name, as specified by the user using
``#pragma clang section`` directive, is applied to that global.

View File

@ -337,6 +337,15 @@ nonTypeTemplateParmDecl()
</pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('objcCategoryDecl0')"><a name="objcCategoryDecl0Anchor">objcCategoryDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCCategoryDecl.html">ObjCCategoryDecl</a>&gt;...</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&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('objcInterfaceDecl0')"><a name="objcInterfaceDecl0Anchor">objcInterfaceDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCInterfaceDecl.html">ObjCInterfaceDecl</a>&gt;...</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&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('objcIvarDecl0')"><a name="objcIvarDecl0Anchor">objcIvarDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCIvarDecl.html">ObjCIvarDecl</a>&gt;...</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&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('objcMethodDecl0')"><a name="objcMethodDecl0Anchor">objcMethodDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>&gt;...</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&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('objcPropertyDecl0')"><a name="objcPropertyDecl0Anchor">objcPropertyDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCPropertyDecl.html">ObjCPropertyDecl</a>&gt;...</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&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('objcProtocolDecl0')"><a name="objcProtocolDecl0Anchor">objcProtocolDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCProtocolDecl.html">ObjCProtocolDecl</a>&gt;...</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&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('parmVarDecl0')"><a name="parmVarDecl0Anchor">parmVarDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt;...</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&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('typeAliasTemplateDecl0')"><a name="typeAliasTemplateDecl0Anchor">typeAliasTemplateDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeAliasTemplateDecl.html">TypeAliasTemplateDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="typeAliasTemplateDecl0"><pre>Matches type alias template declarations.
typeAliasTemplateDecl() matches
template &lt;typename T&gt;
using Y = X&lt;T&gt;;
</pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('typedefDecl0')"><a name="typedefDecl0Anchor">typedefDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefDecl.html">TypedefDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="typedefDecl0"><pre>Matches typedef declarations.
@ -862,6 +924,19 @@ in
</pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxStdInitializerListExpr0')"><a name="cxxStdInitializerListExpr0Anchor">cxxStdInitializerListExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXStdInitializerListExpr.html">CXXStdInitializerListExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxStdInitializerListExpr0"><pre>Matches C++ initializer list expressions.
Given
std::vector&lt;int&gt; a({ 1, 2, 3 });
std::vector&lt;int&gt; b = { 4, 5 };
int c[] = { 6, 7 };
std::pair&lt;int, int&gt; d = { 8, 9 };
cxxStdInitializerListExpr()
matches "{ 1, 2, 3 }" and "{ 4, 5 }"
</pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxTemporaryObjectExpr0')"><a name="cxxTemporaryObjectExpr0Anchor">cxxTemporaryObjectExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXTemporaryObjectExpr.html">CXXTemporaryObjectExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxTemporaryObjectExpr0"><pre>Matches functional cast expressions having N != 1 arguments
@ -1098,7 +1173,7 @@ Example matches [&amp;](){return 5;}
<tr><td colspan="4" class="doc" id="materializeTemporaryExpr0"><pre>Matches nodes where temporaries are materialized.
Example: Given
struct T {void func()};
struct T {void func();};
T f();
void g(T);
materializeTemporaryExpr() matches 'f()' in these statements
@ -1784,17 +1859,44 @@ Example matches a || b (matcher = binaryOperator(hasOperatorName("||")))
</pre></td></tr>
<tr><td>Matcher&lt;CXXBoolLiteral&gt;</td><td class="name" onclick="toggle('equals2')"><a name="equals2Anchor">equals</a></td><td>ValueT Value</td></tr>
<tr><td colspan="4" class="doc" id="equals2"><pre>Matches literals that are equal to the given value.
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;</td><td class="name" onclick="toggle('equals2')"><a name="equals2Anchor">equals</a></td><td>ValueT Value</td></tr>
<tr><td colspan="4" class="doc" id="equals2"><pre>Matches literals that are equal to the given value of type ValueT.
Example matches true (matcher = cxxBoolLiteral(equals(true)))
true
Given
f('false, 3.14, 42);
characterLiteral(equals(0))
matches 'cxxBoolLiteral(equals(false)) and cxxBoolLiteral(equals(0))
match false
floatLiteral(equals(3.14)) and floatLiteral(equals(314e-2))
match 3.14
integerLiteral(equals(42))
matches 42
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;, Matcher&lt;CXXBoolLiteral&gt;,
Note that you cannot directly match a negative numeric literal because the
minus sign is not part of the literal: It is a unary operator whose operand
is the positive numeric literal. Instead, you must use a unaryOperator()
matcher to match the minus sign:
unaryOperator(hasOperatorName("-"),
hasUnaryOperand(integerLiteral(equals(13))))
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;,
Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;
</pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;</td><td class="name" onclick="toggle('equals5')"><a name="equals5Anchor">equals</a></td><td>bool Value</td></tr>
<tr><td colspan="4" class="doc" id="equals5"><pre></pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;</td><td class="name" onclick="toggle('equals11')"><a name="equals11Anchor">equals</a></td><td>double Value</td></tr>
<tr><td colspan="4" class="doc" id="equals11"><pre></pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;</td><td class="name" onclick="toggle('equals8')"><a name="equals8Anchor">equals</a></td><td>unsigned Value</td></tr>
<tr><td colspan="4" class="doc" id="equals8"><pre></pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXCatchStmt.html">CXXCatchStmt</a>&gt;</td><td class="name" onclick="toggle('isCatchAll0')"><a name="isCatchAll0Anchor">isCatchAll</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isCatchAll0"><pre>Matches a C++ catch statement that has a catch-all handler.
@ -2221,16 +2323,43 @@ Example: matches the implicit cast around 0
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;</td><td class="name" onclick="toggle('equals3')"><a name="equals3Anchor">equals</a></td><td>ValueT Value</td></tr>
<tr><td colspan="4" class="doc" id="equals3"><pre>Matches literals that are equal to the given value.
<tr><td colspan="4" class="doc" id="equals3"><pre>Matches literals that are equal to the given value of type ValueT.
Example matches true (matcher = cxxBoolLiteral(equals(true)))
true
Given
f('false, 3.14, 42);
characterLiteral(equals(0))
matches 'cxxBoolLiteral(equals(false)) and cxxBoolLiteral(equals(0))
match false
floatLiteral(equals(3.14)) and floatLiteral(equals(314e-2))
match 3.14
integerLiteral(equals(42))
matches 42
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;, Matcher&lt;CXXBoolLiteral&gt;,
Note that you cannot directly match a negative numeric literal because the
minus sign is not part of the literal: It is a unary operator whose operand
is the positive numeric literal. Instead, you must use a unaryOperator()
matcher to match the minus sign:
unaryOperator(hasOperatorName("-"),
hasUnaryOperand(integerLiteral(equals(13))))
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;,
Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;
</pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;</td><td class="name" onclick="toggle('equals4')"><a name="equals4Anchor">equals</a></td><td>bool Value</td></tr>
<tr><td colspan="4" class="doc" id="equals4"><pre></pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;</td><td class="name" onclick="toggle('equals10')"><a name="equals10Anchor">equals</a></td><td>double Value</td></tr>
<tr><td colspan="4" class="doc" id="equals10"><pre></pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;</td><td class="name" onclick="toggle('equals7')"><a name="equals7Anchor">equals</a></td><td>unsigned Value</td></tr>
<tr><td colspan="4" class="doc" id="equals7"><pre></pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>&gt;</td><td class="name" onclick="toggle('templateArgumentCountIs0')"><a name="templateArgumentCountIs0Anchor">templateArgumentCountIs</a></td><td>unsigned N</td></tr>
<tr><td colspan="4" class="doc" id="templateArgumentCountIs0"><pre>Matches if the number of template arguments equals N.
@ -2458,16 +2587,35 @@ fieldDecl(isBitField())
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>&gt;</td><td class="name" onclick="toggle('equals1')"><a name="equals1Anchor">equals</a></td><td>ValueT Value</td></tr>
<tr><td colspan="4" class="doc" id="equals1"><pre>Matches literals that are equal to the given value.
<tr><td colspan="4" class="doc" id="equals1"><pre>Matches literals that are equal to the given value of type ValueT.
Example matches true (matcher = cxxBoolLiteral(equals(true)))
true
Given
f('false, 3.14, 42);
characterLiteral(equals(0))
matches 'cxxBoolLiteral(equals(false)) and cxxBoolLiteral(equals(0))
match false
floatLiteral(equals(3.14)) and floatLiteral(equals(314e-2))
match 3.14
integerLiteral(equals(42))
matches 42
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;, Matcher&lt;CXXBoolLiteral&gt;,
Note that you cannot directly match a negative numeric literal because the
minus sign is not part of the literal: It is a unary operator whose operand
is the positive numeric literal. Instead, you must use a unaryOperator()
matcher to match the minus sign:
unaryOperator(hasOperatorName("-"),
hasUnaryOperand(integerLiteral(equals(13))))
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;,
Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;
</pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>&gt;</td><td class="name" onclick="toggle('equals12')"><a name="equals12Anchor">equals</a></td><td>double Value</td></tr>
<tr><td colspan="4" class="doc" id="equals12"><pre></pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasDynamicExceptionSpec0')"><a name="hasDynamicExceptionSpec0Anchor">hasDynamicExceptionSpec</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasDynamicExceptionSpec0"><pre>Matches functions that have a dynamic exception specification.
@ -2730,16 +2878,43 @@ functionProtoType(parameterCountIs(3))
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;</td><td class="name" onclick="toggle('equals0')"><a name="equals0Anchor">equals</a></td><td>ValueT Value</td></tr>
<tr><td colspan="4" class="doc" id="equals0"><pre>Matches literals that are equal to the given value.
<tr><td colspan="4" class="doc" id="equals0"><pre>Matches literals that are equal to the given value of type ValueT.
Example matches true (matcher = cxxBoolLiteral(equals(true)))
true
Given
f('false, 3.14, 42);
characterLiteral(equals(0))
matches 'cxxBoolLiteral(equals(false)) and cxxBoolLiteral(equals(0))
match false
floatLiteral(equals(3.14)) and floatLiteral(equals(314e-2))
match 3.14
integerLiteral(equals(42))
matches 42
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;, Matcher&lt;CXXBoolLiteral&gt;,
Note that you cannot directly match a negative numeric literal because the
minus sign is not part of the literal: It is a unary operator whose operand
is the positive numeric literal. Instead, you must use a unaryOperator()
matcher to match the minus sign:
unaryOperator(hasOperatorName("-"),
hasUnaryOperand(integerLiteral(equals(13))))
Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;,
Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;
</pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;</td><td class="name" onclick="toggle('equals6')"><a name="equals6Anchor">equals</a></td><td>bool Value</td></tr>
<tr><td colspan="4" class="doc" id="equals6"><pre></pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;</td><td class="name" onclick="toggle('equals13')"><a name="equals13Anchor">equals</a></td><td>double Value</td></tr>
<tr><td colspan="4" class="doc" id="equals13"><pre></pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;</td><td class="name" onclick="toggle('equals9')"><a name="equals9Anchor">equals</a></td><td>unsigned Value</td></tr>
<tr><td colspan="4" class="doc" id="equals9"><pre></pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;</td><td class="name" onclick="toggle('isArrow0')"><a name="isArrow0Anchor">isArrow</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isArrow0"><pre>Matches member expressions that are called with '-&gt;' as opposed
to '.'.
@ -5171,7 +5346,7 @@ Example matches y in x(y)
<tr><td colspan="4" class="doc" id="hasReceiverType0"><pre>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.
NSString *webViewJavaScript = ...
UIWebView *webView = ...
@ -5419,7 +5594,7 @@ alignof.
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('forFunction0')"><a name="forFunction0Anchor">forFunction</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt; 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&amp; operator=(const F&amp; o) {

View File

@ -28,7 +28,9 @@ The core routine of LibFormat is ``reformat()``:
This reads a token stream out of the lexer ``Lex`` and reformats all the code
ranges in ``Ranges``. The ``FormatStyle`` controls basic decisions made during
formatting. A list of options can be found under :ref:`style-options`.
formatting. A list of options can be found under :ref:`style-options`.
The style options are described in :doc:`ClangFormatStyleOptions`.
.. _style-options:

View File

@ -27,7 +27,7 @@ executable, so make sure to use ``clang`` (not ``ld``) for the final
link step. When linking shared libraries, the MemorySanitizer run-time
is not linked, so ``-Wl,-z,defs`` may cause link errors (don't use it
with MemorySanitizer). To get a reasonable performance add ``-O1`` or
higher. To get meaninful stack traces in error messages add
higher. To get meaningful stack traces in error messages add
``-fno-omit-frame-pointer``. To get perfect stack traces you may need
to disable inlining (just use ``-O1``) and tail call elimination
(``-fno-optimize-sibling-calls``).

View File

@ -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
@ -402,7 +403,7 @@ A *requires-declaration* specifies the requirements that an importing translatio
*feature*:
``!``:sub:`opt` *identifier*
The requirements clause allows specific modules or submodules to specify that they are only accessible with certain language dialects or on certain platforms. The feature list is a set of identifiers, defined below. If any of the features is not available in a given translation unit, that translation unit shall not import the module. The optional ``!`` indicates that a feature is incompatible with the module.
The requirements clause allows specific modules or submodules to specify that they are only accessible with certain language dialects or on certain platforms. The feature list is a set of identifiers, defined below. If any of the features is not available in a given translation unit, that translation unit shall not import the module. When building a module for use by a compilation, submodules requiring unavailable features are ignored. The optional ``!`` indicates that a feature is incompatible with the module.
The following features are defined:
@ -412,6 +413,9 @@ altivec
blocks
The "blocks" language feature is available.
coroutines
Support for the coroutines TS is available.
cplusplus
C++ support is available.
@ -465,9 +469,16 @@ A header declaration specifies that a particular header is associated with the e
.. parsed-literal::
*header-declaration*:
``private``:sub:`opt` ``textual``:sub:`opt` ``header`` *string-literal*
``umbrella`` ``header`` *string-literal*
``exclude`` ``header`` *string-literal*
``private``:sub:`opt` ``textual``:sub:`opt` ``header`` *string-literal* *header-attrs*:sub:`opt`
``umbrella`` ``header`` *string-literal* *header-attrs*:sub:`opt`
``exclude`` ``header`` *string-literal* *header-attrs*:sub:`opt`
*header-attrs*:
'{' *header-attr** '}'
*header-attr*:
``size`` *integer-literal*
``mtime`` *integer-literal*
A header declaration that does not contain ``exclude`` nor ``textual`` specifies a header that contributes to the enclosing module. Specifically, when the module is built, the named header will be parsed and its declarations will be (logically) placed into the enclosing submodule.
@ -500,6 +511,18 @@ A header with the ``exclude`` specifier is excluded from the module. It will not
A given header shall not be referenced by more than one *header-declaration*.
Two *header-declaration*\s, or a *header-declaration* and a ``#include``, are
considered to refer to the same file if the paths resolve to the same file
and the specified *header-attr*\s (if any) match the attributes of that file,
even if the file is named differently (for instance, by a relative path or
via symlinks).
.. note::
The use of *header-attr*\s avoids the need for Clang to speculatively
``stat`` every header referenced by a module map. It is recommended that
*header-attr*\s only be used in machine-generated module maps, to avoid
mismatches between attribute values and the corresponding files.
Umbrella directory declaration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
An umbrella directory declaration specifies that all of the headers in the specified directory should be included within the module.
@ -842,6 +865,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).

View File

@ -1,5 +1,5 @@
=======================================
Clang 4.0.0 (In-Progress) Release Notes
Clang 5.0.0 (In-Progress) Release Notes
=======================================
.. contents::
@ -10,15 +10,15 @@ Written by the `LLVM Team <http://llvm.org/>`_
.. warning::
These are in-progress notes for the upcoming Clang 4.0.0 release. You may
prefer the `Clang 3.9 Release Notes
<http://llvm.org/releases/3.9.0/tools/clang/docs/ReleaseNotes.html>`_.
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
frontend, part of the LLVM Compiler Infrastructure, release 4.0.0. Here we
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
@ -31,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
@ -42,56 +47,32 @@ sections with improvements to Clang's support for those languages.
Major New Features
------------------
- The ``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:
.. 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).
Improvements to Clang's diagnostics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- ...
- -Wcast-qual was implemented for C++. C-style casts are now properly
diagnosed.
- -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 -MJ has been added to simplify adding JSON compilation
database output into existing build systems.
The option ....
Deprecated Compiler Flags
-------------------------
The following options are deprecated and ignored. They will be removed in
future versions of Clang.
- -fslp-vectorize-aggressive used to enable the BB vectorizing pass. They have been superseeded
by the normal SLP vectorizer.
- -fno-slp-vectorize-aggressive used to be the default behavior of clang.
New Pragmas in Clang
-----------------------
@ -101,7 +82,9 @@ Clang now supports the ...
Attribute Changes in Clang
--------------------------
- ...
- The ``overloadable`` attribute now allows at most one function with a given
name to lack the ``overloadable`` attribute. This unmarked function will not
have its name mangled.
Windows Support
---------------
@ -149,7 +132,7 @@ OpenMP Support in Clang
Internal API Changes
--------------------
These are major API changes that have happened since the 3.9 release of
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.
@ -160,20 +143,90 @@ AST Matchers
...
clang-format
------------
* Option **BreakBeforeInheritanceComma** added to break before ``:`` and ``,`` in case of
multiple inheritance in a class declaration. Enabled by default in the Mozilla coding style.
+---------------------+----------------------------------------+
| true | false |
+=====================+========================================+
| .. code-block:: c++ | .. code-block:: c++ |
| | |
| class MyClass | class MyClass : public X, public Y { |
| : public X | }; |
| , public Y { | |
| }; | |
+---------------------+----------------------------------------+
* Align block comment decorations.
+----------------------+---------------------+
| Before | After |
+======================+=====================+
| .. code-block:: c++ | .. code-block:: c++ |
| | |
| /* line 1 | /* line 1 |
| * line 2 | * line 2 |
| */ | */ |
+----------------------+---------------------+
* The :doc:`ClangFormatStyleOptions` documentation provides detailed examples for most options.
* Namespace end comments are now added or updated automatically.
+---------------------+---------------------+
| Before | After |
+=====================+=====================+
| .. code-block:: c++ | .. code-block:: c++ |
| | |
| namespace A { | namespace A { |
| int i; | int i; |
| int j; | int j; |
| } | } |
+---------------------+---------------------+
* 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
--------
...
With the option --show-description, scan-build's list of defects will also
show the description of the defects.
Static Analyzer
---------------
...
Undefined Behavior Sanitizer (UBSan)
------------------------------------
- The Undefined Behavior Sanitizer has a new check for pointer overflow. This
check is on by default. The flag to control this functionality is
-fsanitize=pointer-overflow.
Pointer overflow is an indicator of undefined behavior: when a pointer
indexing expression wraps around the address space, or produces other
unexpected results, its result may not point to a valid object.
- UBSan has several new checks which detect violations of nullability
annotations. These checks are off by default. The flag to control this group
of checks is -fsanitize=nullability. The checks can be individially enabled
by -fsanitize=nullability-arg (which checks calls),
-fsanitize=nullability-assign (which checks assignments), and
-fsanitize=nullability-return (which checks return statements).
- UBSan can now detect invalid loads from bitfields and from ObjC BOOLs.
- UBSan can now avoid emitting unnecessary type checks in C++ class methods and
in several other cases where the result is known at compile-time. UBSan can
also avoid emitting unnecessary overflow checks in arithmetic expressions
with promoted integer operands.
Core Analysis Improvements
==========================

View File

@ -8,351 +8,35 @@ SanitizerCoverage
Introduction
============
Sanitizer tools have a very simple code coverage tool built in. It allows to
get function-level, basic-block-level, and edge-level coverage at a very low
cost.
How to build and run
====================
SanitizerCoverage can be used with :doc:`AddressSanitizer`,
:doc:`LeakSanitizer`, :doc:`MemorySanitizer`,
UndefinedBehaviorSanitizer, or without any sanitizer. Pass one of the
following compile-time flags:
* ``-fsanitize-coverage=func`` for function-level coverage (very fast).
* ``-fsanitize-coverage=bb`` for basic-block-level coverage (may add up to 30%
**extra** slowdown).
* ``-fsanitize-coverage=edge`` for edge-level coverage (up to 40% slowdown).
You may also specify ``-fsanitize-coverage=indirect-calls`` for
additional `caller-callee coverage`_.
At run time, pass ``coverage=1`` in ``ASAN_OPTIONS``,
``LSAN_OPTIONS``, ``MSAN_OPTIONS`` or ``UBSAN_OPTIONS``, as
appropriate. For the standalone coverage mode, use ``UBSAN_OPTIONS``.
To get `Coverage counters`_, add ``-fsanitize-coverage=8bit-counters``
to one of the above compile-time flags. At runtime, use
``*SAN_OPTIONS=coverage=1:coverage_counters=1``.
Example:
.. code-block:: console
% cat -n cov.cc
1 #include <stdio.h>
2 __attribute__((noinline))
3 void foo() { printf("foo\n"); }
4
5 int main(int argc, char **argv) {
6 if (argc == 2)
7 foo();
8 printf("main\n");
9 }
% clang++ -g cov.cc -fsanitize=address -fsanitize-coverage=func
% ASAN_OPTIONS=coverage=1 ./a.out; ls -l *sancov
main
-rw-r----- 1 kcc eng 4 Nov 27 12:21 a.out.22673.sancov
% ASAN_OPTIONS=coverage=1 ./a.out foo ; ls -l *sancov
foo
main
-rw-r----- 1 kcc eng 4 Nov 27 12:21 a.out.22673.sancov
-rw-r----- 1 kcc eng 8 Nov 27 12:21 a.out.22679.sancov
Every time you run an executable instrumented with SanitizerCoverage
one ``*.sancov`` file is created during the process shutdown.
If the executable is dynamically linked against instrumented DSOs,
one ``*.sancov`` file will be also created for every DSO.
Postprocessing
==============
The format of ``*.sancov`` files is very simple: the first 8 bytes is the magic,
one of ``0xC0BFFFFFFFFFFF64`` and ``0xC0BFFFFFFFFFFF32``. The last byte of the
magic defines the size of the following offsets. The rest of the data is the
offsets in the corresponding binary/DSO that were executed during the run.
A simple script
``$LLVM/projects/compiler-rt/lib/sanitizer_common/scripts/sancov.py`` is
provided to dump these offsets.
.. code-block:: console
% sancov.py print a.out.22679.sancov a.out.22673.sancov
sancov.py: read 2 PCs from a.out.22679.sancov
sancov.py: read 1 PCs from a.out.22673.sancov
sancov.py: 2 files merged; 2 PCs total
0x465250
0x4652a0
You can then filter the output of ``sancov.py`` through ``addr2line --exe
ObjectFile`` or ``llvm-symbolizer --obj ObjectFile`` to get file names and line
numbers:
.. code-block:: console
% sancov.py print a.out.22679.sancov a.out.22673.sancov 2> /dev/null | llvm-symbolizer --obj a.out
cov.cc:3
cov.cc:5
Sancov Tool
===========
A new experimental ``sancov`` tool is developed to process coverage files.
The tool is part of LLVM project and is currently supported only on Linux.
It can handle symbolization tasks autonomously without any extra support
from the environment. You need to pass .sancov files (named
``<module_name>.<pid>.sancov`` and paths to all corresponding binary elf files.
Sancov matches these files using module names and binaries file names.
.. code-block:: console
USAGE: sancov [options] <action> (<binary file>|<.sancov file>)...
Action (required)
-print - Print coverage addresses
-covered-functions - Print all covered functions.
-not-covered-functions - Print all not covered functions.
-symbolize - Symbolizes the report.
Options
-blacklist=<string> - Blacklist file (sanitizer blacklist format).
-demangle - Print demangled function name.
-strip_path_prefix=<string> - Strip this prefix from file paths in reports
Coverage Reports (Experimental)
================================
``.sancov`` files do not contain enough information to generate a source-level
coverage report. The missing information is contained
in debug info of the binary. Thus the ``.sancov`` has to be symbolized
to produce a ``.symcov`` file first:
.. code-block:: console
sancov -symbolize my_program.123.sancov my_program > my_program.123.symcov
The ``.symcov`` file can be browsed overlayed over the source code by
running ``tools/sancov/coverage-report-server.py`` script that will start
an HTTP server.
How good is the coverage?
=========================
It is possible to find out which PCs are not covered, by subtracting the covered
set from the set of all instrumented PCs. The latter can be obtained by listing
all callsites of ``__sanitizer_cov()`` in the binary. On Linux, ``sancov.py``
can do this for you. Just supply the path to binary and a list of covered PCs:
.. code-block:: console
% sancov.py print a.out.12345.sancov > covered.txt
sancov.py: read 2 64-bit PCs from a.out.12345.sancov
sancov.py: 1 file merged; 2 PCs total
% sancov.py missing a.out < covered.txt
sancov.py: found 3 instrumented PCs in a.out
sancov.py: read 2 PCs from stdin
sancov.py: 1 PCs missing from coverage
0x4cc61c
Edge coverage
=============
Consider this code:
.. code-block:: c++
void foo(int *a) {
if (a)
*a = 0;
}
It contains 3 basic blocks, let's name them A, B, C:
.. code-block:: none
A
|\
| \
| B
| /
|/
C
If blocks A, B, and C are all covered we know for certain that the edges A=>B
and B=>C were executed, but we still don't know if the edge A=>C was executed.
Such edges of control flow graph are called
`critical <http://en.wikipedia.org/wiki/Control_flow_graph#Special_edges>`_. The
edge-level coverage (``-fsanitize-coverage=edge``) simply splits all critical
edges by introducing new dummy blocks and then instruments those blocks:
.. code-block:: none
A
|\
| \
D B
| /
|/
C
Bitset
======
When ``coverage_bitset=1`` run-time flag is given, the coverage will also be
dumped as a bitset (text file with 1 for blocks that have been executed and 0
for blocks that were not).
.. code-block:: console
% clang++ -fsanitize=address -fsanitize-coverage=edge cov.cc
% ASAN_OPTIONS="coverage=1:coverage_bitset=1" ./a.out
main
% ASAN_OPTIONS="coverage=1:coverage_bitset=1" ./a.out 1
foo
main
% head *bitset*
==> a.out.38214.bitset-sancov <==
01101
==> a.out.6128.bitset-sancov <==
11011%
For a given executable the length of the bitset is always the same (well,
unless dlopen/dlclose come into play), so the bitset coverage can be
easily used for bitset-based corpus distillation.
Caller-callee coverage
======================
(Experimental!)
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
pairs of lines (odd lines are callers, even lines are callees)
.. code-block:: console
a.out 0x4a2e0c
a.out 0x4a6510
a.out 0x4a2e0c
a.out 0x4a87f0
Current limitations:
* Only the first 14 callees for every caller are recorded, the rest are silently
ignored.
* The output format is not very compact since caller and callee may reside in
different modules and we need to spell out the module names.
* The routine that dumps the output is not optimized for speed
* Only Linux x86_64 is tested so far.
* Sandboxes are not supported.
Coverage counters
=================
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
more sensitive coverage information. In addition to boolean values assigned to
every basic block (edge) the instrumentation will collect imprecise counters.
On exit, every counter will be mapped to a 8-bit bitset representing counter
ranges: ``1, 2, 3, 4-7, 8-15, 16-31, 32-127, 128+`` and those 8-bit bitsets will
be dumped to disk.
.. code-block:: console
% clang++ -g cov.cc -fsanitize=address -fsanitize-coverage=edge,8bit-counters
% ASAN_OPTIONS="coverage=1:coverage_counters=1" ./a.out
% ls -l *counters-sancov
... a.out.17110.counters-sancov
% xxd *counters-sancov
0000000: 0001 0100 01
These counters may also be used for in-process coverage-guided fuzzers. See
``include/sanitizer/coverage_interface.h``:
.. code-block:: c++
// The coverage instrumentation may optionally provide imprecise counters.
// Rather than exposing the counter values to the user we instead map
// the counters to a bitset.
// Every counter is associated with 8 bits in the bitset.
// We define 8 value ranges: 1, 2, 3, 4-7, 8-15, 16-31, 32-127, 128+
// The i-th bit is set to 1 if the counter value is in the i-th range.
// This counter-based coverage implementation is *not* thread-safe.
// Returns the number of registered coverage counters.
uintptr_t __sanitizer_get_number_of_counters();
// Updates the counter 'bitset', clears the counters and returns the number of
// new bits in 'bitset'.
// If 'bitset' is nullptr, only clears the counters.
// Otherwise 'bitset' should be at least
// __sanitizer_get_number_of_counters bytes long and 8-aligned.
uintptr_t
__sanitizer_update_counter_bitset_and_clear_counters(uint8_t *bitset);
Tracing basic blocks
====================
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
(depending on the value of ``-fsanitize-coverage=[func,bb,edge]``).
Example:
.. code-block:: console
% clang -g -fsanitize=address -fsanitize-coverage=edge,trace-bb foo.cc
% ASAN_OPTIONS=coverage=1 ./a.out
This will produce two files after the process exit:
`trace-points.PID.sancov` and `trace-events.PID.sancov`.
The first file will contain a textual description of all the instrumented points in the program
in the form that you can feed into llvm-symbolizer (e.g. `a.out 0x4dca89`), one per line.
The second file will contain the actual execution trace as a sequence of 4-byte integers
-- these integers are the indices into the array of instrumented points (the first file).
Basic block tracing is currently supported only for single-threaded applications.
Tracing PCs
===========
*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.
With an additional ``...=trace-pc,indirect-calls`` flag
``__sanitizer_cov_trace_pc_indirect(void *callee)`` will be inserted on every indirect call.
These callbacks are not implemented in the Sanitizer run-time and should be defined
by the user. So, these flags do not require the other sanitizer to be used.
This mechanism is used for fuzzing the Linux kernel (https://github.com/google/syzkaller)
and can be used with `AFL <http://lcamtuf.coredump.cx/afl>`__.
LLVM has a simple code coverage instrumentation built in (SanitizerCoverage).
It inserts calls to user-defined functions on function-, basic-block-, and edge- levels.
Default implementations of those callbacks are provided and implement
simple coverage reporting and visualization,
however if you need *just* coverage visualization you may want to use
:doc:`SourceBasedCodeCoverage <SourceBasedCodeCoverage>` instead.
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).
The compler will also insert a module constructor that will call
The compler will also insert calls to a module constructor:
.. 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 an additional ``...=trace-pc,indirect-calls`` flag
``__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 +51,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.
@ -435,6 +119,76 @@ Example:
guard: 0x71bcdc 4 PC 0x4ecdc7 in main trace-pc-guard-example.cc:4:17
guard: 0x71bcd0 1 PC 0x4ecd20 in foo() trace-pc-guard-example.cc:2:14
Tracing PCs
===========
With ``-fsanitize-coverage=trace-pc`` the compiler will insert
``__sanitizer_cov_trace_pc()`` on every edge.
With an additional ``...=trace-pc,indirect-calls`` flag
``__sanitizer_cov_trace_pc_indirect(void *callee)`` will be inserted on every indirect call.
These callbacks are not implemented in the Sanitizer run-time and should be defined
by the user.
This mechanism is used for fuzzing the Linux kernel
(https://github.com/google/syzkaller).
Instrumentation points
======================
Sanitizer Coverage offers different levels of instrumentation.
* ``edge`` (default): edges are instrumented (see below).
* ``bb``: basic blocks are instrumented.
* ``func``: only the entry block of every function will be instrumented.
Use these flags together with ``trace-pc-guard`` or ``trace-pc``,
like this: ``-fsanitize-coverage=func,trace-pc-guard``.
When ``edge`` or ``bb`` is used, some of the edges/blocks may still be left
uninstrumented (pruned) if such instrumentation is considered redundant.
Use ``no-prune`` (e.g. ``-fsanitize-coverage=bb,no-prune,trace-pc-guard``)
to disable pruning. This could be useful for better coverage visualization.
Edge coverage
-------------
Consider this code:
.. code-block:: c++
void foo(int *a) {
if (a)
*a = 0;
}
It contains 3 basic blocks, let's name them A, B, C:
.. code-block:: none
A
|\
| \
| B
| /
|/
C
If blocks A, B, and C are all covered we know for certain that the edges A=>B
and B=>C were executed, but we still don't know if the edge A=>C was executed.
Such edges of control flow graph are called
`critical <http://en.wikipedia.org/wiki/Control_flow_graph#Special_edges>`_. The
edge-level coverage simply splits all critical
edges by introducing new dummy blocks and then instruments those blocks:
.. code-block:: none
A
|\
| \
D B
| /
|/
C
Tracing data flow
=================
@ -475,10 +229,100 @@ the `LLVM GEP instructions <http://llvm.org/docs/GetElementPtr.html>`_
This interface is a subject to change.
The current implementation is not thread-safe and thus can be safely used only for single-threaded targets.
Default implementation
======================
The sanitizer run-time (AddressSanitizer, MemorySanitizer, etc) provide a
default implementations of some of the coverage callbacks.
You may use this implementation to dump the coverage on disk at the process
exit.
Example:
.. code-block:: console
% cat -n cov.cc
1 #include <stdio.h>
2 __attribute__((noinline))
3 void foo() { printf("foo\n"); }
4
5 int main(int argc, char **argv) {
6 if (argc == 2)
7 foo();
8 printf("main\n");
9 }
% clang++ -g cov.cc -fsanitize=address -fsanitize-coverage=trace-pc-guard
% ASAN_OPTIONS=coverage=1 ./a.out; wc -c *.sancov
main
SanitizerCoverage: ./a.out.7312.sancov 2 PCs written
24 a.out.7312.sancov
% ASAN_OPTIONS=coverage=1 ./a.out foo ; wc -c *.sancov
foo
main
SanitizerCoverage: ./a.out.7316.sancov 3 PCs written
24 a.out.7312.sancov
32 a.out.7316.sancov
Every time you run an executable instrumented with SanitizerCoverage
one ``*.sancov`` file is created during the process shutdown.
If the executable is dynamically linked against instrumented DSOs,
one ``*.sancov`` file will be also created for every DSO.
Sancov data format
------------------
The format of ``*.sancov`` files is very simple: the first 8 bytes is the magic,
one of ``0xC0BFFFFFFFFFFF64`` and ``0xC0BFFFFFFFFFFF32``. The last byte of the
magic defines the size of the following offsets. The rest of the data is the
offsets in the corresponding binary/DSO that were executed during the run.
Sancov Tool
-----------
An simple ``sancov`` tool is provided to process coverage files.
The tool is part of LLVM project and is currently supported only on Linux.
It can handle symbolization tasks autonomously without any extra support
from the environment. You need to pass .sancov files (named
``<module_name>.<pid>.sancov`` and paths to all corresponding binary elf files.
Sancov matches these files using module names and binaries file names.
.. code-block:: console
USAGE: sancov [options] <action> (<binary file>|<.sancov file>)...
Action (required)
-print - Print coverage addresses
-covered-functions - Print all covered functions.
-not-covered-functions - Print all not covered functions.
-symbolize - Symbolizes the report.
Options
-blacklist=<string> - Blacklist file (sanitizer blacklist format).
-demangle - Print demangled function name.
-strip_path_prefix=<string> - Strip this prefix from file paths in reports
Coverage Reports
----------------
**Experimental**
``.sancov`` files do not contain enough information to generate a source-level
coverage report. The missing information is contained
in debug info of the binary. Thus the ``.sancov`` has to be symbolized
to produce a ``.symcov`` file first:
.. code-block:: console
sancov -symbolize my_program.123.sancov my_program > my_program.123.symcov
The ``.symcov`` file can be browsed overlayed over the source code by
running ``tools/sancov/coverage-report-server.py`` script that will start
an HTTP server.
Output directory
================
----------------
By default, .sancov files are created in the current working directory.
This can be changed with ``ASAN_OPTIONS=coverage_dir=/path``:
@ -489,95 +333,3 @@ This can be changed with ``ASAN_OPTIONS=coverage_dir=/path``:
% ls -l /tmp/cov/*sancov
-rw-r----- 1 kcc eng 4 Nov 27 12:21 a.out.22673.sancov
-rw-r----- 1 kcc eng 8 Nov 27 12:21 a.out.22679.sancov
Sudden death
============
Normally, coverage data is collected in memory and saved to disk when the
program exits (with an ``atexit()`` handler), when a SIGSEGV is caught, or when
``__sanitizer_cov_dump()`` is called.
If the program ends with a signal that ASan does not handle (or can not handle
at all, like SIGKILL), coverage data will be lost. This is a big problem on
Android, where SIGKILL is a normal way of evicting applications from memory.
With ``ASAN_OPTIONS=coverage=1:coverage_direct=1`` coverage data is written to a
memory-mapped file as soon as it collected.
.. code-block:: console
% ASAN_OPTIONS="coverage=1:coverage_direct=1" ./a.out
main
% ls
7036.sancov.map 7036.sancov.raw a.out
% sancov.py rawunpack 7036.sancov.raw
sancov.py: reading map 7036.sancov.map
sancov.py: unpacking 7036.sancov.raw
writing 1 PCs to a.out.7036.sancov
% sancov.py print a.out.7036.sancov
sancov.py: read 1 PCs from a.out.7036.sancov
sancov.py: 1 files merged; 1 PCs total
0x4b2bae
Note that on 64-bit platforms, this method writes 2x more data than the default,
because it stores full PC values instead of 32-bit offsets.
In-process fuzzing
==================
Coverage data could be useful for fuzzers and sometimes it is preferable to run
a fuzzer in the same process as the code being fuzzed (in-process fuzzer).
You can use ``__sanitizer_get_total_unique_coverage()`` from
``<sanitizer/coverage_interface.h>`` which returns the number of currently
covered entities in the program. This will tell the fuzzer if the coverage has
increased after testing every new input.
If a fuzzer finds a bug in the ASan run, you will need to save the reproducer
before exiting the process. Use ``__asan_set_death_callback`` from
``<sanitizer/asan_interface.h>`` to do that.
An example of such fuzzer can be found in `the LLVM tree
<http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/README.txt?view=markup>`_.
Performance
===========
This coverage implementation is **fast**. With function-level coverage
(``-fsanitize-coverage=func``) the overhead is not measurable. With
basic-block-level coverage (``-fsanitize-coverage=bb``) the overhead varies
between 0 and 25%.
============== ========= ========= ========= ========= ========= =========
benchmark cov0 cov1 diff 0-1 cov2 diff 0-2 diff 1-2
============== ========= ========= ========= ========= ========= =========
400.perlbench 1296.00 1307.00 1.01 1465.00 1.13 1.12
401.bzip2 858.00 854.00 1.00 1010.00 1.18 1.18
403.gcc 613.00 617.00 1.01 683.00 1.11 1.11
429.mcf 605.00 582.00 0.96 610.00 1.01 1.05
445.gobmk 896.00 880.00 0.98 1050.00 1.17 1.19
456.hmmer 892.00 892.00 1.00 918.00 1.03 1.03
458.sjeng 995.00 1009.00 1.01 1217.00 1.22 1.21
462.libquantum 497.00 492.00 0.99 534.00 1.07 1.09
464.h264ref 1461.00 1467.00 1.00 1543.00 1.06 1.05
471.omnetpp 575.00 590.00 1.03 660.00 1.15 1.12
473.astar 658.00 652.00 0.99 715.00 1.09 1.10
483.xalancbmk 471.00 491.00 1.04 582.00 1.24 1.19
433.milc 616.00 627.00 1.02 627.00 1.02 1.00
444.namd 602.00 601.00 1.00 654.00 1.09 1.09
447.dealII 630.00 634.00 1.01 653.00 1.04 1.03
450.soplex 365.00 368.00 1.01 395.00 1.08 1.07
453.povray 427.00 434.00 1.02 495.00 1.16 1.14
470.lbm 357.00 375.00 1.05 370.00 1.04 0.99
482.sphinx3 927.00 928.00 1.00 1000.00 1.08 1.08
============== ========= ========= ========= ========= ========= =========
Why another coverage?
=====================
Why did we implement yet another code coverage?
* We needed something that is lightning fast, plays well with
AddressSanitizer, and does not significantly increase the binary size.
* Traditional coverage implementations based in global counters
`suffer from contention on counters
<https://groups.google.com/forum/#!topic/llvm-dev/cDqYgnxNEhY>`_.

View File

@ -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
================================================
@ -271,6 +274,11 @@ To specify an alternate directory for raw profiles, use
Drawbacks and limitations
=========================
* Prior to version 2.26, the GNU binutils BFD linker is not able link programs
compiled with ``-fcoverage-mapping`` in its ``--gc-sections`` mode. Possible
workarounds include disabling ``--gc-sections``, upgrading to a newer version
of BFD, or using the Gold linker.
* Code coverage does not handle unpredictable changes in control flow or stack
unwinding in the presence of exceptions precisely. Consider the following
function:

View File

@ -123,6 +123,52 @@ which currently must be enabled through a linker option.
``-Wl,-plugin-opt,cache-dir=/path/to/cache``
- ld64 (support in clang 3.9 and Xcode 8):
``-Wl,-cache_path_lto,/path/to/cache``
- lld (as of LLVM r296702):
``-Wl,--thinlto-cache-dir=/path/to/cache``
Cache Pruning
-------------
To help keep the size of the cache under control, ThinLTO supports cache
pruning. Cache pruning is supported with ld64 and ELF lld, but currently only
ELF lld allows you to control the policy with a policy string. The cache
policy must be specified with a linker option.
- ELF lld (as of LLVM r298036):
``-Wl,--thinlto-cache-policy,POLICY``
A policy string is a series of key-value pairs separated by ``:`` characters.
Possible key-value pairs are:
- ``cache_size=X%``: The maximum size for the cache directory is ``X`` percent
of the available space on the the disk. Set to 100 to indicate no limit,
50 to indicate that the cache size will not be left over half the available
disk space. A value over 100 is invalid. A value of 0 disables the percentage
size-based pruning. The default is 75%.
- ``cache_size_bytes=X``, ``cache_size_bytes=Xk``, ``cache_size_bytes=Xm``,
``cache_size_bytes=Xg``:
Sets the maximum size for the cache directory to ``X`` bytes (or KB, MB,
GB respectively). A value over the amount of available space on the disk
will be reduced to the amount of available space. A value of 0 disables
the byte size-based pruning. The default is no byte size-based pruning.
Note that ThinLTO will apply both size-based pruning policies simultaneously,
and changing one does not affect the other. For example, a policy of
``cache_size_bytes=1g`` on its own will cause both the 1GB and default 75%
policies to be applied unless the default ``cache_size`` is overridden.
- ``prune_after=Xs``, ``prune_after=Xm``, ``prune_after=Xh``: Sets the
expiration time for cache files to ``X`` seconds (or minutes, hours
respectively). When a file hasn't been accessed for ``prune_after`` seconds,
it is removed from the cache. A value of 0 disables the expiration-based
pruning. The default is 1 week.
- ``prune_interval=Xs``, ``prune_interval=Xm``, ``prune_interval=Xh``:
Sets the pruning interval to ``X`` seconds (or minutes, hours
respectively). This is intended to be used to avoid scanning the directory
too often. It does not impact the decision of which files to prune. A
value of 0 forces the scan to occur. The default is every 20 minutes.
Clang Bootstrap
---------------

View File

@ -764,8 +764,6 @@ implementation.
#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
#endif
#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
#define CAPABILITY(x) \
THREAD_ANNOTATION_ATTRIBUTE__(capability(x))
@ -886,11 +884,11 @@ implementation.
// Deprecated.
#define PT_GUARDED_VAR \
THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded)
THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_var)
// Deprecated.
#define GUARDED_VAR \
THREAD_ANNOTATION_ATTRIBUTE__(guarded)
THREAD_ANNOTATION_ATTRIBUTE__(guarded_var)
// Replaced by REQUIRES
#define EXCLUSIVE_LOCKS_REQUIRED(...) \

View File

@ -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
@ -100,6 +106,8 @@ Available checks are:
invalid pointers. These checks are made in terms of
``__builtin_object_size``, and consequently may be able to detect more
problems at higher optimization levels.
- ``-fsanitize=pointer-overflow``: Performing pointer arithmetic which
overflows.
- ``-fsanitize=return``: In C++, reaching the end of a
value-returning function without returning a value.
- ``-fsanitize=returns-nonnull-attribute``: Returning null pointer
@ -117,7 +125,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 +138,21 @@ 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.
Volatile
--------
The ``null``, ``alignment``, ``object-size``, and ``vptr`` checks do not apply
to pointers to types with the ``volatile`` qualifier.
Stack traces and report symbolization
=====================================

View File

@ -322,18 +322,40 @@ output format of the diagnostics that it generates.
by category, so it should be a high level category. We want dozens
of these, not hundreds or thousands of them.
.. _opt_fsave-optimization-record:
**-fsave-optimization-record**
Write optimization remarks to a YAML file.
This option, which defaults to off, controls whether Clang writes
optimization reports to a YAML file. By recording diagnostics in a file,
using a structured YAML format, users can parse or sort the remarks in a
convenient way.
.. _opt_foptimization-record-file:
**-foptimization-record-file**
Control the file to which optimization reports are written.
When optimization reports are being output (see
:ref:`-fsave-optimization-record <opt_fsave-optimization-record>`), this
option controls the file to which those reports are written.
If this option is not used, optimization records are output to a file named
after the primary file being compiled. If that's "foo.c", for example,
optimization records are output to "foo.opt.yaml".
.. _opt_fdiagnostics-show-hotness:
**-f[no-]diagnostics-show-hotness**
Enable profile hotness information in diagnostic line.
This option, which defaults to off, controls whether Clang prints the
profile hotness associated with a diagnostics in the presence of
profile-guided optimization information. This is currently supported with
optimization remarks (see :ref:`Options to Emit Optimization Reports
<rpass>`). The hotness information allows users to focus on the hot
optimization remarks that are likely to be more relevant for run-time
performance.
This option controls whether Clang prints the profile hotness associated
with diagnostics in the presence of profile-guided optimization information.
This is currently supported with optimization remarks (see
:ref:`Options to Emit Optimization Reports <rpass>`). The hotness information
allows users to focus on the hot optimization remarks that are likely to be
more relevant for run-time performance.
For example, in this output, the block containing the callsite of `foo` was
executed 3000 times according to the profile data:
@ -344,6 +366,23 @@ output format of the diagnostics that it generates.
sum += foo(x, x - 2);
^
This option is implied when
:ref:`-fsave-optimization-record <opt_fsave-optimization-record>` is used.
Otherwise, it defaults to off.
.. _opt_fdiagnostics-hotness-threshold:
**-fdiagnostics-hotness-threshold**
Prevent optimization remarks from being output if they do not have at least
this hotness value.
This option, which defaults to zero, controls the minimum hotness an
optimization remark would need in order to be output by Clang. This is
currently supported with optimization remarks (see :ref:`Options to Emit
Optimization Reports <rpass>`) when profile hotness information in
diagnostics is enabled (see
:ref:`-fdiagnostics-show-hotness <opt_fdiagnostics-show-hotness>`).
.. _opt_fdiagnostics-fixit-info:
**-f[no-]diagnostics-fixit-info**
@ -562,6 +601,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 +806,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 +1745,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 +1928,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?).
@ -2056,6 +2122,8 @@ can be given manually.
In this case the kernel code should contain ``#include <opencl-c.h>`` just as a
regular C include.
.. _opencl_cl_ext:
.. option:: -cl-ext
Disables support of OpenCL extensions. All OpenCL targets provide a list
@ -2177,6 +2245,41 @@ To enable modules for OpenCL:
$ clang -target spir-unknown-unknown -c -emit-llvm -Xclang -finclude-default-header -fmodules -fimplicit-module-maps -fmodules-cache-path=<path to the generated module> test.cl
OpenCL Extensions
-----------------
All of the ``cl_khr_*`` extensions from `the official OpenCL specification
<https://www.khronos.org/registry/OpenCL/sdk/2.0/docs/man/xhtml/EXTENSION.html>`_
up to and including version 2.0 are available and set per target depending on the
support available in the specific architecture.
It is possible to alter the default extensions setting per target using
``-cl-ext`` flag. (See :ref:`flags description <opencl_cl_ext>` for more details).
Vendor extensions can be added flexibly by declaring the list of types and
functions associated with each extensions enclosed within the following
compiler pragma directives:
.. code-block:: c
#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
For example, parsing the following code adds ``my_t`` type and ``my_func``
function to the custom ``my_ext`` extension.
.. code-block:: c
#pragma OPENCL EXTENSION my_ext : begin
typedef struct{
int a;
}my_t;
void my_func(my_t);
#pragma OPENCL EXTENSION my_ext : end
Declaring the same types in different vendor extensions is disallowed.
OpenCL Metadata
---------------
@ -2215,7 +2318,7 @@ does not have any effect on the IR. For more details reffer to the specification
<https://www.khronos.org/registry/cl/specs/opencl-2.0-openclc.pdf#49>`_
opencl_hint_unroll
opencl_unroll_hint
^^^^^^^^^^^^^^^^^^
The implementation of this feature mirrors the unroll hint for C.
@ -2236,7 +2339,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.
@ -2247,7 +2350,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.
@ -2462,7 +2565,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:
@ -2505,7 +2608,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:
@ -2519,6 +2622,10 @@ Execute ``clang-cl /?`` to see a list of supported options:
/Brepro Emit an object file which can be reproduced over time
/C Don't discard comments when preprocessing
/c Compile only
/d1reportAllClassLayout Dump record layout information
/diagnostics:caret Enable caret and column diagnostics (on by default)
/diagnostics:classic Disable column and caret diagnostics
/diagnostics:column Disable caret diagnostics but keep column info
/D <macro[=value]> Define macro
/EH<value> Exception handling model
/EP Disable linemarker output and preprocess to stdout
@ -2613,6 +2720,8 @@ Execute ``clang-cl /?`` to see a list of supported options:
/Zc:threadSafeInit Enable thread-safe initialization of static variables
/Zc:trigraphs- Disable trigraphs (default)
/Zc:trigraphs Enable trigraphs
/Zc:twoPhase- Disable two-phase name lookup in templates
/Zc:twoPhase Enable two-phase name lookup in templates
/Zd Emit debug line number tables only
/Zi Alias for /Z7. Does not produce PDBs.
/Zl Don't mention any default libraries in the object file
@ -2625,12 +2734,14 @@ Execute ``clang-cl /?`` to see a list of supported options:
--analyze Run the static analyzer
-fansi-escape-codes Use ANSI escape codes for diagnostics
-fcolor-diagnostics Use colors in diagnostics
-fdebug-macro Emit macro debug information
-fdelayed-template-parsing
Parse templated function definitions at the end of the translation unit
-fdiagnostics-absolute-paths
Print absolute paths in diagnostics
-fdiagnostics-parseable-fixits
Print fix-its in machine parseable form
-flto=<value> Set LTO mode to either 'full' or 'thin'
-flto Enable LTO in 'full' mode
-fms-compatibility-version=<value>
Dot-separated value representing the Microsoft compiler version
@ -2639,12 +2750,27 @@ Execute ``clang-cl /?`` to see a list of supported options:
-fms-extensions Accept some non-standard constructs supported by the Microsoft compiler
-fmsc-version=<value> Microsoft compiler version number to report in _MSC_VER
(0 = don't define it (default))
-fno-debug-macro Do not emit macro debug information
-fno-delayed-template-parsing
Disable delayed template parsing
-fno-sanitize-address-use-after-scope
Disable use-after-scope detection in AddressSanitizer
-fno-sanitize-blacklist Don't use blacklist file for sanitizers
-fno-sanitize-cfi-cross-dso
Disable control flow integrity (CFI) checks for cross-DSO calls.
-fno-sanitize-coverage=<value>
Disable specified features of coverage instrumentation for Sanitizers
-fno-sanitize-memory-track-origins
Disable origins tracking in MemorySanitizer
-fno-sanitize-recover=<value>
Disable recovery for specified sanitizers
-fno-sanitize-stats Disable sanitizer statistics gathering.
-fno-sanitize-thread-atomics
Disable atomic operations instrumentation in ThreadSanitizer
-fno-sanitize-thread-func-entry-exit
Disable function entry/exit instrumentation in ThreadSanitizer
-fno-sanitize-thread-memory-access
Disable memory access instrumentation in ThreadSanitizer
-fno-sanitize-trap=<value>
Disable trapping for specified sanitizers
-fno-standalone-debug Limit debug information produced to reduce size of debug binary
@ -2656,13 +2782,36 @@ Execute ``clang-cl /?`` to see a list of supported options:
(overridden by '=' form of option or LLVM_PROFILE_FILE env var)
-fprofile-instr-use=<value>
Use instrumentation data for profile-guided optimization
-fsanitize-address-field-padding=<value>
Level of field padding for AddressSanitizer
-fsanitize-address-globals-dead-stripping
Enable linker dead stripping of globals in AddressSanitizer
-fsanitize-address-use-after-scope
Enable use-after-scope detection in AddressSanitizer
-fsanitize-blacklist=<value>
Path to blacklist file for sanitizers
-fsanitize-cfi-cross-dso
Enable control flow integrity (CFI) checks for cross-DSO calls.
-fsanitize-coverage=<value>
Specify the type of coverage instrumentation for Sanitizers
-fsanitize-memory-track-origins=<value>
Enable origins tracking in MemorySanitizer
-fsanitize-memory-track-origins
Enable origins tracking in MemorySanitizer
-fsanitize-memory-use-after-dtor
Enable use-after-destroy detection in MemorySanitizer
-fsanitize-recover=<value>
Enable recovery for specified sanitizers
-fsanitize-stats Enable sanitizer statistics gathering.
-fsanitize-thread-atomics
Enable atomic operations instrumentation in ThreadSanitizer (default)
-fsanitize-thread-func-entry-exit
Enable function entry/exit instrumentation in ThreadSanitizer (default)
-fsanitize-thread-memory-access
Enable memory access instrumentation in ThreadSanitizer (default)
-fsanitize-trap=<value> Enable trapping for specified sanitizers
-fsanitize-undefined-strip-path-components=<number>
Strip (or keep only, if negative) a given number of path components when emitting check metadata.
-fsanitize=<check> Turn on runtime checks for various forms of undefined or suspicious
behavior. See user manual for available checks
-fstandalone-debug Emit full debug info for all types used by the program
@ -2670,6 +2819,7 @@ Execute ``clang-cl /?`` to see a list of supported options:
-gline-tables-only Emit debug line number tables only
-miamcu Use Intel MCU ABI
-mllvm <value> Additional arguments to forward to LLVM's option processing
-nobuiltininc Disable builtin #include directories
-Qunused-arguments Don't emit warning for unused driver arguments
-R<remark> Enable the specified remark
--target=<value> Generate code for the given target

View File

@ -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'}}
}

View File

@ -48,10 +48,10 @@ copyright = u'2013-%d, Analyzer Team' % date.today().year
# |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.

View File

@ -48,10 +48,10 @@ copyright = u'2007-%d, The Clang Team' % date.today().year
# |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.

View File

@ -132,7 +132,7 @@ INLINE_INHERITED_MEMB = NO
# shortest path that makes the file name unique will be used
# The default value is: YES.
FULL_PATH_NAMES = NO
FULL_PATH_NAMES = YES
# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
# Stripping is only done if one of the specified strings matches the left-hand
@ -144,7 +144,7 @@ FULL_PATH_NAMES = NO
# will be relative from the directory where doxygen is started.
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
STRIP_FROM_PATH = ../..
STRIP_FROM_PATH = @abs_srcdir@/..
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
# path mentioned in the documentation of a class, which tells the reader which
@ -153,7 +153,7 @@ STRIP_FROM_PATH = ../..
# specify the list of include paths that are normally passed to the compiler
# using the -I flag.
STRIP_FROM_INC_PATH =
STRIP_FROM_INC_PATH = @abs_srcdir@/../include
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
# less readable) file names. This can be useful is your file systems doesn't
@ -513,7 +513,7 @@ SHOW_GROUPED_MEMB_INC = NO
# files with double quotes in the documentation rather than with sharp brackets.
# The default value is: NO.
FORCE_LOCAL_INCLUDES = NO
FORCE_LOCAL_INCLUDES = YES
# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
# documentation for inline members.
@ -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

View File

@ -19,6 +19,7 @@ Using Clang as a Compiler
UsersManual
Toolchain
LanguageExtensions
ClangCommandLineReference
AttributeReference
DiagnosticsReference
CrossCompilation

View File

@ -19,16 +19,15 @@ 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)
return text
def indent(text, columns):
def indent(text, columns, indent_first_line=True):
indent = ' ' * columns
s = re.sub(r'\n([^\n])', '\n' + indent + '\\1', text, flags=re.S)
if s.startswith('\n'):
if not indent_first_line or s.startswith('\n'):
return s
return indent + s
@ -65,7 +64,9 @@ class NestedField:
self.comment = comment.strip()
def __str__(self):
return '* ``%s`` %s' % (self.name, doxygen2rst(self.comment))
return '\n* ``%s`` %s' % (
self.name,
doxygen2rst(indent(self.comment, 2, indent_first_line=False)))
class Enum:
def __init__(self, name, comment):
@ -180,7 +181,7 @@ def read_options(header):
if enums.has_key(option.type):
option.enum = enums[option.type]
elif nested_structs.has_key(option.type):
option.nested_struct = nested_structs[option.type];
option.nested_struct = nested_structs[option.type]
else:
raise Exception('Unknown type: %s' % option.type)
return options
@ -196,4 +197,3 @@ contents = substitute(contents, 'FORMAT_STYLE_OPTIONS', options_text)
with open(DOC_FILE, 'wb') as output:
output.write(contents)

View File

@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS
ExecutionEngine
MC
MCJIT
Option
Support
native
)

View File

@ -7,7 +7,7 @@
|* *|
|*===----------------------------------------------------------------------===*|
|* *|
|* This header provides a public inferface to use CompilationDatabase without *|
|* This header provides a public interface to use CompilationDatabase without *|
|* the full Clang C++ API. *|
|* *|
\*===----------------------------------------------------------------------===*/

View File

@ -7,7 +7,7 @@
|* *|
|*===----------------------------------------------------------------------===*|
|* *|
|* This header provides a public inferface to a Clang library for extracting *|
|* This header provides a public interface to a Clang library for extracting *|
|* high-level symbol information from source files without exposing the full *|
|* Clang C++ API. *|
|* *|
@ -32,7 +32,7 @@
* compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
*/
#define CINDEX_VERSION_MAJOR 0
#define CINDEX_VERSION_MINOR 37
#define CINDEX_VERSION_MINOR 43
#define CINDEX_VERSION_ENCODE(major, minor) ( \
((major) * 10000) \
@ -80,6 +80,12 @@ extern "C" {
*/
typedef void *CXIndex;
/**
* \brief An opaque type representing target information for a given translation
* unit.
*/
typedef struct CXTargetInfoImpl *CXTargetInfo;
/**
* \brief A single translation unit, which resides in an index.
*/
@ -165,7 +171,60 @@ typedef struct CXVersion {
*/
int Subminor;
} CXVersion;
/**
* \brief Describes the exception specification of a cursor.
*
* A negative value indicates that the cursor is not a function declaration.
*/
enum CXCursor_ExceptionSpecificationKind {
/**
* \brief The cursor has no exception specification.
*/
CXCursor_ExceptionSpecificationKind_None,
/**
* \brief The cursor has exception specification throw()
*/
CXCursor_ExceptionSpecificationKind_DynamicNone,
/**
* \brief The cursor has exception specification throw(T1, T2)
*/
CXCursor_ExceptionSpecificationKind_Dynamic,
/**
* \brief The cursor has exception specification throw(...).
*/
CXCursor_ExceptionSpecificationKind_MSAny,
/**
* \brief The cursor has exception specification basic noexcept.
*/
CXCursor_ExceptionSpecificationKind_BasicNoexcept,
/**
* \brief The cursor has exception specification computed noexcept.
*/
CXCursor_ExceptionSpecificationKind_ComputedNoexcept,
/**
* \brief The exception specification has not yet been evaluated.
*/
CXCursor_ExceptionSpecificationKind_Unevaluated,
/**
* \brief The exception specification has not yet been instantiated.
*/
CXCursor_ExceptionSpecificationKind_Uninstantiated,
/**
* \brief The exception specification has not been parsed yet.
*/
CXCursor_ExceptionSpecificationKind_Unparsed
};
/**
* \brief Provides a shared context for creating translation units.
*
@ -478,8 +537,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
*
@ -1228,7 +1287,12 @@ enum CXTranslationUnit_Flags {
* purposes of an IDE, this is undesirable behavior and as much information
* as possible should be reported. Use this flag to enable this behavior.
*/
CXTranslationUnit_KeepGoing = 0x200
CXTranslationUnit_KeepGoing = 0x200,
/**
* \brief Sets the preprocessor in a mode for parsing a single file only.
*/
CXTranslationUnit_SingleFileParse = 0x400
};
/**
@ -1412,6 +1476,15 @@ CINDEX_LINKAGE int clang_saveTranslationUnit(CXTranslationUnit TU,
const char *FileName,
unsigned options);
/**
* \brief Suspend a translation unit in order to free memory associated with it.
*
* A suspended translation unit uses significantly less memory but on the other
* side does not support any other calls than \c clang_reparseTranslationUnit
* to resume it or \c clang_disposeTranslationUnit to dispose it completely.
*/
CINDEX_LINKAGE unsigned clang_suspendTranslationUnit(CXTranslationUnit);
/**
* \brief Destroy the specified CXTranslationUnit object.
*/
@ -1552,6 +1625,36 @@ CINDEX_LINKAGE CXTUResourceUsage clang_getCXTUResourceUsage(CXTranslationUnit TU
CINDEX_LINKAGE void clang_disposeCXTUResourceUsage(CXTUResourceUsage usage);
/**
* \brief Get target information for this translation unit.
*
* The CXTargetInfo object cannot outlive the CXTranslationUnit object.
*/
CINDEX_LINKAGE CXTargetInfo
clang_getTranslationUnitTargetInfo(CXTranslationUnit CTUnit);
/**
* \brief Destroy the CXTargetInfo object.
*/
CINDEX_LINKAGE void
clang_TargetInfo_dispose(CXTargetInfo Info);
/**
* \brief Get the normalized target triple as a string.
*
* Returns the empty string in case of any error.
*/
CINDEX_LINKAGE CXString
clang_TargetInfo_getTriple(CXTargetInfo Info);
/**
* \brief Get the pointer width of the target in bits.
*
* Returns -1 in case of error.
*/
CINDEX_LINKAGE int
clang_TargetInfo_getPointerWidth(CXTargetInfo Info);
/**
* @}
*/
@ -3011,8 +3114,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,
@ -3039,7 +3143,52 @@ enum CXTypeKind {
*
* E.g., struct S, or via a qualified name, e.g., N::M::type, or both.
*/
CXType_Elaborated = 119
CXType_Elaborated = 119,
/* OpenCL PipeType. */
CXType_Pipe = 120,
/* OpenCL builtin types. */
CXType_OCLImage1dRO = 121,
CXType_OCLImage1dArrayRO = 122,
CXType_OCLImage1dBufferRO = 123,
CXType_OCLImage2dRO = 124,
CXType_OCLImage2dArrayRO = 125,
CXType_OCLImage2dDepthRO = 126,
CXType_OCLImage2dArrayDepthRO = 127,
CXType_OCLImage2dMSAARO = 128,
CXType_OCLImage2dArrayMSAARO = 129,
CXType_OCLImage2dMSAADepthRO = 130,
CXType_OCLImage2dArrayMSAADepthRO = 131,
CXType_OCLImage3dRO = 132,
CXType_OCLImage1dWO = 133,
CXType_OCLImage1dArrayWO = 134,
CXType_OCLImage1dBufferWO = 135,
CXType_OCLImage2dWO = 136,
CXType_OCLImage2dArrayWO = 137,
CXType_OCLImage2dDepthWO = 138,
CXType_OCLImage2dArrayDepthWO = 139,
CXType_OCLImage2dMSAAWO = 140,
CXType_OCLImage2dArrayMSAAWO = 141,
CXType_OCLImage2dMSAADepthWO = 142,
CXType_OCLImage2dArrayMSAADepthWO = 143,
CXType_OCLImage3dWO = 144,
CXType_OCLImage1dRW = 145,
CXType_OCLImage1dArrayRW = 146,
CXType_OCLImage1dBufferRW = 147,
CXType_OCLImage2dRW = 148,
CXType_OCLImage2dArrayRW = 149,
CXType_OCLImage2dDepthRW = 150,
CXType_OCLImage2dArrayDepthRW = 151,
CXType_OCLImage2dMSAARW = 152,
CXType_OCLImage2dArrayMSAARW = 153,
CXType_OCLImage2dMSAADepthRW = 154,
CXType_OCLImage2dArrayMSAADepthRW = 155,
CXType_OCLImage3dRW = 156,
CXType_OCLSampler = 157,
CXType_OCLEvent = 158,
CXType_OCLQueue = 159,
CXType_OCLReserveID = 160
};
/**
@ -3056,7 +3205,7 @@ enum CXCallingConv {
CXCallingConv_AAPCS_VFP = 7,
CXCallingConv_X86RegCall = 8,
CXCallingConv_IntelOclBicc = 9,
CXCallingConv_X86_64Win64 = 10,
CXCallingConv_Win64 = 10,
CXCallingConv_X86_64SysV = 11,
CXCallingConv_X86VectorCall = 12,
CXCallingConv_Swift = 13,
@ -3325,6 +3474,16 @@ CINDEX_LINKAGE unsigned clang_isVolatileQualifiedType(CXType T);
*/
CINDEX_LINKAGE unsigned clang_isRestrictQualifiedType(CXType T);
/**
* \brief Returns the address space of the given type.
*/
CINDEX_LINKAGE unsigned clang_getAddressSpace(CXType T);
/**
* \brief Returns the typedef name of the given type.
*/
CINDEX_LINKAGE CXString clang_getTypedefName(CXType CT);
/**
* \brief For pointer types, returns the type of the pointee.
*/
@ -3364,6 +3523,13 @@ CINDEX_LINKAGE enum CXCallingConv clang_getFunctionTypeCallingConv(CXType T);
*/
CINDEX_LINKAGE CXType clang_getResultType(CXType T);
/**
* \brief Retrieve the exception specification type associated with a function type.
*
* If a non-function type is passed in, an error code of -1 is returned.
*/
CINDEX_LINKAGE int clang_getExceptionSpecificationType(CXType T);
/**
* \brief Retrieve the number of non-variadic parameters associated with a
* function type.
@ -3392,6 +3558,13 @@ CINDEX_LINKAGE unsigned clang_isFunctionTypeVariadic(CXType T);
*/
CINDEX_LINKAGE CXType clang_getCursorResultType(CXCursor C);
/**
* \brief Retrieve the exception specification type associated with a given cursor.
*
* This only returns a valid result if the cursor refers to a function or method.
*/
CINDEX_LINKAGE int clang_getCursorExceptionSpecificationType(CXCursor C);
/**
* \brief Return 1 if the CXType is a POD (plain old data) type, and 0
* otherwise.
@ -3435,6 +3608,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
@ -3964,8 +4147,8 @@ CINDEX_LINKAGE int clang_Cursor_getObjCSelectorIndex(CXCursor);
CINDEX_LINKAGE int clang_Cursor_isDynamicCall(CXCursor C);
/**
* \brief Given a cursor pointing to an Objective-C message, returns the CXType
* of the receiver.
* \brief Given a cursor pointing to an Objective-C message or property
* reference, or C++ method call, returns the CXType of the receiver.
*/
CINDEX_LINKAGE CXType clang_Cursor_getReceiverType(CXCursor C);
@ -4023,8 +4206,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);
@ -4033,6 +4216,23 @@ CINDEX_LINKAGE unsigned clang_Cursor_isObjCOptional(CXCursor C);
*/
CINDEX_LINKAGE unsigned clang_Cursor_isVariadic(CXCursor C);
/**
* \brief Returns non-zero if the given cursor points to a symbol marked with
* external_source_symbol attribute.
*
* \param language If non-NULL, and the attribute is present, will be set to
* the 'language' string from the attribute.
*
* \param definedIn If non-NULL, and the attribute is present, will be set to
* the 'definedIn' string from the attribute.
*
* \param isGenerated If non-NULL, and the attribute is present, will be set to
* non-zero if the 'generated_declaration' is set in the attribute.
*/
CINDEX_LINKAGE unsigned clang_Cursor_isExternalSymbol(CXCursor C,
CXString *language, CXString *definedIn,
unsigned *isGenerated);
/**
* \brief Given a cursor that represents a declaration, return the associated
* comment's source range. The range may include multiple consecutive comments
@ -4216,6 +4416,11 @@ CINDEX_LINKAGE unsigned clang_CXXMethod_isStatic(CXCursor C);
*/
CINDEX_LINKAGE unsigned clang_CXXMethod_isVirtual(CXCursor C);
/**
* \brief Determine if an enum declaration refers to a scoped enum.
*/
CINDEX_LINKAGE unsigned clang_EnumDecl_isScoped(CXCursor C);
/**
* \brief Determine if a C++ member function or member function template is
* declared 'const'.
@ -4700,7 +4905,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
@ -5589,7 +5794,8 @@ typedef enum {
CXIdxEntityLang_None = 0,
CXIdxEntityLang_C = 1,
CXIdxEntityLang_ObjC = 2,
CXIdxEntityLang_CXX = 3
CXIdxEntityLang_CXX = 3,
CXIdxEntityLang_Swift = 4
} CXIdxEntityLanguage;
/**

View File

@ -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 @@ private:
/// \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 @@ private:
/// 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 @@ private:
/// \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 @@ private:
const TargetInfo *Target;
const TargetInfo *AuxTarget;
clang::PrintingPolicy PrintingPolicy;
public:
IdentifierTable &Idents;
SelectorTable &Selectors;
@ -604,7 +612,7 @@ public:
void setPrintingPolicy(const clang::PrintingPolicy &Policy) {
PrintingPolicy = Policy;
}
SourceManager& getSourceManager() { return SourceMgr; }
const SourceManager& getSourceManager() const { return SourceMgr; }
@ -619,7 +627,7 @@ public:
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 @@ public:
}
/// Return the total memory used for various side tables.
size_t getSideTableAllocatedMemory() const;
PartialDiagnostic::StorageAllocator &getDiagAllocator() {
return DiagAllocator;
}
@ -647,13 +655,17 @@ public:
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 @@ public:
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 @@ public:
/// \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 @@ public:
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 @@ public:
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());
@ -923,7 +935,7 @@ public:
/// \brief Get the additional modules in which the definition \p Def has
/// been merged.
ArrayRef<Module*> getModulesWithMergedDefinition(NamedDecl *Def) {
ArrayRef<Module*> getModulesWithMergedDefinition(const NamedDecl *Def) {
auto MergedIt = MergedDefModules.find(Def);
if (MergedIt == MergedDefModules.end())
return None;
@ -973,7 +985,7 @@ public:
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 @@ public:
/// 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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
/// \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;
@ -1422,6 +1441,10 @@ public:
/// The sizeof operator requires this (C99 6.5.3.4p4).
CanQualType getSizeType() const;
/// \brief Return the unique signed counterpart of
/// the integer type corresponding to size_t.
CanQualType getSignedSizeType() const;
/// \brief Return the unique type for "intmax_t" (C99 7.18.1.5), defined in
/// <stdint.h>.
CanQualType getIntMaxType() const;
@ -1471,11 +1494,11 @@ public:
/// \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 +1519,11 @@ public:
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 +1531,7 @@ public:
return getObjCIdType();
return ObjCIdRedefinitionType;
}
/// \brief Set the user-written type that redefines \c id.
void setObjCIdRedefinitionType(QualType RedefType) {
ObjCIdRedefinitionType = RedefType;
@ -1521,7 +1544,7 @@ public:
return getObjCClassType();
return ObjCClassRedefinitionType;
}
/// \brief Set the user-written type that redefines 'SEL'.
void setObjCClassRedefinitionType(QualType RedefType) {
ObjCClassRedefinitionType = RedefType;
@ -1534,7 +1557,7 @@ public:
return getObjCSelType();
return ObjCSelRedefinitionType;
}
/// \brief Set the user-written type that redefines 'SEL'.
void setObjCSelRedefinitionType(QualType RedefType) {
ObjCSelRedefinitionType = RedefType;
@ -1586,7 +1609,7 @@ public:
/// \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 +1694,7 @@ public:
/// \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 +1704,7 @@ public:
bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto,
ObjCProtocolDecl *rProto) const;
ObjCPropertyImplDecl *getObjCPropertyImplDeclForPropertyDecl(
const ObjCPropertyDecl *PD,
const Decl *Container) const;
@ -1693,7 +1716,7 @@ public:
/// \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 +1728,26 @@ public:
/// \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 +1765,12 @@ public:
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 +1833,7 @@ public:
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 +1844,7 @@ public:
Qs.removeObjCLifetime();
return getQualifiedType(type.getUnqualifiedType(), Qs);
}
DeclarationNameInfo getNameForTemplate(TemplateName Name,
SourceLocation NameLoc) const;
@ -1840,7 +1863,7 @@ public:
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 +1928,7 @@ public:
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 +1950,11 @@ public:
/// 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;
@ -2031,15 +2054,20 @@ public:
/// Get the offset of a FieldDecl or IndirectFieldDecl, in bits.
uint64_t getFieldOffset(const ValueDecl *FD) const;
/// Get the offset of an ObjCIvarDecl in bits.
uint64_t lookupFieldBitOffset(const ObjCInterfaceDecl *OID,
const ObjCImplementationDecl *ID,
const ObjCIvarDecl *Ivar) const;
bool isNearlyEmpty(const CXXRecordDecl *RD) const;
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 +2143,7 @@ public:
*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 +2162,9 @@ public:
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 +2218,7 @@ public:
/// \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 +2245,7 @@ public:
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 +2264,14 @@ public:
/// 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 +2297,7 @@ public:
/// 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,21 +2326,14 @@ public:
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.
uint64_t getTargetNullPointerValue(QualType QT) const;
bool addressSpaceMapManglingFor(unsigned AS) const {
return AddrSpaceMapMangling ||
AS < LangAS::Offset ||
AS >= LangAS::Offset + LangAS::Count;
return AddrSpaceMapMangling || AS >= LangAS::FirstTargetAddressSpace;
}
private:
@ -2325,11 +2346,11 @@ public:
//===--------------------------------------------------------------------===//
/// 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 +2365,7 @@ public:
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 +2391,9 @@ public:
QualType mergeTransparentUnionType(QualType, QualType,
bool OfBlockPointer=false,
bool Unqualified = false);
QualType mergeObjCGCQualifiers(QualType, QualType);
bool doFunctionTypesMatchOnExtParameterInfos(
const FunctionProtoType *FromFunctionType,
const FunctionProtoType *ToFunctionType);
@ -2442,7 +2463,7 @@ public:
/// 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 +2487,10 @@ public:
/// 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 +2499,16 @@ public:
/// 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 +2565,15 @@ public:
/// \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 +2586,25 @@ public:
/// \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.
///

View File

@ -0,0 +1,103 @@
//===--- ASTStructuralEquivalence.h - ---------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the StructuralEquivalenceContext class which checks for
// structural equivalence between types.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ASTSTRUCTURALEQUIVALENCE_H
#define LLVM_CLANG_AST_ASTSTRUCTURALEQUIVALENCE_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Optional.h"
#include <deque>
namespace clang {
class ASTContext;
class Decl;
class DiagnosticBuilder;
class QualType;
class RecordDecl;
class SourceLocation;
struct StructuralEquivalenceContext {
/// AST contexts for which we are checking structural equivalence.
ASTContext &FromCtx, &ToCtx;
/// The set of "tentative" equivalences between two canonical
/// declarations, mapping from a declaration in the first context to the
/// declaration in the second context that we believe to be equivalent.
llvm::DenseMap<Decl *, Decl *> TentativeEquivalences;
/// Queue of declarations in the first context whose equivalence
/// with a declaration in the second context still needs to be verified.
std::deque<Decl *> DeclsToCheck;
/// Declaration (from, to) pairs that are known not to be equivalent
/// (which we have already complained about).
llvm::DenseSet<std::pair<Decl *, Decl *>> &NonEquivalentDecls;
/// Whether we're being strict about the spelling of types when
/// unifying two types.
bool StrictTypeSpelling;
/// Whether warn or error on tag type mismatches.
bool ErrorOnTagTypeMismatch;
/// Whether to complain about failures.
bool Complain;
/// \c true if the last diagnostic came from ToCtx.
bool LastDiagFromC2;
StructuralEquivalenceContext(
ASTContext &FromCtx, ASTContext &ToCtx,
llvm::DenseSet<std::pair<Decl *, Decl *>> &NonEquivalentDecls,
bool StrictTypeSpelling = false, bool Complain = true,
bool ErrorOnTagTypeMismatch = false)
: FromCtx(FromCtx), ToCtx(ToCtx), NonEquivalentDecls(NonEquivalentDecls),
StrictTypeSpelling(StrictTypeSpelling),
ErrorOnTagTypeMismatch(ErrorOnTagTypeMismatch), Complain(Complain),
LastDiagFromC2(false) {}
DiagnosticBuilder Diag1(SourceLocation Loc, unsigned DiagID);
DiagnosticBuilder Diag2(SourceLocation Loc, unsigned DiagID);
/// Determine whether the two declarations are structurally
/// equivalent.
bool IsStructurallyEquivalent(Decl *D1, Decl *D2);
/// Determine whether the two types are structurally equivalent.
bool IsStructurallyEquivalent(QualType T1, QualType T2);
/// Find the index of the given anonymous struct/union within its
/// context.
///
/// \returns Returns the index of this anonymous struct/union in its context,
/// including the next assigned index (if none of them match). Returns an
/// empty option if the context is not a record, i.e.. if the anonymous
/// struct/union is at namespace or block scope.
///
/// FIXME: This is needed by ASTImporter and ASTStructureEquivalence. It
/// probably makes more sense in some other common place then here.
static llvm::Optional<unsigned>
findUntaggedStructOrUnionIndex(RecordDecl *Anon);
private:
/// Finish checking all of the structural equivalences.
///
/// \returns true if an error occurred, false otherwise.
bool Finish();
};
} // namespace clang
#endif // LLVM_CLANG_AST_ASTSTRUCTURALEQUIVALENCE_H

View File

@ -22,6 +22,7 @@
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/Support/type_traits.h"
#include <algorithm>
#include <cstddef>
#include <cstring>
#include <memory>

View File

@ -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)

View File

@ -127,7 +127,11 @@ class CXXBasePaths {
/// class subobjects for that class type. The key of the map is
/// the cv-unqualified canonical type of the base class subobject.
llvm::SmallDenseMap<QualType, std::pair<bool, unsigned>, 8> ClassSubobjects;
/// VisitedDependentRecords - Records the dependent records that have been
/// already visited.
llvm::SmallDenseSet<const CXXRecordDecl *, 4> VisitedDependentRecords;
/// FindAmbiguities - Whether Sema::IsDerivedFrom should try find
/// ambiguous paths while it is looking for a path from a derived
/// type to a base type.
@ -161,7 +165,8 @@ class CXXBasePaths {
void ComputeDeclsFound();
bool lookupInBases(ASTContext &Context, const CXXRecordDecl *Record,
CXXRecordDecl::BaseMatchesCallback BaseMatches);
CXXRecordDecl::BaseMatchesCallback BaseMatches,
bool LookupInDependent = false);
public:
typedef std::list<CXXBasePath>::iterator paths_iterator;

View File

@ -208,6 +208,10 @@ public:
/// \returns \c true if declaration that this comment is attached to declares
/// a function pointer.
bool isFunctionPointerVarDecl();
/// \returns \c true if the declaration that this comment is attached to
/// declares a variable or a field whose type is a function or a block
/// pointer.
bool isFunctionOrBlockPointerVarLikeDecl();
bool isFunctionOrMethodVariadic();
bool isObjCMethodDecl();
bool isObjCPropertyDecl();

View File

@ -301,16 +301,6 @@ public:
using Decl::isModulePrivate;
using Decl::setModulePrivate;
/// \brief Determine whether this declaration is hidden from name lookup.
bool isHidden() const { return Hidden; }
/// \brief Set whether this declaration is hidden from name lookup.
void setHidden(bool Hide) {
assert((!Hide || isFromASTFile() || hasLocalOwningModuleStorage()) &&
"declaration with no owning module can't be hidden");
Hidden = Hide;
}
/// \brief Determine whether this declaration is a C++ class member.
bool isCXXClassMember() const {
const DeclContext *DC = getDeclContext();
@ -838,7 +828,7 @@ protected:
/// 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;
@ -861,6 +851,7 @@ protected:
class NonParmVarDeclBitfields {
friend class VarDecl;
friend class ImplicitParamDecl;
friend class ASTDeclReader;
unsigned : NumVarDeclBits;
@ -904,6 +895,10 @@ protected:
/// declared in the same block scope. This controls whether we should merge
/// the type of this declaration with its previous declaration.
unsigned PreviousDeclInSameBlockScope : 1;
/// Defines kind of the ImplicitParamDecl: 'this', 'self', 'vtt', '_cmd' or
/// something else.
unsigned ImplicitParamKind : 3;
};
union {
@ -966,9 +961,16 @@ public:
/// hasLocalStorage - Returns true if a variable with function scope
/// is a non-static local variable.
bool hasLocalStorage() const {
if (getStorageClass() == SC_None)
if (getStorageClass() == SC_None) {
// OpenCL v1.2 s6.5.3: The __constant or constant address space name is
// used to describe variables allocated in global memory and which are
// accessed inside a kernel(s) as read-only variables. As such, variables
// in constant address space cannot have local storage.
if (getType().getAddressSpace() == LangAS::opencl_constant)
return false;
// Second check is for C++11 [dcl.stc]p4.
return !isFileVarDecl() && getTSCSpec() == TSCS_unspecified;
}
// Global Named Register (GNU extension)
if (getStorageClass() == SC_Register && !isLocalVarDeclOrParm())
@ -1379,20 +1381,50 @@ public:
class ImplicitParamDecl : public VarDecl {
void anchor() override;
public:
/// Defines the kind of the implicit parameter: is this an implicit parameter
/// with pointer to 'this', 'self', '_cmd', virtual table pointers, captured
/// context or something else.
enum ImplicitParamKind : unsigned {
ObjCSelf, /// Parameter for Objective-C 'self' argument
ObjCCmd, /// Parameter for Objective-C '_cmd' argument
CXXThis, /// Parameter for C++ 'this' argument
CXXVTT, /// Parameter for C++ virtual table pointers
CapturedContext, /// Parameter for captured context
Other, /// Other implicit parameter
};
/// Create implicit parameter.
static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation IdLoc, IdentifierInfo *Id,
QualType T);
QualType T, ImplicitParamKind ParamKind);
static ImplicitParamDecl *Create(ASTContext &C, QualType T,
ImplicitParamKind ParamKind);
static ImplicitParamDecl *CreateDeserialized(ASTContext &C, unsigned ID);
ImplicitParamDecl(ASTContext &C, DeclContext *DC, SourceLocation IdLoc,
IdentifierInfo *Id, QualType Type)
: VarDecl(ImplicitParam, C, DC, IdLoc, IdLoc, Id, Type,
/*tinfo*/ nullptr, SC_None) {
IdentifierInfo *Id, QualType Type,
ImplicitParamKind ParamKind)
: VarDecl(ImplicitParam, C, DC, IdLoc, IdLoc, Id, Type,
/*TInfo=*/nullptr, SC_None) {
NonParmVarDeclBits.ImplicitParamKind = ParamKind;
setImplicit();
}
ImplicitParamDecl(ASTContext &C, QualType Type, ImplicitParamKind ParamKind)
: VarDecl(ImplicitParam, C, /*DC=*/nullptr, SourceLocation(),
SourceLocation(), /*Id=*/nullptr, Type,
/*TInfo=*/nullptr, SC_None) {
NonParmVarDeclBits.ImplicitParamKind = ParamKind;
setImplicit();
}
/// Returns the implicit parameter kind.
ImplicitParamKind getParameterKind() const {
return static_cast<ImplicitParamKind>(NonParmVarDeclBits.ImplicitParamKind);
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ImplicitParam; }
@ -1605,9 +1637,14 @@ private:
// 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;
@ -1619,6 +1656,7 @@ private:
unsigned HasImplicitReturnZero : 1;
unsigned IsLateTemplateParsed : 1;
unsigned IsConstexpr : 1;
unsigned InstantiationIsPending:1;
/// \brief Indicates if the function uses __try.
unsigned UsesSEHTry : 1;
@ -1708,11 +1746,13 @@ protected:
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),
InstantiationIsPending(false),
UsesSEHTry(false), HasSkippedBody(false), WillHaveBody(false),
EndRangeLoc(NameInfo.getEndLoc()), TemplateOrSpecialization(),
DNLoc(NameInfo.getInfo()) {}
@ -1826,14 +1866,15 @@ public:
return getBody(Definition);
}
/// isThisDeclarationADefinition - Returns whether this specific
/// declaration of the function is also a definition. This does not
/// determine whether the function has been defined (e.g., in a
/// previous definition); for that information, use isDefined. Note
/// that this returns false for a defaulted function unless that function
/// has been implicitly defined (possibly as deleted).
/// Returns whether this specific declaration of the function is also a
/// definition that does not contain uninstantiated body.
///
/// This does not determine whether the function has been defined (e.g., in a
/// previous definition); for that information, use isDefined.
///
bool isThisDeclarationADefinition() const {
return IsDeleted || Body || IsLateTemplateParsed;
return IsDeleted || IsDefaulted || Body || IsLateTemplateParsed ||
WillHaveBody || hasDefiningAttr();
}
/// doesThisDeclarationHaveABody - Returns whether this specific
@ -1904,6 +1945,15 @@ public:
bool isConstexpr() const { return IsConstexpr; }
void setConstexpr(bool IC) { IsConstexpr = IC; }
/// \brief Whether the instantiation of this function is pending.
/// This bit is set when the decision to instantiate this function is made
/// and unset if and when the function body is created. That leaves out
/// cases where instantiation did not happen because the template definition
/// was not seen in this TU. This bit remains set in those cases, under the
/// assumption that the instantiation will happen in some other TU.
bool instantiationIsPending() const { return InstantiationIsPending; }
void setInstantiationIsPending(bool IC) { InstantiationIsPending = IC; }
/// \brief Indicates the function uses __try.
bool usesSEHTry() const { return UsesSEHTry; }
void setUsesSEHTry(bool UST) { UsesSEHTry = UST; }
@ -1969,7 +2019,10 @@ public:
/// These functions have special behavior under C++1y [expr.new]:
/// An implementation is allowed to omit a call to a replaceable global
/// allocation function. [...]
bool isReplaceableGlobalAllocationFunction() const;
///
/// If this function is an aligned allocation/deallocation function, return
/// true through IsAligned.
bool isReplaceableGlobalAllocationFunction(bool *IsAligned = nullptr) const;
/// Compute the language linkage.
LanguageLinkage getLanguageLinkage() const;
@ -2076,10 +2129,7 @@ public:
const Attr *getUnusedResultAttr() const;
/// \brief Returns true if this function or its return type has the
/// warn_unused_result attribute. If the return type has the attribute and
/// this function is a method of the return type's class, then false will be
/// returned to avoid spurious warnings on member methods such as assignment
/// operators.
/// warn_unused_result attribute.
bool hasUnusedResultAttr() const { return getUnusedResultAttr() != nullptr; }
/// \brief Returns the storage class as written in the source. For the
@ -2475,7 +2525,7 @@ public:
void setCapturedVLAType(const VariableArrayType *VLAType);
/// getParent - Returns the parent of this field declaration, which
/// is the struct in which this method is defined.
/// is the struct in which this field is defined.
const RecordDecl *getParent() const {
return cast<RecordDecl>(getDeclContext());
}
@ -2635,12 +2685,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 +2748,22 @@ public:
/// 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 +3295,18 @@ public:
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;

View File

@ -34,6 +34,7 @@ class DeclarationName;
class DependentDiagnostic;
class EnumDecl;
class ExportDecl;
class ExternalSourceSymbolAttr;
class FunctionDecl;
class FunctionType;
enum Linkage : unsigned char;
@ -201,26 +202,33 @@ public:
OBJC_TQ_CSNullability = 0x40
};
protected:
// Enumeration values used in the bits stored in NextInContextAndBits.
enum {
/// \brief Whether this declaration is a top-level declaration (function,
/// global variable, etc.) that is lexically inside an objc container
/// definition.
TopLevelDeclInObjCContainerFlag = 0x01,
/// \brief Whether this declaration is private to the module in which it was
/// defined.
ModulePrivateFlag = 0x02
/// The kind of ownership a declaration has, for visibility purposes.
/// This enumeration is designed such that higher values represent higher
/// levels of name hiding.
enum class ModuleOwnershipKind : unsigned {
/// This declaration is not owned by a module.
Unowned,
/// This declaration has an owning module, but is globally visible
/// (typically because its owning module is visible and we know that
/// modules cannot later become hidden in this compilation).
/// After serialization and deserialization, this will be converted
/// to VisibleWhenImported.
Visible,
/// This declaration has an owning module, and is visible when that
/// module is imported.
VisibleWhenImported,
/// This declaration has an owning module, but is only visible to
/// lookups that occur within that module.
ModulePrivate
};
protected:
/// \brief The next declaration within the same lexical
/// DeclContext. These pointers form the linked list that is
/// traversed via DeclContext's decls_begin()/decls_end().
///
/// The extra two bits are used for the TopLevelDeclInObjCContainer and
/// ModulePrivate bits.
llvm::PointerIntPair<Decl *, 2, unsigned> NextInContextAndBits;
/// The extra two bits are used for the ModuleOwnershipKind.
llvm::PointerIntPair<Decl *, 2, ModuleOwnershipKind> NextInContextAndBits;
private:
friend class DeclContext;
@ -281,6 +289,11 @@ private:
/// are regarded as "referenced" but not "used".
unsigned Referenced : 1;
/// \brief Whether this declaration is a top-level declaration (function,
/// global variable, etc.) that is lexically inside an objc container
/// definition.
unsigned TopLevelDeclInObjCContainer : 1;
/// \brief Whether statistic collection is enabled.
static bool StatisticsEnabled;
@ -293,11 +306,6 @@ protected:
/// \brief Whether this declaration was loaded from an AST file.
unsigned FromASTFile : 1;
/// \brief Whether this declaration is hidden from normal name lookup, e.g.,
/// because it is was loaded from an AST file is either module-private or
/// because its submodule has not been made visible.
unsigned Hidden : 1;
/// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
unsigned IdentifierNamespace : 13;
@ -331,26 +339,38 @@ protected:
private:
bool AccessDeclContextSanity() const;
protected:
/// Get the module ownership kind to use for a local lexical child of \p DC,
/// which may be either a local or (rarely) an imported declaration.
static ModuleOwnershipKind getModuleOwnershipKindForChildOf(DeclContext *DC) {
if (DC) {
auto *D = cast<Decl>(DC);
auto MOK = D->getModuleOwnershipKind();
if (MOK != ModuleOwnershipKind::Unowned &&
(!D->isFromASTFile() || D->hasLocalOwningModuleStorage()))
return MOK;
// If D is not local and we have no local module storage, then we don't
// need to track module ownership at all.
}
return ModuleOwnershipKind::Unowned;
}
protected:
Decl(Kind DK, DeclContext *DC, SourceLocation L)
: NextInContextAndBits(), DeclCtx(DC),
Loc(L), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false), Used(false), Referenced(false),
Access(AS_none), FromASTFile(0), Hidden(DC && cast<Decl>(DC)->Hidden),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
CacheValidAndLinkage(0)
{
: NextInContextAndBits(nullptr, getModuleOwnershipKindForChildOf(DC)),
DeclCtx(DC), Loc(L), DeclKind(DK), InvalidDecl(0), HasAttrs(false),
Implicit(false), Used(false), Referenced(false),
TopLevelDeclInObjCContainer(false), Access(AS_none), FromASTFile(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
CacheValidAndLinkage(0) {
if (StatisticsEnabled) add(DK);
}
Decl(Kind DK, EmptyShell Empty)
: NextInContextAndBits(), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false), Used(false), Referenced(false),
Access(AS_none), FromASTFile(0), Hidden(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
CacheValidAndLinkage(0)
{
: NextInContextAndBits(), DeclKind(DK), InvalidDecl(0), HasAttrs(false),
Implicit(false), Used(false), Referenced(false),
TopLevelDeclInObjCContainer(false), Access(AS_none), FromASTFile(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
CacheValidAndLinkage(0) {
if (StatisticsEnabled) add(DK);
}
@ -550,22 +570,21 @@ public:
/// global variable, etc.) that is lexically inside an objc container
/// definition.
bool isTopLevelDeclInObjCContainer() const {
return NextInContextAndBits.getInt() & TopLevelDeclInObjCContainerFlag;
return TopLevelDeclInObjCContainer;
}
void setTopLevelDeclInObjCContainer(bool V = true) {
unsigned Bits = NextInContextAndBits.getInt();
if (V)
Bits |= TopLevelDeclInObjCContainerFlag;
else
Bits &= ~TopLevelDeclInObjCContainerFlag;
NextInContextAndBits.setInt(Bits);
TopLevelDeclInObjCContainer = V;
}
/// \brief Looks on this and related declarations for an applicable
/// external source symbol attribute.
ExternalSourceSymbolAttr *getExternalSourceSymbolAttr() const;
/// \brief Whether this declaration was marked as being private to the
/// module in which it was defined.
bool isModulePrivate() const {
return NextInContextAndBits.getInt() & ModulePrivateFlag;
return getModuleOwnershipKind() == ModuleOwnershipKind::ModulePrivate;
}
/// \brief Whether this declaration is exported (by virtue of being lexically
@ -580,15 +599,14 @@ public:
const Attr *getDefiningAttr() const;
protected:
/// \brief Specify whether this declaration was marked as being private
/// \brief Specify that this declaration was marked as being private
/// to the module in which it was defined.
void setModulePrivate(bool MP = true) {
unsigned Bits = NextInContextAndBits.getInt();
if (MP)
Bits |= ModulePrivateFlag;
else
Bits &= ~ModulePrivateFlag;
NextInContextAndBits.setInt(Bits);
void setModulePrivate() {
// The module-private specifier has no effect on unowned declarations.
// FIXME: We should track this in some way for source fidelity.
if (getModuleOwnershipKind() == ModuleOwnershipKind::Unowned)
return;
setModuleOwnershipKind(ModuleOwnershipKind::ModulePrivate);
}
/// \brief Set the owning module ID.
@ -616,6 +634,14 @@ public:
getAvailability(std::string *Message = nullptr,
VersionTuple EnclosingVersion = VersionTuple()) const;
/// \brief Retrieve the version of the target platform in which this
/// declaration was introduced.
///
/// \returns An empty version tuple if this declaration has no 'introduced'
/// availability attributes, or the version tuple that's specified in the
/// attribute otherwise.
VersionTuple getVersionIntroduced() const;
/// \brief Determine whether this declaration is marked 'deprecated'.
///
/// \param Message If non-NULL and the declaration is deprecated,
@ -654,20 +680,19 @@ public:
/// 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;
}
@ -680,7 +705,7 @@ public:
/// \brief Get the imported owning module, if this decl is from an imported
/// (non-local) module.
Module *getImportedOwningModule() const {
if (!isFromASTFile())
if (!isFromASTFile() || !hasOwningModule())
return nullptr;
return getOwningModuleSlow();
@ -689,16 +714,59 @@ public:
/// \brief Get the local owning module, if known. Returns nullptr if owner is
/// not yet known or declaration is not from a module.
Module *getLocalOwningModule() const {
if (isFromASTFile() || !Hidden)
if (isFromASTFile() || !hasOwningModule())
return nullptr;
assert(hasLocalOwningModuleStorage() &&
"owned local decl but no local module storage");
return reinterpret_cast<Module *const *>(this)[-1];
}
void setLocalOwningModule(Module *M) {
assert(!isFromASTFile() && Hidden && hasLocalOwningModuleStorage() &&
assert(!isFromASTFile() && hasOwningModule() &&
hasLocalOwningModuleStorage() &&
"should not have a cached owning module");
reinterpret_cast<Module **>(this)[-1] = M;
}
/// Is this declaration owned by some module?
bool hasOwningModule() const {
return getModuleOwnershipKind() != ModuleOwnershipKind::Unowned;
}
/// Get the module that owns this declaration.
Module *getOwningModule() const {
return isFromASTFile() ? getImportedOwningModule() : getLocalOwningModule();
}
/// \brief Determine whether this declaration might be hidden from name
/// lookup. Note that the declaration might be visible even if this returns
/// \c false, if the owning module is visible within the query context.
// FIXME: Rename this to make it clearer what it does.
bool isHidden() const {
return (int)getModuleOwnershipKind() > (int)ModuleOwnershipKind::Visible;
}
/// Set that this declaration is globally visible, even if it came from a
/// module that is not visible.
void setVisibleDespiteOwningModule() {
if (isHidden())
setModuleOwnershipKind(ModuleOwnershipKind::Visible);
}
/// \brief Get the kind of module ownership for this declaration.
ModuleOwnershipKind getModuleOwnershipKind() const {
return NextInContextAndBits.getInt();
}
/// \brief Set whether this declaration is hidden from name lookup.
void setModuleOwnershipKind(ModuleOwnershipKind MOK) {
assert(!(getModuleOwnershipKind() == ModuleOwnershipKind::Unowned &&
MOK != ModuleOwnershipKind::Unowned && !isFromASTFile() &&
!hasLocalOwningModuleStorage()) &&
"no storage available for owning module for this declaration");
NextInContextAndBits.setInt(MOK);
}
unsigned getIdentifierNamespace() const {
return IdentifierNamespace;
}
@ -1030,7 +1098,7 @@ public:
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 +1879,8 @@ public:
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;

View File

@ -203,6 +203,11 @@ public:
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 @@ public:
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 @@ public:
/// \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
@ -1548,10 +1563,13 @@ public:
/// \param Paths used to record the paths from this class to its base class
/// subobjects that match the search criteria.
///
/// \param LookupInDependent can be set to true to extend the search to
/// dependent base classes.
///
/// \returns true if there exists any path from this class to a base class
/// subobject that matches the search criteria.
bool lookupInBases(BaseMatchesCallback BaseMatches,
CXXBasePaths &Paths) const;
bool lookupInBases(BaseMatchesCallback BaseMatches, CXXBasePaths &Paths,
bool LookupInDependent = false) const;
/// \brief Base-class lookup callback that determines whether the given
/// base class specifier refers to a specific class declaration.
@ -1592,6 +1610,16 @@ public:
static bool FindOrdinaryMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path, DeclarationName Name);
/// \brief Base-class lookup callback that determines whether there exists
/// a member with the given name.
///
/// This callback can be used with \c lookupInBases() to find members
/// of the given name within a C++ class hierarchy, including dependent
/// classes.
static bool
FindOrdinaryMemberInDependentClasses(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path, DeclarationName Name);
/// \brief Base-class lookup callback that determines whether there exists
/// an OpenMP declare reduction member with the given name.
///
@ -1618,6 +1646,14 @@ public:
/// \brief Get the indirect primary bases for this class.
void getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet& Bases) const;
/// Performs an imprecise lookup of a dependent name in this class.
///
/// This function does not follow strict semantic rules and should be used
/// only when lookup rules can be relaxed, e.g. indexing.
std::vector<const NamedDecl *>
lookupDependentName(const DeclarationName &Name,
llvm::function_ref<bool(const NamedDecl *ND)> Filter);
/// Renders and displays an inheritance diagram
/// for this C++ class and all of its base classes (transitively) using
/// GraphViz.
@ -1738,6 +1774,58 @@ public:
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
@ -1798,6 +1886,19 @@ public:
return (CD->begin_overridden_methods() != CD->end_overridden_methods());
}
/// If it's possible to devirtualize a call to this method, return the called
/// function. Otherwise, return null.
/// \param Base The object on which this virtual function is called.
/// \param IsAppleKext True if we are compiling for Apple kext.
CXXMethodDecl *getDevirtualizedMethod(const Expr *Base, bool IsAppleKext);
const CXXMethodDecl *getDevirtualizedMethod(const Expr *Base,
bool IsAppleKext) const {
return const_cast<CXXMethodDecl *>(this)->getDevirtualizedMethod(
Base, IsAppleKext);
}
/// \brief Determine whether this is a usual deallocation function
/// (C++ [basic.stc.dynamic.deallocation]p2), which is an overloaded
/// delete or delete[] operator with a particular signature.
@ -2161,13 +2262,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 +2278,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 +2295,6 @@ public:
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 +2358,14 @@ public:
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 +2501,14 @@ public:
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 +2531,16 @@ public:
/// \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 +2552,12 @@ public:
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 +2569,13 @@ public:
/// 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; }

View File

@ -131,7 +131,7 @@ public:
} 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);

View File

@ -381,15 +381,17 @@ public:
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 @@ private:
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 @@ public:
}
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; }
@ -1027,10 +1039,9 @@ public:
typedef llvm::DenseMap<std::pair<IdentifierInfo*,
unsigned/*isClassProperty*/>,
ObjCPropertyDecl*> PropertyMap;
typedef llvm::DenseMap<const ObjCProtocolDecl *, ObjCPropertyDecl*>
ProtocolPropertyMap;
typedef llvm::SmallDenseSet<const ObjCProtocolDecl *, 8> ProtocolPropertySet;
typedef llvm::SmallVector<ObjCPropertyDecl*, 8> PropertyDeclOrder;
/// This routine collects list of properties to be implemented in the class.
@ -2147,7 +2158,8 @@ public:
PropertyDeclOrder &PO) const override;
void collectInheritedProtocolProperties(const ObjCPropertyDecl *Property,
ProtocolPropertyMap &PM) const;
ProtocolPropertySet &PS,
PropertyDeclOrder &PO) const;
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ObjCProtocol; }
@ -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 @@ public:
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 @@ public:
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),

View File

@ -344,6 +344,32 @@ public:
// 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 @@ public:
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 @@ public:
}
SourceRange getSourceRange() const override LLVM_READONLY {
return SourceRange(TemplateParams->getTemplateLoc(),
return SourceRange(getTemplateParameters()->getTemplateLoc(),
TemplatedDecl.getPointer()->getSourceRange().getEnd());
}
@ -407,7 +453,29 @@ protected:
/// (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 @@ protected:
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 @@ public:
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 @@ public:
/// 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 @@ protected:
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 @@ public:
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 @@ public:
/// 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 @@ public:
/// 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

View File

@ -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 @@ public:
CXXConstructorName,
CXXDestructorName,
CXXConversionFunctionName,
CXXDeductionGuideName,
CXXOperatorName,
CXXLiteralOperatorName,
CXXUsingDirective
@ -118,42 +121,36 @@ private:
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 @@ public:
/// 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 @@ public:
/// 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);

View File

@ -115,6 +115,7 @@ protected:
ExprBits.InstantiationDependent = ID;
ExprBits.ValueKind = VK;
ExprBits.ObjectKind = OK;
assert(ExprBits.ObjectKind == OK && "truncated kind");
ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
setType(T);
}
@ -907,6 +908,10 @@ public:
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 @@ public:
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 @@ public:
// 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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
// 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 @@ public:
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 @@ public:
// 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 @@ public:
// 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 @@ public:
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 @@ public:
// Iterators
child_range children();
const_child_range children() const;
};
//===----------------------------------------------------------------------===//
@ -2153,6 +2192,9 @@ public:
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 @@ public:
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 @@ public:
// 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 @@ public:
// 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 @@ public:
// 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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ protected:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
// 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 @@ public:
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 @@ public:
// 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 @@ public:
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 @@ public:
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 @@ public:
// 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 @@ public:
// 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;
@ -4192,6 +4284,9 @@ public:
}
Designator *getDesignator(unsigned Idx) { return &designators()[Idx]; }
const Designator *getDesignator(unsigned Idx) const {
return &designators()[Idx];
}
void setDesignators(const ASTContext &C, const Designator *Desigs,
unsigned NumDesigs);
@ -4254,6 +4349,10 @@ public:
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 +4386,9 @@ public:
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 +4434,10 @@ public:
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 +4499,9 @@ public:
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 +4530,9 @@ public:
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 +4567,9 @@ public:
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 +4616,9 @@ public:
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 +4739,9 @@ public:
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 +4810,9 @@ public:
// 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 +4854,9 @@ public:
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 +4902,9 @@ public:
// 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 +5043,15 @@ public:
}
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 +5157,9 @@ public:
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 +5178,10 @@ public:
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(); }

View File

@ -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 @@ public:
// 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 @@ public:
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 @@ public:
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)

View 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

View File

@ -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 @@ public:
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.
///

View File

@ -49,7 +49,7 @@ public:
NSStr_initWithString,
NSStr_initWithUTF8String
};
static const unsigned NumNSStringMethods = 5;
static const unsigned NumNSStringMethods = 6;
IdentifierInfo *getNSClassId(NSClassIdKindKind K) const;
@ -112,7 +112,7 @@ public:
NSMutableDict_setObjectForKeyedSubscript,
NSMutableDict_setValueForKey
};
static const unsigned NumNSDictionaryMethods = 14;
static const unsigned NumNSDictionaryMethods = 13;
/// \brief The Objective-C NSDictionary selectors.
Selector getNSDictionarySelector(NSDictionaryMethodKind MK) const;

View 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 NestedNameSpecifier;
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

View File

@ -20,6 +20,7 @@
#include "clang/AST/Stmt.h"
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/MapVector.h"
namespace clang {
@ -76,10 +77,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 +96,8 @@ public:
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 +204,7 @@ public:
/// 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 +235,31 @@ public:
///
/// \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 +346,7 @@ public:
/// 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 +361,29 @@ public:
/// \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; }
@ -1866,6 +1890,217 @@ public:
}
};
/// This represents clause 'task_reduction' in the '#pragma omp taskgroup'
/// directives.
///
/// \code
/// #pragma omp taskgroup task_reduction(+:a,b)
/// \endcode
/// In this example directive '#pragma omp taskgroup' has clause
/// 'task_reduction' with operator '+' and the variables 'a' and 'b'.
///
class OMPTaskReductionClause final
: public OMPVarListClause<OMPTaskReductionClause>,
public OMPClauseWithPostUpdate,
private llvm::TrailingObjects<OMPTaskReductionClause, Expr *> {
friend TrailingObjects;
friend OMPVarListClause;
friend class OMPClauseReader;
/// Location of ':'.
SourceLocation ColonLoc;
/// Nested name specifier for C++.
NestedNameSpecifierLoc QualifierLoc;
/// Name of custom operator.
DeclarationNameInfo NameInfo;
/// Build clause with number of variables \a N.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
/// \param ColonLoc Location of ':'.
/// \param N Number of the variables in the clause.
/// \param QualifierLoc The nested-name qualifier with location information
/// \param NameInfo The full name info for reduction identifier.
///
OMPTaskReductionClause(SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation ColonLoc, SourceLocation EndLoc,
unsigned N, NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo)
: OMPVarListClause<OMPTaskReductionClause>(OMPC_task_reduction, StartLoc,
LParenLoc, EndLoc, N),
OMPClauseWithPostUpdate(this), ColonLoc(ColonLoc),
QualifierLoc(QualifierLoc), NameInfo(NameInfo) {}
/// Build an empty clause.
///
/// \param N Number of variables.
///
explicit OMPTaskReductionClause(unsigned N)
: OMPVarListClause<OMPTaskReductionClause>(
OMPC_task_reduction, SourceLocation(), SourceLocation(),
SourceLocation(), N),
OMPClauseWithPostUpdate(this), ColonLoc(), QualifierLoc(), NameInfo() {}
/// Sets location of ':' symbol in clause.
void setColonLoc(SourceLocation CL) { ColonLoc = CL; }
/// Sets the name info for specified reduction identifier.
void setNameInfo(DeclarationNameInfo DNI) { NameInfo = DNI; }
/// Sets the nested name specifier.
void setQualifierLoc(NestedNameSpecifierLoc NSL) { QualifierLoc = NSL; }
/// Set list of helper expressions, required for proper codegen of the clause.
/// These expressions represent private copy of the reduction variable.
void setPrivates(ArrayRef<Expr *> Privates);
/// Get the list of helper privates.
MutableArrayRef<Expr *> getPrivates() {
return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
}
ArrayRef<const Expr *> getPrivates() const {
return llvm::makeArrayRef(varlist_end(), varlist_size());
}
/// Set list of helper expressions, required for proper codegen of the clause.
/// These expressions represent LHS expression in the final reduction
/// expression performed by the reduction clause.
void setLHSExprs(ArrayRef<Expr *> LHSExprs);
/// Get the list of helper LHS expressions.
MutableArrayRef<Expr *> getLHSExprs() {
return MutableArrayRef<Expr *>(getPrivates().end(), varlist_size());
}
ArrayRef<const Expr *> getLHSExprs() const {
return llvm::makeArrayRef(getPrivates().end(), varlist_size());
}
/// Set list of helper expressions, required for proper codegen of the clause.
/// These expressions represent RHS expression in the final reduction
/// expression performed by the reduction clause. Also, variables in these
/// expressions are used for proper initialization of reduction copies.
void setRHSExprs(ArrayRef<Expr *> RHSExprs);
/// Get the list of helper destination expressions.
MutableArrayRef<Expr *> getRHSExprs() {
return MutableArrayRef<Expr *>(getLHSExprs().end(), varlist_size());
}
ArrayRef<const Expr *> getRHSExprs() const {
return llvm::makeArrayRef(getLHSExprs().end(), varlist_size());
}
/// Set list of helper reduction expressions, required for proper
/// codegen of the clause. These expressions are binary expressions or
/// operator/custom reduction call that calculates new value from source
/// helper expressions to destination helper expressions.
void setReductionOps(ArrayRef<Expr *> ReductionOps);
/// Get the list of helper reduction expressions.
MutableArrayRef<Expr *> getReductionOps() {
return MutableArrayRef<Expr *>(getRHSExprs().end(), varlist_size());
}
ArrayRef<const Expr *> getReductionOps() const {
return llvm::makeArrayRef(getRHSExprs().end(), varlist_size());
}
public:
/// Creates clause with a list of variables \a VL.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param ColonLoc Location of ':'.
/// \param EndLoc Ending location of the clause.
/// \param VL The variables in the clause.
/// \param QualifierLoc The nested-name qualifier with location information
/// \param NameInfo The full name info for reduction identifier.
/// \param Privates List of helper expressions for proper generation of
/// private copies.
/// \param LHSExprs List of helper expressions for proper generation of
/// assignment operation required for copyprivate clause. This list represents
/// LHSs of the reduction expressions.
/// \param RHSExprs List of helper expressions for proper generation of
/// assignment operation required for copyprivate clause. This list represents
/// RHSs of the reduction expressions.
/// Also, variables in these expressions are used for proper initialization of
/// reduction copies.
/// \param ReductionOps List of helper expressions that represents reduction
/// expressions:
/// \code
/// LHSExprs binop RHSExprs;
/// operator binop(LHSExpr, RHSExpr);
/// <CutomReduction>(LHSExpr, RHSExpr);
/// \endcode
/// Required for proper codegen of final reduction operation performed by the
/// reduction clause.
/// \param PreInit Statement that must be executed before entering the OpenMP
/// region with this clause.
/// \param PostUpdate Expression that must be executed after exit from the
/// OpenMP region with this clause.
///
static OMPTaskReductionClause *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL,
NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo, ArrayRef<Expr *> Privates,
ArrayRef<Expr *> LHSExprs, ArrayRef<Expr *> RHSExprs,
ArrayRef<Expr *> ReductionOps, Stmt *PreInit, Expr *PostUpdate);
/// Creates an empty clause with the place for \a N variables.
///
/// \param C AST context.
/// \param N The number of variables.
///
static OMPTaskReductionClause *CreateEmpty(const ASTContext &C, unsigned N);
/// Gets location of ':' symbol in clause.
SourceLocation getColonLoc() const { return ColonLoc; }
/// Gets the name info for specified reduction identifier.
const DeclarationNameInfo &getNameInfo() const { return NameInfo; }
/// Gets the nested name specifier.
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
typedef MutableArrayRef<Expr *>::iterator helper_expr_iterator;
typedef ArrayRef<const Expr *>::iterator helper_expr_const_iterator;
typedef llvm::iterator_range<helper_expr_iterator> helper_expr_range;
typedef llvm::iterator_range<helper_expr_const_iterator>
helper_expr_const_range;
helper_expr_const_range privates() const {
return helper_expr_const_range(getPrivates().begin(), getPrivates().end());
}
helper_expr_range privates() {
return helper_expr_range(getPrivates().begin(), getPrivates().end());
}
helper_expr_const_range lhs_exprs() const {
return helper_expr_const_range(getLHSExprs().begin(), getLHSExprs().end());
}
helper_expr_range lhs_exprs() {
return helper_expr_range(getLHSExprs().begin(), getLHSExprs().end());
}
helper_expr_const_range rhs_exprs() const {
return helper_expr_const_range(getRHSExprs().begin(), getRHSExprs().end());
}
helper_expr_range rhs_exprs() {
return helper_expr_range(getRHSExprs().begin(), getRHSExprs().end());
}
helper_expr_const_range reduction_ops() const {
return helper_expr_const_range(getReductionOps().begin(),
getReductionOps().end());
}
helper_expr_range reduction_ops() {
return helper_expr_range(getReductionOps().begin(),
getReductionOps().end());
}
child_range children() {
return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
reinterpret_cast<Stmt **>(varlist_end()));
}
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_task_reduction;
}
};
/// \brief This represents clause 'linear' in the '#pragma omp ...'
/// directives.
///
@ -2978,7 +3213,7 @@ protected:
// Organize the components by declaration and retrieve the original
// expression. Original expressions are always the first component of the
// mappable component list.
llvm::DenseMap<ValueDecl *, SmallVector<MappableExprComponentListRef, 8>>
llvm::MapVector<ValueDecl *, SmallVector<MappableExprComponentListRef, 8>>
ComponentListMap;
{
auto CI = ComponentLists.begin();
@ -3456,7 +3691,7 @@ public:
/// 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 +3707,27 @@ public:
/// \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 +3753,7 @@ public:
/// 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 +3769,28 @@ public:
/// \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 '('.

View File

@ -593,6 +593,16 @@ bool RecursiveASTVisitor<Derived>::PostVisitStmt(Stmt *S) {
#define STMT(CLASS, PARENT) \
case Stmt::CLASS##Class: \
TRY_TO(WalkUpFrom##CLASS(static_cast<CLASS *>(S))); break;
#define INITLISTEXPR(CLASS, PARENT) \
case Stmt::CLASS##Class: \
{ \
auto ILE = static_cast<CLASS *>(S); \
if (auto Syn = ILE->isSemanticForm() ? ILE->getSyntacticForm() : ILE) \
TRY_TO(WalkUpFrom##CLASS(Syn)); \
if (auto Sem = ILE->isSemanticForm() ? ILE : ILE->getSemanticForm()) \
TRY_TO(WalkUpFrom##CLASS(Sem)); \
break; \
}
#include "clang/AST/StmtNodes.inc"
}
@ -774,6 +784,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,12 +1023,20 @@ 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, {})
DEF_TRAVERSE_TYPE(TemplateTypeParmType, {})
DEF_TRAVERSE_TYPE(SubstTemplateTypeParmType, {})
DEF_TRAVERSE_TYPE(SubstTemplateTypeParmPackType, {})
DEF_TRAVERSE_TYPE(SubstTemplateTypeParmType, {
TRY_TO(TraverseType(T->getReplacementType()));
})
DEF_TRAVERSE_TYPE(SubstTemplateTypeParmPackType, {
TRY_TO(TraverseTemplateArgument(T->getArgumentPack()));
})
DEF_TRAVERSE_TYPE(TemplateSpecializationType, {
TRY_TO(TraverseTemplateName(T->getTemplateName()));
@ -1232,11 +1255,20 @@ 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, {})
DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmType, {})
DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmPackType, {})
DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmType, {
TRY_TO(TraverseType(TL.getTypePtr()->getReplacementType()));
})
DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmPackType, {
TRY_TO(TraverseTemplateArgument(TL.getTypePtr()->getArgumentPack()));
})
// FIXME: use the loc for the template name?
DEF_TRAVERSE_TYPELOC(TemplateSpecializationType, {
@ -1767,6 +1799,7 @@ DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); })
if (TypeSourceInfo *TSI = D->getTypeAsWritten()) \
TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); \
\
TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); \
if (!getDerived().shouldVisitTemplateInstantiations() && \
D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) \
/* Returning from here skips traversing the \
@ -1932,6 +1965,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().
@ -2191,13 +2231,15 @@ bool RecursiveASTVisitor<Derived>::TraverseSynOrSemInitListExpr(
// the syntactic and the semantic form.
//
// There is no guarantee about which form \p S takes when this method is called.
DEF_TRAVERSE_STMT(InitListExpr, {
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(
InitListExpr *S, DataRecursionQueue *Queue) {
TRY_TO(TraverseSynOrSemInitListExpr(
S->isSemanticForm() ? S->getSyntacticForm() : S, Queue));
TRY_TO(TraverseSynOrSemInitListExpr(
S->isSemanticForm() ? S : S->getSemanticForm(), Queue));
ShouldVisitChildren = false;
})
return true;
}
// GenericSelectionExpr is a special case because the types and expressions
// are interleaved. We also need to watch out for null types (default
@ -2305,7 +2347,7 @@ DEF_TRAVERSE_STMT(LambdaExpr, {
}
TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
FunctionProtoTypeLoc Proto = TL.castAs<FunctionProtoTypeLoc>();
FunctionProtoTypeLoc Proto = TL.getAsAdjusted<FunctionProtoTypeLoc>();
if (S->hasExplicitParameters() && S->hasExplicitResultType()) {
// Visit the whole type.
@ -2495,6 +2537,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 +2759,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 +2773,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;
}
@ -2966,6 +3016,28 @@ RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) {
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPTaskReductionClause(
OMPTaskReductionClause *C) {
TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc()));
TRY_TO(TraverseDeclarationNameInfo(C->getNameInfo()));
TRY_TO(VisitOMPClauseList(C));
TRY_TO(VisitOMPClauseWithPostUpdate(C));
for (auto *E : C->privates()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->lhs_exprs()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->rhs_exprs()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->reduction_ops()) {
TRY_TO(TraverseStmt(E));
}
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPFlushClause(OMPFlushClause *C) {
TRY_TO(VisitOMPClauseList(C));
@ -2993,6 +3065,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 +3073,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;
}

View File

@ -21,6 +21,60 @@
namespace clang {
class ASTContext;
// Some notes on redeclarables:
//
// - Every redeclarable is on a circular linked list.
//
// - Every decl has a pointer to the first element of the chain _and_ a
// DeclLink that may point to one of 3 possible states:
// - the "previous" (temporal) element in the chain
// - the "latest" (temporal) element in the chain
// - the an "uninitialized-latest" value (when newly-constructed)
//
// - The first element is also often called the canonical element. Every
// element has a pointer to it so that "getCanonical" can be fast.
//
// - Most links in the chain point to previous, except the link out of
// the first; it points to latest.
//
// - Elements are called "first", "previous", "latest" or
// "most-recent" when referring to temporal order: order of addition
// to the chain.
//
// - To make matters confusing, the DeclLink type uses the term "next"
// for its pointer-storage internally (thus functions like
// NextIsPrevious). It's easiest to just ignore the implementation of
// DeclLink when making sense of the redeclaration chain.
//
// - There's also a "definition" link for several types of
// redeclarable, where only one definition should exist at any given
// time (and the defn pointer is stored in the decl's "data" which
// is copied to every element on the chain when it's changed).
//
// Here is some ASCII art:
//
// "first" "latest"
// "canonical" "most recent"
// +------------+ first +--------------+
// | | <--------------------------- | |
// | | | |
// | | | |
// | | +--------------+ | |
// | | first | | | |
// | | <---- | | | |
// | | | | | |
// | @class A | link | @interface A | link | @class A |
// | seen first | <---- | seen second | <---- | seen third |
// | | | | | |
// +------------+ +--------------+ +--------------+
// | data | defn | data | defn | data |
// | | ----> | | <---- | |
// +------------+ +--------------+ +--------------+
// | | ^ ^
// | |defn | |
// | link +-----+ |
// +-->-------------------------------------------+
/// \brief Provides common interface for the Decls that can be redeclared.
template<typename decl_type>
class Redeclarable {

View File

@ -39,6 +39,7 @@ namespace clang {
class Expr;
class IdentifierInfo;
class LabelDecl;
class ODRHash;
class ParmVarDecl;
class PrinterHelper;
struct PrintingPolicy;
@ -126,13 +127,13 @@ protected:
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 @@ protected:
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 @@ protected:
ObjCIndirectCopyRestoreExprBitfields ObjCIndirectCopyRestoreExprBits;
InitListExprBitfields InitListExprBits;
TypeTraitExprBitfields TypeTraitExprBits;
CoawaitExprBitfields CoawaitBits;
};
friend class ASTStmtReader;
@ -340,6 +350,8 @@ protected:
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 @@ public:
/// 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

View File

@ -296,7 +296,9 @@ public:
/// \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.
@ -306,66 +308,106 @@ class CoroutineBodyStmt : public Stmt {
OnFallthrough, ///< Handler for control flow falling off the body.
Allocate, ///< Coroutine frame memory allocation.
Deallocate, ///< Coroutine frame memory deallocation.
ReturnValue, ///< Return value for thunk function.
ReturnValue, ///< Return value for thunk function: p.get_return_object().
ResultDecl, ///< Declaration holding the result of get_return_object.
ReturnStmt, ///< Return statement for the 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;
Expr *ReturnValue = nullptr;
Stmt *ResultDecl = nullptr;
Stmt *ReturnStmt = 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<Expr>(getStoredStmts()[SubStmt::ReturnValue]);
}
Stmt *getResultDecl() const { return getStoredStmts()[SubStmt::ResultDecl]; }
Stmt *getReturnStmt() const { return getStoredStmts()[SubStmt::ReturnStmt]; }
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 +432,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 +457,9 @@ public:
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();

View File

@ -118,6 +118,8 @@ public:
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

View File

@ -198,6 +198,26 @@ public:
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) {
@ -298,12 +318,18 @@ class OMPLoopDirective : public OMPExecutableDirective {
/// \brief Offsets to the stored exprs.
/// This enumeration contains offsets to all the pointers to children
/// expressions stored in OMPLoopDirective.
/// The first 9 children are nesessary for all the loop directives, and
/// the next 10 are specific to the worksharing ones.
/// The first 9 children are necessary for all the loop directives,
/// the next 8 are specific to the worksharing ones, and the next 11 are
/// used for combined constructs containing two pragmas associated to loops.
/// After the fixed children, three arrays of length CollapsedNum are
/// 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 +345,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 8 exprs are used by worksharing and distribute loops only.
IsLastIterVariableOffset = 9,
LowerBoundVariableOffset = 10,
UpperBoundVariableOffset = 11,
@ -328,11 +354,22 @@ class OMPLoopDirective : public OMPExecutableDirective {
NextLowerBoundOffset = 14,
NextUpperBoundOffset = 15,
NumIterationsOffset = 16,
// Offset to the end for worksharing loop directives.
WorksharingEnd = 17,
PrevLowerBoundVariableOffset = 17,
PrevUpperBoundVariableOffset = 18,
DistIncOffset = 19,
PrevEnsureUpperBoundOffset = 20,
CombinedLowerBoundVariableOffset = 21,
CombinedUpperBoundVariableOffset = 22,
CombinedEnsureUpperBoundOffset = 23,
CombinedInitOffset = 24,
CombinedConditionOffset = 25,
CombinedNextLowerBoundOffset = 26,
CombinedNextUpperBoundOffset = 27,
// Offset to the end (and start of the following counters/updates/finals
// arrays) for worksharing loop directives.
WorksharingEnd = 19,
// arrays) for combined distribute loop directives.
CombinedDistributeEnd = 28,
};
/// \brief Get the counters storage.
@ -396,11 +433,12 @@ protected:
/// \brief Offset to the start of children expression arrays.
static unsigned getArraysOffset(OpenMPDirectiveKind Kind) {
return (isOpenMPWorksharingDirective(Kind) ||
isOpenMPTaskLoopDirective(Kind) ||
isOpenMPDistributeDirective(Kind))
? WorksharingEnd
: DefaultEnd;
if (isOpenMPLoopBoundSharingDirective(Kind))
return CombinedDistributeEnd;
if (isOpenMPWorksharingDirective(Kind) || isOpenMPTaskLoopDirective(Kind) ||
isOpenMPDistributeDirective(Kind))
return WorksharingEnd;
return DefaultEnd;
}
/// \brief Children number.
@ -488,19 +526,60 @@ protected:
*std::next(child_begin(), NumIterationsOffset) = NI;
}
void setPrevLowerBoundVariable(Expr *PrevLB) {
assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
isOpenMPTaskLoopDirective(getDirectiveKind()) ||
isOpenMPDistributeDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
*std::next(child_begin(), PrevLowerBoundVariableOffset) = PrevLB;
}
void setPrevUpperBoundVariable(Expr *PrevUB) {
assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
isOpenMPTaskLoopDirective(getDirectiveKind()) ||
isOpenMPDistributeDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
*std::next(child_begin(), PrevUpperBoundVariableOffset) = PrevUB;
}
void setDistInc(Expr *DistInc) {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
*std::next(child_begin(), DistIncOffset) = DistInc;
}
void setPrevEnsureUpperBound(Expr *PrevEUB) {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
*std::next(child_begin(), PrevEnsureUpperBoundOffset) = PrevEUB;
}
void setCombinedLowerBoundVariable(Expr *CombLB) {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
*std::next(child_begin(), CombinedLowerBoundVariableOffset) = CombLB;
}
void setCombinedUpperBoundVariable(Expr *CombUB) {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
*std::next(child_begin(), CombinedUpperBoundVariableOffset) = CombUB;
}
void setCombinedEnsureUpperBound(Expr *CombEUB) {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
*std::next(child_begin(), CombinedEnsureUpperBoundOffset) = CombEUB;
}
void setCombinedInit(Expr *CombInit) {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
*std::next(child_begin(), CombinedInitOffset) = CombInit;
}
void setCombinedCond(Expr *CombCond) {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
*std::next(child_begin(), CombinedConditionOffset) = CombCond;
}
void setCombinedNextLowerBound(Expr *CombNLB) {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
*std::next(child_begin(), CombinedNextLowerBoundOffset) = CombNLB;
}
void setCombinedNextUpperBound(Expr *CombNUB) {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
*std::next(child_begin(), CombinedNextUpperBoundOffset) = CombNUB;
}
void setCounters(ArrayRef<Expr *> A);
void setPrivateCounters(ArrayRef<Expr *> A);
void setInits(ArrayRef<Expr *> A);
@ -508,6 +587,33 @@ protected:
void setFinals(ArrayRef<Expr *> A);
public:
/// The expressions built to support OpenMP loops in combined/composite
/// pragmas (e.g. pragma omp distribute parallel for)
struct DistCombinedHelperExprs {
/// DistributeLowerBound - used when composing 'omp distribute' with
/// 'omp for' in a same construct.
Expr *LB;
/// DistributeUpperBound - used when composing 'omp distribute' with
/// 'omp for' in a same construct.
Expr *UB;
/// DistributeEnsureUpperBound - used when composing 'omp distribute'
/// with 'omp for' in a same construct, EUB depends on DistUB
Expr *EUB;
/// Distribute loop iteration variable init used when composing 'omp
/// distribute'
/// with 'omp for' in a same construct
Expr *Init;
/// Distribute Loop condition used when composing 'omp distribute'
/// with 'omp for' in a same construct
Expr *Cond;
/// Update of LowerBound for statically sheduled omp loops for
/// outer loop in combined constructs (e.g. 'distribute parallel for')
Expr *NLB;
/// Update of UpperBound for statically sheduled omp loops for
/// outer loop in combined constructs (e.g. 'distribute parallel for')
Expr *NUB;
};
/// \brief The expressions built for the OpenMP loop CodeGen for the
/// whole collapsed loop nest.
struct HelperExprs {
@ -535,7 +641,7 @@ public:
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 +653,16 @@ public:
/// \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.
@ -560,6 +676,9 @@ public:
/// Init statement for all captured expressions.
Stmt *PreInits;
/// Expressions used when combining OpenMP loop pragmas
DistCombinedHelperExprs DistCombinedFields;
/// \brief Check if all the expressions are built (does not check the
/// worksharing ones).
bool builtAll() {
@ -588,6 +707,8 @@ public:
NumIterations = nullptr;
PrevLB = nullptr;
PrevUB = nullptr;
DistInc = nullptr;
PrevEUB = nullptr;
Counters.resize(Size);
PrivateCounters.resize(Size);
Inits.resize(Size);
@ -601,6 +722,13 @@ public:
Finals[i] = nullptr;
}
PreInits = nullptr;
DistCombinedFields.LB = nullptr;
DistCombinedFields.UB = nullptr;
DistCombinedFields.EUB = nullptr;
DistCombinedFields.Init = nullptr;
DistCombinedFields.Cond = nullptr;
DistCombinedFields.NLB = nullptr;
DistCombinedFields.NUB = nullptr;
}
};
@ -704,21 +832,71 @@ public:
*std::next(child_begin(), NumIterationsOffset)));
}
Expr *getPrevLowerBoundVariable() const {
assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
isOpenMPTaskLoopDirective(getDirectiveKind()) ||
isOpenMPDistributeDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), PrevLowerBoundVariableOffset)));
}
Expr *getPrevUpperBoundVariable() const {
assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
isOpenMPTaskLoopDirective(getDirectiveKind()) ||
isOpenMPDistributeDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), PrevUpperBoundVariableOffset)));
}
Expr *getDistInc() const {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), DistIncOffset)));
}
Expr *getPrevEnsureUpperBound() const {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), PrevEnsureUpperBoundOffset)));
}
Expr *getCombinedLowerBoundVariable() const {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), CombinedLowerBoundVariableOffset)));
}
Expr *getCombinedUpperBoundVariable() const {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), CombinedUpperBoundVariableOffset)));
}
Expr *getCombinedEnsureUpperBound() const {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), CombinedEnsureUpperBoundOffset)));
}
Expr *getCombinedInit() const {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), CombinedInitOffset)));
}
Expr *getCombinedCond() const {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), CombinedConditionOffset)));
}
Expr *getCombinedNextLowerBound() const {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), CombinedNextLowerBoundOffset)));
}
Expr *getCombinedNextUpperBound() const {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), CombinedNextUpperBoundOffset)));
}
const Stmt *getBody() const {
// This relies on the loop form is already checked by Sema.
Stmt *Body = getAssociatedStmt()->IgnoreContainers(true);
@ -1717,7 +1895,7 @@ public:
}
};
/// \brief This represents '#pragma omp taskgroup' directive.
/// This represents '#pragma omp taskgroup' directive.
///
/// \code
/// #pragma omp taskgroup
@ -1725,39 +1903,45 @@ public:
///
class OMPTaskgroupDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
/// \brief Build directive with the given start and end location.
/// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
/// \param NumClauses Number of clauses.
///
OMPTaskgroupDirective(SourceLocation StartLoc, SourceLocation EndLoc)
OMPTaskgroupDirective(SourceLocation StartLoc, SourceLocation EndLoc,
unsigned NumClauses)
: OMPExecutableDirective(this, OMPTaskgroupDirectiveClass, OMPD_taskgroup,
StartLoc, EndLoc, 0, 1) {}
StartLoc, EndLoc, NumClauses, 1) {}
/// \brief Build an empty directive.
/// Build an empty directive.
/// \param NumClauses Number of clauses.
///
explicit OMPTaskgroupDirective()
explicit OMPTaskgroupDirective(unsigned NumClauses)
: OMPExecutableDirective(this, OMPTaskgroupDirectiveClass, OMPD_taskgroup,
SourceLocation(), SourceLocation(), 0, 1) {}
SourceLocation(), SourceLocation(), NumClauses,
1) {}
public:
/// \brief Creates directive.
/// Creates directive.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
///
static OMPTaskgroupDirective *Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation EndLoc,
Stmt *AssociatedStmt);
static OMPTaskgroupDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
/// \brief Creates an empty directive.
/// Creates an empty directive.
///
/// \param C AST context.
/// \param NumClauses Number of clauses.
///
static OMPTaskgroupDirective *CreateEmpty(const ASTContext &C, EmptyShell);
static OMPTaskgroupDirective *CreateEmpty(const ASTContext &C,
unsigned NumClauses, EmptyShell);
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPTaskgroupDirectiveClass;

View File

@ -119,10 +119,7 @@ private:
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 @@ private:
};
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);

View File

@ -333,6 +333,23 @@ public:
bool hasAddressSpace() const { return Mask & AddressSpaceMask; }
unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; }
bool hasTargetSpecificAddressSpace() const {
return getAddressSpace() >= LangAS::FirstTargetAddressSpace;
}
/// 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 || hasTargetSpecificAddressSpace());
if (Addr)
return Addr - LangAS::FirstTargetAddressSpace;
// 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 +1037,9 @@ public:
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,
@ -1379,7 +1399,7 @@ protected:
/// Extra information which affects how the function is called, like
/// regparm and the calling convention.
unsigned ExtInfo : 10;
unsigned ExtInfo : 11;
/// Used only by FunctionProtoType, put here to pack with the
/// other bitfields.
@ -1732,6 +1752,7 @@ public:
bool isTemplateTypeParmType() const; // C++ template type parameter
bool isNullPtrType() const; // C++11 std::nullptr_t
bool isAlignValT() const; // C++17 std::align_val_t
bool isStdByteType() const; // C++17 std::byte
bool isAtomicType() const; // C11 _Atomic()
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
@ -1744,7 +1765,6 @@ public:
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 +1805,8 @@ public:
}
/// \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 +1883,22 @@ public:
/// 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 +1908,13 @@ public:
/// 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;
@ -1972,10 +2012,11 @@ public:
Optional<NullabilityKind> getNullability(const ASTContext &context) const;
/// Determine whether the given type can have a nullability
/// specifier applied to it, i.e., if it is any kind of pointer type
/// or a dependent type that could instantiate to any kind of
/// pointer type.
bool canHaveNullability() const;
/// specifier applied to it, i.e., if it is any kind of pointer type.
///
/// \param ResultIfUnknown The value to return if we don't yet know whether
/// this type can have nullability because it is dependent.
bool canHaveNullability(bool ResultIfUnknown = true) const;
/// Retrieve the set of substitutions required when accessing a member
/// of the Objective-C receiver type that is declared in the given context.
@ -2057,7 +2098,7 @@ public:
: Type(Builtin, QualType(), /*Dependent=*/(K == Dependent),
/*InstantiationDependent=*/(K == Dependent),
/*VariablyModified=*/false,
/*Unexpanded paramter pack=*/false) {
/*Unexpanded parameter pack=*/false) {
BuiltinTypeBits.Kind = K;
}
@ -2905,19 +2946,23 @@ class FunctionType : public Type {
// * AST read and write
// * Codegen
class ExtInfo {
// Feel free to rearrange or add bits, but if you go over 10,
// Feel free to rearrange or add bits, but if you go over 11,
// you'll need to adjust both the Bits field below and
// Type::FunctionTypeBitfields.
// | CC |noreturn|produces|regparm|
// |0 .. 4| 5 | 6 | 7 .. 9|
// | CC |noreturn|produces|nocallersavedregs|regparm|
// |0 .. 4| 5 | 6 | 7 |8 .. 10|
//
// regparm is either 0 (no regparm attribute) or the regparm value+1.
enum { CallConvMask = 0x1F };
enum { NoReturnMask = 0x20 };
enum { ProducesResultMask = 0x40 };
enum { RegParmMask = ~(CallConvMask | NoReturnMask | ProducesResultMask),
RegParmOffset = 7 }; // Assumed to be the last field
enum { NoCallerSavedRegsMask = 0x80 };
enum {
RegParmMask = ~(CallConvMask | NoReturnMask | ProducesResultMask |
NoCallerSavedRegsMask),
RegParmOffset = 8
}; // Assumed to be the last field
uint16_t Bits;
@ -2928,13 +2973,13 @@ class FunctionType : public Type {
public:
// Constructor with no defaults. Use this when you know that you
// have all the elements (when reading an AST file for example).
ExtInfo(bool noReturn, bool hasRegParm, unsigned regParm, CallingConv cc,
bool producesResult) {
assert((!hasRegParm || regParm < 7) && "Invalid regparm value");
Bits = ((unsigned) cc) |
(noReturn ? NoReturnMask : 0) |
(producesResult ? ProducesResultMask : 0) |
(hasRegParm ? ((regParm + 1) << RegParmOffset) : 0);
ExtInfo(bool noReturn, bool hasRegParm, unsigned regParm, CallingConv cc,
bool producesResult, bool noCallerSavedRegs) {
assert((!hasRegParm || regParm < 7) && "Invalid regparm value");
Bits = ((unsigned)cc) | (noReturn ? NoReturnMask : 0) |
(producesResult ? ProducesResultMask : 0) |
(noCallerSavedRegs ? NoCallerSavedRegsMask : 0) |
(hasRegParm ? ((regParm + 1) << RegParmOffset) : 0);
}
// Constructor with all defaults. Use when for example creating a
@ -2947,6 +2992,7 @@ class FunctionType : public Type {
bool getNoReturn() const { return Bits & NoReturnMask; }
bool getProducesResult() const { return Bits & ProducesResultMask; }
bool getNoCallerSavedRegs() const { return Bits & NoCallerSavedRegsMask; }
bool getHasRegParm() const { return (Bits >> RegParmOffset) != 0; }
unsigned getRegParm() const {
unsigned RegParm = Bits >> RegParmOffset;
@ -2980,6 +3026,13 @@ class FunctionType : public Type {
return ExtInfo(Bits & ~ProducesResultMask);
}
ExtInfo withNoCallerSavedRegs(bool noCallerSavedRegs) const {
if (noCallerSavedRegs)
return ExtInfo(Bits | NoCallerSavedRegsMask);
else
return ExtInfo(Bits & ~NoCallerSavedRegsMask);
}
ExtInfo withRegParm(unsigned RegParm) const {
assert(RegParm < 7 && "Invalid regparm value");
return ExtInfo((Bits & ~RegParmMask) |
@ -3097,9 +3150,11 @@ public:
class ExtParameterInfo {
enum {
ABIMask = 0x0F,
IsConsumed = 0x10
IsConsumed = 0x10,
HasPassObjSize = 0x20,
};
unsigned char Data;
public:
ExtParameterInfo() : Data(0) {}
@ -3128,6 +3183,15 @@ public:
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;
@ -3815,6 +3879,7 @@ public:
attr_sptr,
attr_uptr,
attr_nonnull,
attr_ns_returns_retained,
attr_nullable,
attr_null_unspecified,
attr_objc_kindof,
@ -4089,25 +4154,60 @@ public:
}
};
/// \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 +4221,6 @@ public:
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 +4237,43 @@ public:
}
};
/// \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 +4470,9 @@ public:
const TemplateSpecializationType *getInjectedTST() const {
return cast<TemplateSpecializationType>(InjectedType.getTypePtr());
}
TemplateName getTemplateName() const {
return getInjectedTST()->getTemplateName();
}
CXXRecordDecl *getDecl() const;
@ -5718,10 +5846,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 +5863,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 +5973,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 +6056,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))

View File

@ -70,6 +70,13 @@ public:
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.
@ -1537,7 +1544,11 @@ class DependentSizedArrayTypeLoc :
public InheritingConcreteTypeLoc<ArrayTypeLoc,
DependentSizedArrayTypeLoc,
DependentSizedArrayType> {
public:
void initializeLocal(ASTContext &Context, SourceLocation Loc) {
ArrayTypeLoc::initializeLocal(Context, Loc);
setSizeExpr(getTypePtr()->getSizeExpr());
}
};
class VariableArrayTypeLoc :
@ -1827,9 +1838,25 @@ public:
}
};
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 +2199,24 @@ public:
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

View File

@ -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)

View File

@ -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());
}

View File

@ -154,6 +154,28 @@ public:
bool isRTTIKind() const { return isRTTIKind(getKind()); }
GlobalDecl getGlobalDecl() const {
assert(isUsedFunctionPointerKind() &&
"GlobalDecl can be created only from virtual function");
auto *DtorDecl = dyn_cast<CXXDestructorDecl>(getFunctionDecl());
switch (getKind()) {
case CK_FunctionPointer:
return GlobalDecl(getFunctionDecl());
case CK_CompleteDtorPointer:
return GlobalDecl(DtorDecl, CXXDtorType::Dtor_Complete);
case CK_DeletingDtorPointer:
return GlobalDecl(DtorDecl, CXXDtorType::Dtor_Deleting);
case CK_VCallOffset:
case CK_VBaseOffset:
case CK_OffsetToTop:
case CK_RTTI:
case CK_UnusedFunctionPointer:
llvm_unreachable("Only function pointers kinds");
}
llvm_unreachable("Should already return");
}
private:
static bool isFunctionPointerKind(Kind ComponentKind) {
return isUsedFunctionPointerKind(ComponentKind) ||

View File

@ -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.
///
@ -1150,6 +1223,20 @@ AST_MATCHER_P(InitListExpr, hasSyntacticForm,
InnerMatcher.matches(*SyntForm, Finder, Builder));
}
/// \brief Matches C++ initializer list expressions.
///
/// Given
/// \code
/// std::vector<int> a({ 1, 2, 3 });
/// std::vector<int> b = { 4, 5 };
/// int c[] = { 6, 7 };
/// std::pair<int, int> d = { 8, 9 };
/// \endcode
/// cxxStdInitializerListExpr()
/// matches "{ 1, 2, 3 }" and "{ 4, 5 }"
const internal::VariadicDynCastAllOfMatcher<Stmt,
CXXStdInitializerListExpr> cxxStdInitializerListExpr;
/// \brief Matches implicit initializers of init list expressions.
///
/// Given
@ -1333,7 +1420,7 @@ const internal::VariadicDynCastAllOfMatcher<
///
/// Example: Given
/// \code
/// struct T {void func()};
/// struct T {void func();};
/// T f();
/// void g(T);
/// \endcode
@ -2522,7 +2609,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 = ...
@ -3719,14 +3806,30 @@ AST_MATCHER_P(CompoundStmt, statementCountIs, unsigned, N) {
return Node.size() == N;
}
/// \brief Matches literals that are equal to the given value.
/// \brief Matches literals that are equal to the given value of type ValueT.
///
/// Example matches true (matcher = cxxBoolLiteral(equals(true)))
/// Given
/// \code
/// true
/// f('\0', false, 3.14, 42);
/// \endcode
/// characterLiteral(equals(0))
/// matches '\0'
/// cxxBoolLiteral(equals(false)) and cxxBoolLiteral(equals(0))
/// match false
/// floatLiteral(equals(3.14)) and floatLiteral(equals(314e-2))
/// match 3.14
/// integerLiteral(equals(42))
/// matches 42
///
/// Usable as: Matcher<CharacterLiteral>, Matcher<CXXBoolLiteral>,
/// Note that you cannot directly match a negative numeric literal because the
/// minus sign is not part of the literal: It is a unary operator whose operand
/// is the positive numeric literal. Instead, you must use a unaryOperator()
/// matcher to match the minus sign:
///
/// unaryOperator(hasOperatorName("-"),
/// hasUnaryOperand(integerLiteral(equals(13))))
///
/// Usable as: Matcher<CharacterLiteral>, Matcher<CXXBoolLiteralExpr>,
/// Matcher<FloatingLiteral>, Matcher<IntegerLiteral>
template <typename ValueT>
internal::PolymorphicMatcherWithParam1<internal::ValueEqualsMatcher, ValueT>
@ -3736,6 +3839,34 @@ equals(const ValueT &Value) {
ValueT>(Value);
}
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(equals,
AST_POLYMORPHIC_SUPPORTED_TYPES(CharacterLiteral,
CXXBoolLiteralExpr,
IntegerLiteral),
bool, Value, 0) {
return internal::ValueEqualsMatcher<NodeType, ParamT>(Value)
.matchesNode(Node);
}
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(equals,
AST_POLYMORPHIC_SUPPORTED_TYPES(CharacterLiteral,
CXXBoolLiteralExpr,
IntegerLiteral),
unsigned, Value, 1) {
return internal::ValueEqualsMatcher<NodeType, ParamT>(Value)
.matchesNode(Node);
}
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(equals,
AST_POLYMORPHIC_SUPPORTED_TYPES(CharacterLiteral,
CXXBoolLiteralExpr,
FloatingLiteral,
IntegerLiteral),
double, Value, 2) {
return internal::ValueEqualsMatcher<NodeType, ParamT>(Value)
.matchesNode(Node);
}
/// \brief Matches the operator Name of operator expressions (binary or
/// unary).
///
@ -5507,7 +5638,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

View File

@ -76,7 +76,7 @@ public:
ET_ParserInvalidToken = 106,
ET_ParserMalformedBindExpr = 107,
ET_ParserTrailingCode = 108,
ET_ParserUnsignedError = 109,
ET_ParserNumberError = 109,
ET_ParserOverloadedType = 110
};

View File

@ -19,8 +19,10 @@
/// \code
/// Grammar for the expressions supported:
/// <Expression> := <Literal> | <NamedValue> | <MatcherExpression>
/// <Literal> := <StringLiteral> | <Unsigned>
/// <Literal> := <StringLiteral> | <Boolean> | <Double> | <Unsigned>
/// <StringLiteral> := "quoted string"
/// <Boolean> := true | false
/// <Double> := [0-9]+.[0-9]* | [0-9]+.[0-9]*[eE][-+]?[0-9]+
/// <Unsigned> := [0-9]+
/// <NamedValue> := <Identifier>
/// <MatcherExpression> := <Identifier>(<ArgumentList>) |

View File

@ -35,6 +35,8 @@ class ArgKind {
public:
enum Kind {
AK_Matcher,
AK_Boolean,
AK_Double,
AK_Unsigned,
AK_String
};
@ -56,7 +58,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 +184,7 @@ public:
/// \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)
@ -241,6 +243,8 @@ struct VariantMatcher::TypedMatcherOps final : VariantMatcher::MatcherOps {
/// copy/assignment.
///
/// Supported types:
/// - \c bool
// - \c double
/// - \c unsigned
/// - \c llvm::StringRef
/// - \c VariantMatcher (\c DynTypedMatcher / \c Matcher<T>)
@ -253,14 +257,29 @@ public:
VariantValue &operator=(const VariantValue &Other);
/// \brief Specific constructors for each supported type.
VariantValue(bool Boolean);
VariantValue(double Double);
VariantValue(unsigned Unsigned);
VariantValue(StringRef String);
VariantValue(const VariantMatcher &Matchers);
/// \brief Constructs an \c unsigned value (disambiguation from bool).
VariantValue(int Signed) : VariantValue(static_cast<unsigned>(Signed)) {}
/// \brief Returns true iff this is not an empty value.
explicit operator bool() const { return hasValue(); }
bool hasValue() const { return Type != VT_Nothing; }
/// \brief Boolean value functions.
bool isBoolean() const;
bool getBoolean() const;
void setBoolean(bool Boolean);
/// \brief Double value functions.
bool isDouble() const;
double getDouble() const;
void setDouble(double Double);
/// \brief Unsigned value functions.
bool isUnsigned() const;
unsigned getUnsigned() const;
@ -281,7 +300,7 @@ public:
/// \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 +309,7 @@ public:
/// \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;
@ -303,6 +322,8 @@ private:
/// \brief All supported value types.
enum ValueType {
VT_Nothing,
VT_Boolean,
VT_Double,
VT_Unsigned,
VT_String,
VT_Matcher
@ -311,6 +332,8 @@ private:
/// \brief All supported value types.
union AllValues {
unsigned Unsigned;
double Double;
bool Boolean;
std::string *String;
VariantMatcher *Matcher;
};

View File

@ -38,15 +38,15 @@ typedef llvm::DomTreeNodeBase<CFGBlock> DomTreeNode;
class DominatorTree : public ManagedAnalysis {
virtual void anchor();
public:
llvm::DominatorTreeBase<CFGBlock>* DT;
llvm::DomTreeBase<CFGBlock>* DT;
DominatorTree() {
DT = new llvm::DominatorTreeBase<CFGBlock>(false);
DT = new llvm::DomTreeBase<CFGBlock>();
}
~DominatorTree() override { delete DT; }
llvm::DominatorTreeBase<CFGBlock>& getBase() { return *DT; }
llvm::DomTreeBase<CFGBlock>& getBase() { return *DT; }
/// \brief This method returns the root CFGBlock of the dominators tree.
///

View File

@ -426,6 +426,7 @@ public:
bool addImplicitDtors = false,
bool addInitializers = false,
bool addTemporaryDtors = false,
bool addLifetime = false,
bool synthesizeBodies = false,
bool addStaticInitBranches = false,
bool addCXXNewAllocator = true,

View File

@ -58,6 +58,7 @@ public:
Statement,
Initializer,
NewAllocator,
LifetimeEnds,
// dtor kind
AutomaticObjectDtor,
DeleteDtor,
@ -167,6 +168,28 @@ private:
}
};
/// Represents the point where the lifetime of an automatic object ends
class CFGLifetimeEnds : public CFGElement {
public:
explicit CFGLifetimeEnds(const VarDecl *var, const Stmt *stmt)
: CFGElement(LifetimeEnds, var, stmt) {}
const VarDecl *getVarDecl() const {
return static_cast<VarDecl *>(Data1.getPointer());
}
const Stmt *getTriggerStmt() const {
return static_cast<Stmt *>(Data2.getPointer());
}
private:
friend class CFGElement;
CFGLifetimeEnds() {}
static bool isKind(const CFGElement &elem) {
return elem.getKind() == LifetimeEnds;
}
};
/// CFGImplicitDtor - Represents C++ object destructor implicitly generated
/// by compiler on various occasions.
class CFGImplicitDtor : public CFGElement {
@ -701,6 +724,10 @@ public:
Elements.push_back(CFGAutomaticObjDtor(VD, S), C);
}
void appendLifetimeEnds(VarDecl *VD, Stmt *S, BumpVectorContext &C) {
Elements.push_back(CFGLifetimeEnds(VD, S), C);
}
void appendDeleteDtor(CXXRecordDecl *RD, CXXDeleteExpr *DE, BumpVectorContext &C) {
Elements.push_back(CFGDeleteDtor(RD, DE), C);
}
@ -717,6 +744,19 @@ public:
*I = CFGAutomaticObjDtor(VD, S);
return ++I;
}
// Scope leaving must be performed in reversed order. So insertion is in two
// steps. First we prepare space for some number of elements, then we insert
// the elements beginning at the last position in prepared space.
iterator beginLifetimeEndsInsert(iterator I, size_t Cnt,
BumpVectorContext &C) {
return iterator(
Elements.insert(I.base(), Cnt, CFGLifetimeEnds(nullptr, nullptr), C));
}
iterator insertLifetimeEnds(iterator I, VarDecl *VD, Stmt *S) {
*I = CFGLifetimeEnds(VD, S);
return ++I;
}
};
/// \brief CFGCallback defines methods that should be called when a logical
@ -753,6 +793,7 @@ public:
bool AddEHEdges;
bool AddInitializers;
bool AddImplicitDtors;
bool AddLifetime;
bool AddTemporaryDtors;
bool AddStaticInitBranches;
bool AddCXXNewAllocator;
@ -774,8 +815,10 @@ public:
BuildOptions()
: forcedBlkExprs(nullptr), Observer(nullptr),
PruneTriviallyFalseEdges(true), AddEHEdges(false),
PruneTriviallyFalseEdges(true),
AddEHEdges(false),
AddInitializers(false), AddImplicitDtors(false),
AddLifetime(false),
AddTemporaryDtors(false), AddStaticInitBranches(false),
AddCXXNewAllocator(false), AddCXXDefaultInitExprInCtors(false) {}
};

View File

@ -98,7 +98,7 @@ public:
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.

View File

@ -15,10 +15,12 @@
#ifndef LLVM_CLANG_AST_CLONEDETECTION_H
#define LLVM_CLANG_AST_CLONEDETECTION_H
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Regex.h"
#include <vector>
namespace clang {
@ -29,7 +31,193 @@ class VarDecl;
class ASTContext;
class CompoundStmt;
/// \brief Identifies a list of statements.
namespace clone_detection {
/// Returns a string that represents all macro expansions that expanded into the
/// given SourceLocation.
///
/// If 'getMacroStack(A) == getMacroStack(B)' is true, then the SourceLocations
/// A and B are expanded from the same macros in the same order.
std::string getMacroStack(SourceLocation Loc, ASTContext &Context);
/// Collects the data of a single Stmt.
///
/// This class defines what a code clone is: If it collects for two statements
/// the same data, then those two statements are considered to be clones of each
/// other.
///
/// All collected data is forwarded to the given data consumer of the type T.
/// The data consumer class needs to provide a member method with the signature:
/// update(StringRef Str)
template <typename T>
class StmtDataCollector : public ConstStmtVisitor<StmtDataCollector<T>> {
ASTContext &Context;
/// The data sink to which all data is forwarded.
T &DataConsumer;
public:
/// Collects data of the given Stmt.
/// \param S The given statement.
/// \param Context The ASTContext of S.
/// \param DataConsumer The data sink to which all data is forwarded.
StmtDataCollector(const Stmt *S, ASTContext &Context, T &DataConsumer)
: Context(Context), DataConsumer(DataConsumer) {
this->Visit(S);
}
typedef unsigned DataPiece;
// Below are utility methods for appending different data to the vector.
void addData(DataPiece Integer) {
DataConsumer.update(
StringRef(reinterpret_cast<char *>(&Integer), sizeof(Integer)));
}
void addData(llvm::StringRef Str) { DataConsumer.update(Str); }
void addData(const QualType &QT) { addData(QT.getAsString()); }
// The functions below collect the class specific data of each Stmt subclass.
// Utility macro for defining a visit method for a given class. This method
// calls back to the ConstStmtVisitor to visit all parent classes.
#define DEF_ADD_DATA(CLASS, CODE) \
void Visit##CLASS(const CLASS *S) { \
CODE; \
ConstStmtVisitor<StmtDataCollector>::Visit##CLASS(S); \
}
DEF_ADD_DATA(Stmt, {
addData(S->getStmtClass());
// This ensures that macro generated code isn't identical to macro-generated
// code.
addData(getMacroStack(S->getLocStart(), Context));
addData(getMacroStack(S->getLocEnd(), Context));
})
DEF_ADD_DATA(Expr, { addData(S->getType()); })
//--- Builtin functionality ----------------------------------------------//
DEF_ADD_DATA(ArrayTypeTraitExpr, { addData(S->getTrait()); })
DEF_ADD_DATA(ExpressionTraitExpr, { addData(S->getTrait()); })
DEF_ADD_DATA(PredefinedExpr, { addData(S->getIdentType()); })
DEF_ADD_DATA(TypeTraitExpr, {
addData(S->getTrait());
for (unsigned i = 0; i < S->getNumArgs(); ++i)
addData(S->getArg(i)->getType());
})
//--- Calls --------------------------------------------------------------//
DEF_ADD_DATA(CallExpr, {
// Function pointers don't have a callee and we just skip hashing it.
if (const FunctionDecl *D = S->getDirectCallee()) {
// If the function is a template specialization, we also need to handle
// the template arguments as they are not included in the qualified name.
if (auto Args = D->getTemplateSpecializationArgs()) {
std::string ArgString;
// Print all template arguments into ArgString
llvm::raw_string_ostream OS(ArgString);
for (unsigned i = 0; i < Args->size(); ++i) {
Args->get(i).print(Context.getLangOpts(), OS);
// Add a padding character so that 'foo<X, XX>()' != 'foo<XX, X>()'.
OS << '\n';
}
OS.flush();
addData(ArgString);
}
addData(D->getQualifiedNameAsString());
}
})
//--- Exceptions ---------------------------------------------------------//
DEF_ADD_DATA(CXXCatchStmt, { addData(S->getCaughtType()); })
//--- C++ OOP Stmts ------------------------------------------------------//
DEF_ADD_DATA(CXXDeleteExpr, {
addData(S->isArrayFormAsWritten());
addData(S->isGlobalDelete());
})
//--- Casts --------------------------------------------------------------//
DEF_ADD_DATA(ObjCBridgedCastExpr, { addData(S->getBridgeKind()); })
//--- Miscellaneous Exprs ------------------------------------------------//
DEF_ADD_DATA(BinaryOperator, { addData(S->getOpcode()); })
DEF_ADD_DATA(UnaryOperator, { addData(S->getOpcode()); })
//--- Control flow -------------------------------------------------------//
DEF_ADD_DATA(GotoStmt, { addData(S->getLabel()->getName()); })
DEF_ADD_DATA(IndirectGotoStmt, {
if (S->getConstantTarget())
addData(S->getConstantTarget()->getName());
})
DEF_ADD_DATA(LabelStmt, { addData(S->getDecl()->getName()); })
DEF_ADD_DATA(MSDependentExistsStmt, { addData(S->isIfExists()); })
DEF_ADD_DATA(AddrLabelExpr, { addData(S->getLabel()->getName()); })
//--- Objective-C --------------------------------------------------------//
DEF_ADD_DATA(ObjCIndirectCopyRestoreExpr, { addData(S->shouldCopy()); })
DEF_ADD_DATA(ObjCPropertyRefExpr, {
addData(S->isSuperReceiver());
addData(S->isImplicitProperty());
})
DEF_ADD_DATA(ObjCAtCatchStmt, { addData(S->hasEllipsis()); })
//--- Miscellaneous Stmts ------------------------------------------------//
DEF_ADD_DATA(CXXFoldExpr, {
addData(S->isRightFold());
addData(S->getOperator());
})
DEF_ADD_DATA(GenericSelectionExpr, {
for (unsigned i = 0; i < S->getNumAssocs(); ++i) {
addData(S->getAssocType(i));
}
})
DEF_ADD_DATA(LambdaExpr, {
for (const LambdaCapture &C : S->captures()) {
addData(C.isPackExpansion());
addData(C.getCaptureKind());
if (C.capturesVariable())
addData(C.getCapturedVar()->getType());
}
addData(S->isGenericLambda());
addData(S->isMutable());
})
DEF_ADD_DATA(DeclStmt, {
auto numDecls = std::distance(S->decl_begin(), S->decl_end());
addData(static_cast<DataPiece>(numDecls));
for (const Decl *D : S->decls()) {
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
addData(VD->getType());
}
}
})
DEF_ADD_DATA(AsmStmt, {
addData(S->isSimple());
addData(S->isVolatile());
addData(S->generateAsmString(Context));
for (unsigned i = 0; i < S->getNumInputs(); ++i) {
addData(S->getInputConstraint(i));
}
for (unsigned i = 0; i < S->getNumOutputs(); ++i) {
addData(S->getOutputConstraint(i));
}
for (unsigned i = 0; i < S->getNumClobbers(); ++i) {
addData(S->getClobber(i));
}
})
DEF_ADD_DATA(AttributedStmt, {
for (const Attr *A : S->getAttrs()) {
addData(std::string(A->getSpelling()));
}
})
};
} // namespace clone_detection
/// 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 +227,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 +237,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 +245,20 @@ public:
/// 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 +298,12 @@ public:
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 +341,235 @@ public:
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);
};
struct FilenamePatternConstraint {
StringRef IgnoredFilesPattern;
std::shared_ptr<llvm::Regex> IgnoredFilesRegex;
FilenamePatternConstraint(StringRef IgnoredFilesPattern)
: IgnoredFilesPattern(IgnoredFilesPattern) {
IgnoredFilesRegex = std::make_shared<llvm::Regex>("^(" +
IgnoredFilesPattern.str() + "$)");
}
bool isAutoGenerated(const CloneDetector::CloneGroup &Group);
void constrain(std::vector<CloneDetector::CloneGroup> &CloneGroups) {
CloneConstraint::filterGroups(
CloneGroups, [this](const CloneDetector::CloneGroup &Group) {
return isAutoGenerated(Group);
});
}
};
/// 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 +590,37 @@ public:
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

View File

@ -20,30 +20,37 @@ 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))).
FirstTargetAddressSpace
};
/// The type of a lookup table which maps from language-specific address spaces
/// to target-specific ones.
typedef unsigned Map[Count];
typedef unsigned Map[FirstTargetAddressSpace];
}
}

View File

@ -28,7 +28,7 @@
namespace clang {
template <size_t SizeOfStr, typename FieldType>
class StringSizerHelper {
char FIELD_TOO_SMALL[SizeOfStr <= FieldType(~0U) ? 1 : -1];
static_assert(SizeOfStr <= FieldType(~0U), "Field too small!");
public:
enum { Size = SizeOfStr };
};

View File

@ -149,6 +149,9 @@ class ExprArgument<string name, bit opt = 0> : Argument<name, opt>;
class FunctionArgument<string name, bit opt = 0, bit fake = 0> : Argument<name,
opt,
fake>;
class NamedArgument<string name, bit opt = 0, bit fake = 0> : Argument<name,
opt,
fake>;
class TypeArgument<string name, bit opt = 0> : Argument<name, opt>;
class UnsignedArgument<string name, bit opt = 0> : Argument<name, opt>;
class VariadicUnsignedArgument<string name> : Argument<name, 1>;
@ -248,6 +251,8 @@ def COnly : LangOpt<"CPlusPlus", 1>;
def CPlusPlus : LangOpt<"CPlusPlus">;
def OpenCL : LangOpt<"OpenCL">;
def RenderScript : LangOpt<"RenderScript">;
def ObjC : LangOpt<"ObjC1">;
def BlocksSupported : LangOpt<"Blocks">;
// Defines targets for target-specific attributes. The list of strings should
// specify architectures for which the target applies, based off the ArchType
@ -258,6 +263,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"]>;
@ -269,6 +275,112 @@ def TargetMicrosoftCXXABI : TargetArch<["x86", "x86_64", "arm", "thumb"]> {
let CXXABIs = ["Microsoft"];
}
// Attribute subject match rules that are used for #pragma clang attribute.
//
// A instance of AttrSubjectMatcherRule represents an individual match rule.
// An individual match rule can correspond to a number of different attribute
// subjects, e.g. "record" matching rule corresponds to the Record and
// CXXRecord attribute subjects.
//
// Match rules are used in the subject list of the #pragma clang attribute.
// Match rules can have sub-match rules that are instances of
// AttrSubjectMatcherSubRule. A sub-match rule can correspond to a number
// of different attribute subjects, and it can have a negated spelling as well.
// For example, "variable(unless(is_parameter))" matching rule corresponds to
// the NonParmVar attribute subject.
class AttrSubjectMatcherSubRule<string name, list<AttrSubject> subjects,
bit negated = 0> {
string Name = name;
list<AttrSubject> Subjects = subjects;
bit Negated = negated;
// Lists language options, one of which is required to be true for the
// attribute to be applicable. If empty, the language options are taken
// from the parent matcher rule.
list<LangOpt> LangOpts = [];
}
class AttrSubjectMatcherRule<string name, list<AttrSubject> subjects,
list<AttrSubjectMatcherSubRule> subrules = []> {
string Name = name;
list<AttrSubject> Subjects = subjects;
list<AttrSubjectMatcherSubRule> Constraints = subrules;
// 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 = [];
}
// function(is_member)
def SubRuleForCXXMethod : AttrSubjectMatcherSubRule<"is_member", [CXXMethod]> {
let LangOpts = [CPlusPlus];
}
def SubjectMatcherForFunction : AttrSubjectMatcherRule<"function", [Function], [
SubRuleForCXXMethod
]>;
// hasType is abstract, it should be used with one of the sub-rules.
def SubjectMatcherForType : AttrSubjectMatcherRule<"hasType", [], [
AttrSubjectMatcherSubRule<"functionType", [FunctionLike]>
// FIXME: There's a matcher ambiguity with objc methods and blocks since
// functionType excludes them but functionProtoType includes them.
// AttrSubjectMatcherSubRule<"functionProtoType", [HasFunctionProto]>
]>;
def SubjectMatcherForTypedef : AttrSubjectMatcherRule<"type_alias",
[TypedefName]>;
def SubjectMatcherForRecord : AttrSubjectMatcherRule<"record", [Record,
CXXRecord], [
// unless(is_union)
AttrSubjectMatcherSubRule<"is_union", [Struct], 1>
]>;
def SubjectMatcherForEnum : AttrSubjectMatcherRule<"enum", [Enum]>;
def SubjectMatcherForEnumConstant : AttrSubjectMatcherRule<"enum_constant",
[EnumConstant]>;
def SubjectMatcherForVar : AttrSubjectMatcherRule<"variable", [Var], [
AttrSubjectMatcherSubRule<"is_thread_local", [TLSVar]>,
AttrSubjectMatcherSubRule<"is_global", [GlobalVar]>,
AttrSubjectMatcherSubRule<"is_parameter", [ParmVar]>,
// unless(is_parameter)
AttrSubjectMatcherSubRule<"is_parameter", [NonParmVar], 1>
]>;
def SubjectMatcherForField : AttrSubjectMatcherRule<"field", [Field]>;
def SubjectMatcherForNamespace : AttrSubjectMatcherRule<"namespace",
[Namespace]> {
let LangOpts = [CPlusPlus];
}
def SubjectMatcherForObjCInterface : AttrSubjectMatcherRule<"objc_interface",
[ObjCInterface]> {
let LangOpts = [ObjC];
}
def SubjectMatcherForObjCProtocol : AttrSubjectMatcherRule<"objc_protocol",
[ObjCProtocol]> {
let LangOpts = [ObjC];
}
def SubjectMatcherForObjCCategory : AttrSubjectMatcherRule<"objc_category",
[ObjCCategory]> {
let LangOpts = [ObjC];
}
def SubjectMatcherForObjCMethod : AttrSubjectMatcherRule<"objc_method",
[ObjCMethod], [
AttrSubjectMatcherSubRule<"is_instance", [ObjCInstanceMethod]>
]> {
let LangOpts = [ObjC];
}
def SubjectMatcherForObjCProperty : AttrSubjectMatcherRule<"objc_property",
[ObjCProperty]> {
let LangOpts = [ObjC];
}
def SubjectMatcherForBlock : AttrSubjectMatcherRule<"block", [Block]> {
let LangOpts = [BlocksSupported];
}
// Aggregate attribute subject match rules are abstract match rules that can't
// be used directly in #pragma clang attribute. Instead, users have to use
// subject match rules that correspond to attribute subjects that derive from
// the specified subject.
class AttrSubjectMatcherAggregateRule<AttrSubject subject> {
AttrSubject Subject = subject;
}
def SubjectMatcherForNamed : AttrSubjectMatcherAggregateRule<Named>;
class Attr {
// The various ways in which an attribute can be spelled in source
list<Spelling> Spellings;
@ -301,6 +413,17 @@ 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;
// Set to true if this attribute can be used with '#pragma clang attribute'.
// By default, when this value is false, an attribute is supported by the
// '#pragma clang attribute' only when:
// - It has documentation.
// - It has a subject list whose subjects can be represented using subject
// match rules.
// - It has GNU/CXX11 spelling and doesn't require delayed parsing.
bit ForcePragmaAttributeSupport = 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 +463,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 +495,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 +573,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">;
@ -464,6 +597,9 @@ def AnalyzerNoReturn : InheritableAttr {
def Annotate : InheritableParamAttr {
let Spellings = [GNU<"annotate">];
let Args = [StringArgument<"Annotation">];
// Ensure that the annotate attribute can be used with
// '#pragma clang attribute' even though it has no subject list.
let ForcePragmaAttributeSupport = 1;
let Documentation = [Undocumented];
}
@ -480,6 +616,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">];
@ -506,13 +655,48 @@ def Availability : InheritableAttr {
.Case("tvos_app_extension", "tvOS (App Extension)")
.Case("watchos_app_extension", "watchOS (App Extension)")
.Default(llvm::StringRef());
}
static llvm::StringRef getPlatformNameSourceSpelling(llvm::StringRef Platform) {
return llvm::StringSwitch<llvm::StringRef>(Platform)
.Case("ios", "iOS")
.Case("macos", "macOS")
.Case("tvos", "tvOS")
.Case("watchos", "watchOS")
.Case("ios_app_extension", "iOSApplicationExtension")
.Case("macos_app_extension", "macOSApplicationExtension")
.Case("tvos_app_extension", "tvOSApplicationExtension")
.Case("watchos_app_extension", "watchOSApplicationExtension")
.Default(Platform);
}
static llvm::StringRef canonicalizePlatformName(llvm::StringRef Platform) {
return llvm::StringSwitch<llvm::StringRef>(Platform)
.Case("iOS", "ios")
.Case("macOS", "macos")
.Case("tvOS", "tvos")
.Case("watchOS", "watchos")
.Case("iOSApplicationExtension", "ios_app_extension")
.Case("macOSApplicationExtension", "macos_app_extension")
.Case("tvOSApplicationExtension", "tvos_app_extension")
.Case("watchOSApplicationExtension", "watchos_app_extension")
.Default(Platform);
} }];
let HasCustomParsing = 1;
let DuplicatesAllowedWhileMerging = 1;
// let Subjects = SubjectList<[Named]>;
let Subjects = SubjectList<[Named]>;
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"]>];
@ -707,6 +891,13 @@ def OpenCLUnrollHint : InheritableAttr {
let Documentation = [OpenCLUnrollHintDocs];
}
def OpenCLIntelReqdSubGroupSize: InheritableAttr {
let Spellings = [GNU<"intel_reqd_sub_group_size">];
let Args = [UnsignedArgument<"SubGroupSize">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [OpenCLIntelReqdSubGroupSizeDocs];
}
// This attribute is both a type attribute, and a declaration attribute (for
// parameter variables).
def OpenCLAccess : Attr {
@ -771,6 +962,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 +1039,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 {
@ -982,6 +1182,12 @@ def MipsInterrupt : InheritableAttr, TargetSpecificAttr<TargetMips> {
let Documentation = [MipsInterruptDocs];
}
def MicroMips : InheritableAttr, TargetSpecificAttr<TargetMips> {
let Spellings = [GCC<"micromips">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [MicroMipsDocs];
}
def Mode : Attr {
let Spellings = [GCC<"mode">];
let Subjects = SubjectList<[Var, Enum, TypedefName, Field], ErrorDiag,
@ -1064,6 +1270,12 @@ def NoMips16 : InheritableAttr, TargetSpecificAttr<TargetMips> {
let Documentation = [Undocumented];
}
def NoMicroMips : InheritableAttr, TargetSpecificAttr<TargetMips> {
let Spellings = [GCC<"nomicromips">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [MicroMipsDocs];
}
// This is not a TargetSpecificAttr so that is silently accepted and
// ignored on other targets as encouraged by the OpenCL spec.
//
@ -1115,7 +1327,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 +1390,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?
@ -1463,6 +1683,42 @@ def Section : InheritableAttr {
let Documentation = [SectionDocs];
}
def PragmaClangBSSSection : InheritableAttr {
// This attribute has no spellings as it is only ever created implicitly.
let Spellings = [];
let Args = [StringArgument<"Name">];
let Subjects = SubjectList<[GlobalVar], ErrorDiag,
"ExpectedFunctionMethodOrGlobalVar">;
let Documentation = [Undocumented];
}
def PragmaClangDataSection : InheritableAttr {
// This attribute has no spellings as it is only ever created implicitly.
let Spellings = [];
let Args = [StringArgument<"Name">];
let Subjects = SubjectList<[GlobalVar], ErrorDiag,
"ExpectedFunctionMethodOrGlobalVar">;
let Documentation = [Undocumented];
}
def PragmaClangRodataSection : InheritableAttr {
// This attribute has no spellings as it is only ever created implicitly.
let Spellings = [];
let Args = [StringArgument<"Name">];
let Subjects = SubjectList<[GlobalVar], ErrorDiag,
"ExpectedFunctionMethodOrGlobalVar">;
let Documentation = [Undocumented];
}
def PragmaClangTextSection : InheritableAttr {
// This attribute has no spellings as it is only ever created implicitly.
let Spellings = [];
let Args = [StringArgument<"Name">];
let Subjects = SubjectList<[Function], ErrorDiag,
"ExpectedFunctionMethodOrGlobalVar">;
let Documentation = [Undocumented];
}
def Sentinel : InheritableAttr {
let Spellings = [GCC<"sentinel">];
let Args = [DefaultIntArgument<"Sentinel", 0>,
@ -1498,6 +1754,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];
@ -1540,11 +1802,18 @@ def Target : InheritableAttr {
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [TargetDocs];
let AdditionalMembers = [{
typedef std::pair<std::vector<std::string>, StringRef> ParsedTargetAttr;
struct ParsedTargetAttr {
std::vector<std::string> Features;
StringRef Architecture;
bool DuplicateArchitecture = false;
};
ParsedTargetAttr parse() const {
return parse(getFeaturesStr());
}
static ParsedTargetAttr parse(StringRef Features) {
ParsedTargetAttr Ret;
SmallVector<StringRef, 1> AttrFeatures;
getFeaturesStr().split(AttrFeatures, ",");
Features.split(AttrFeatures, ",");
// Grab the various features and prepend a "+" to turn on the feature to
// the backend and add them to our existing set of features.
@ -1561,12 +1830,15 @@ def Target : InheritableAttr {
continue;
// While we're here iterating check for a different target cpu.
if (Feature.startswith("arch="))
Ret.second = Feature.split("=").second.trim();
else if (Feature.startswith("no-"))
Ret.first.push_back("-" + Feature.split("-").second.str());
if (Feature.startswith("arch=")) {
if (!Ret.Architecture.empty())
Ret.DuplicateArchitecture = true;
else
Ret.Architecture = Feature.split("=").second.trim();
} else if (Feature.startswith("no-"))
Ret.Features.push_back("-" + Feature.split("-").second.str());
else
Ret.first.push_back("+" + Feature.str());
Ret.Features.push_back("+" + Feature.str());
}
return Ret;
}
@ -1596,14 +1868,14 @@ def Unavailable : InheritableAttr {
def DiagnoseIf : InheritableAttr {
let Spellings = [GNU<"diagnose_if">];
let Subjects = SubjectList<[Function]>;
let Subjects = SubjectList<[Function, ObjCMethod, ObjCProperty]>;
let Args = [ExprArgument<"Cond">, StringArgument<"Message">,
EnumArgument<"DiagnosticType",
"DiagnosticType",
["error", "warning"],
["DT_Error", "DT_Warning"]>,
BoolArgument<"ArgDependent", 0, /*fake*/ 1>,
FunctionArgument<"Parent", 0, /*fake*/ 1>];
NamedArgument<"Parent", 0, /*fake*/ 1>];
let DuplicatesAllowedWhileMerging = 1;
let LateParsed = 1;
let AdditionalMembers = [{
@ -1681,6 +1953,7 @@ def Visibility : InheritableAttr {
let Args = [EnumArgument<"Visibility", "VisibilityType",
["default", "hidden", "internal", "protected"],
["Default", "Hidden", "Hidden", "Protected"]>];
let MeaningfulToClassTemplateDefinition = 1;
let Documentation = [Undocumented];
}
@ -1750,6 +2023,12 @@ def AnyX86Interrupt : InheritableAttr, TargetSpecificAttr<TargetAnyX86> {
let Documentation = [AnyX86InterruptDocs];
}
def AnyX86NoCallerSavedRegisters : InheritableAttr,
TargetSpecificAttr<TargetAnyX86> {
let Spellings = [GCC<"no_caller_saved_registers">];
let Documentation = [AnyX86NoCallerSavedRegistersDocs];
}
def X86ForceAlignArgPointer : InheritableAttr, TargetSpecificAttr<TargetX86> {
let Spellings = [GNU<"force_align_arg_pointer">];
// Technically, this appertains to a FunctionDecl, but the target-specific
@ -2180,9 +2459,8 @@ def DLLImport : InheritableAttr, TargetSpecificAttr<TargetWindows> {
let Documentation = [DLLImportDocs];
}
def SelectAny : InheritableAttr {
let Spellings = [Declspec<"selectany">];
let LangOpts = [MicrosoftExt];
def SelectAny : InheritableAttr, TargetSpecificAttr<TargetWindows> {
let Spellings = [Declspec<"selectany">, GCC<"selectany">];
let Documentation = [Undocumented];
}

View File

@ -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 = [{
@ -575,20 +605,27 @@ semantics:
for ``T`` and ``U`` to be incompatible.
The declaration of ``overloadable`` functions is restricted to function
declarations and definitions. Most importantly, if any function with a given
name is given the ``overloadable`` attribute, then all function declarations
and definitions with that name (and in that scope) must have the
``overloadable`` attribute. This rule even applies to redeclarations of
functions whose original declaration had the ``overloadable`` attribute, e.g.,
declarations and definitions. If a function is marked with the ``overloadable``
attribute, then all declarations and definitions of functions with that name,
except for at most one (see the note below about unmarked overloads), must have
the ``overloadable`` attribute. In addition, redeclarations of a function with
the ``overloadable`` attribute must have the ``overloadable`` attribute, and
redeclarations of a function without the ``overloadable`` attribute must *not*
have the ``overloadable`` attribute. e.g.,
.. code-block:: c
int f(int) __attribute__((overloadable));
float f(float); // error: declaration of "f" must have the "overloadable" attribute
int f(int); // error: redeclaration of "f" must have the "overloadable" attribute
int g(int) __attribute__((overloadable));
int g(int) { } // error: redeclaration of "g" must also have the "overloadable" attribute
int h(int);
int h(int) __attribute__((overloadable)); // error: declaration of "h" must not
// have the "overloadable" attribute
Functions marked ``overloadable`` must have prototypes. Therefore, the
following code is ill-formed:
@ -621,7 +658,28 @@ caveats to this use of name mangling:
linkage specification, it's name *will* be mangled in the same way as it
would in C.
Query for this feature with ``__has_extension(attribute_overloadable)``.
For the purpose of backwards compatibility, at most one function with the same
name as other ``overloadable`` functions may omit the ``overloadable``
attribute. In this case, the function without the ``overloadable`` attribute
will not have its name mangled.
For example:
.. code-block:: c
// Notes with mangled names assume Itanium mangling.
int f(int);
int f(double) __attribute__((overloadable));
void foo() {
f(5); // Emits a call to f (not _Z1fi, as it would with an overload that
// was marked with overloadable).
f(1.0); // Emits a call to _Z1fd.
}
Support for unmarked overloads is not present in some versions of clang. You may
query for it using ``__has_extension(overloadable_unmarked)``.
Query for this attribute with ``__has_attribute(overloadable)``.
}];
}
@ -852,13 +910,13 @@ the function declaration for a hypothetical function ``f``:
void f(void) __attribute__((availability(macos,introduced=10.4,deprecated=10.6,obsoleted=10.7)));
The availability attribute states that ``f`` was introduced in Mac OS X 10.4,
deprecated in Mac OS X 10.6, and obsoleted in Mac OS X 10.7. This information
The availability attribute states that ``f`` was introduced in macOS 10.4,
deprecated in macOS 10.6, and obsoleted in macOS 10.7. This information
is used by Clang to determine when it is safe to use ``f``: for example, if
Clang is instructed to compile code for Mac OS X 10.5, a call to ``f()``
succeeds. If Clang is instructed to compile code for Mac OS X 10.6, the call
Clang is instructed to compile code for macOS 10.5, a call to ``f()``
succeeds. If Clang is instructed to compile code for macOS 10.6, the call
succeeds but Clang emits a warning specifying that the function is deprecated.
Finally, if Clang is instructed to compile code for Mac OS X 10.7, the call
Finally, if Clang is instructed to compile code for macOS 10.7, the call
fails because ``f()`` is no longer available.
The availability attribute is a comma-separated list starting with the
@ -903,7 +961,7 @@ are:
command-line arguments.
``macos``
Apple's Mac OS X operating system. The minimum deployment target is
Apple's macOS operating system. The minimum deployment target is
specified by the ``-mmacosx-version-min=*version*`` command-line argument.
``macosx`` is supported for backward-compatibility reasons, but it is
deprecated.
@ -957,9 +1015,79 @@ When one method overrides another, the overriding method can be more widely avai
- (id)method __attribute__((availability(macos,introduced=10.3))); // okay: method moved into base class later
- (id)method __attribute__((availability(macos,introduced=10.5))); // error: this method was available via the base class in 10.4
@end
Starting with the macOS 10.12 SDK, the ``API_AVAILABLE`` macro from
``<os/availability.h>`` can simplify the spelling:
.. code-block:: objc
@interface A
- (id)method API_AVAILABLE(macos(10.11)));
- (id)otherMethod API_AVAILABLE(macos(10.11), ios(11.0));
@end
Also see the documentation for `@available
<http://clang.llvm.org/docs/LanguageExtensions.html#objective-c-available>`_
}];
}
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 +1310,46 @@ The semantics are as follows:
}];
}
def MicroMipsDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
Clang supports the GNU style ``__attribute__((micromips))`` and
``__attribute__((nomicromips))`` attributes on MIPS targets. These attributes
may be attached to a function definition and instructs the backend to generate
or not to generate microMIPS code for that function.
These attributes override the `-mmicromips` and `-mno-micromips` options
on the command line.
}];
}
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 +2047,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 = [{
@ -2053,6 +2270,21 @@ s6.11.5 for details.
}];
}
def OpenCLIntelReqdSubGroupSizeDocs : Documentation {
let Category = DocCatStmt;
let Heading = "__attribute__((intel_reqd_sub_group_size))";
let Content = [{
The optional attribute intel_reqd_sub_group_size can be used to indicate that
the kernel must be compiled and executed with the specified subgroup size. When
this attribute is present, get_max_sub_group_size() is guaranteed to return the
specified integer value. This is important for the correctness of many subgroup
algorithms, and in some cases may be used by the compiler to generate more optimal
code. See `cl_intel_required_subgroup_size
<https://www.khronos.org/registry/OpenCL/extensions/intel/cl_intel_required_subgroup_size.txt>`
for details.
}];
}
def OpenCLAccessDocs : Documentation {
let Category = DocCatStmt;
let Heading = "__read_only, __write_only, __read_write (read_only, write_only, read_write)";
@ -2494,6 +2726,40 @@ hardware design, touch the red zone.
}];
}
def AnyX86NoCallerSavedRegistersDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
Use this attribute to indicate that the specified function has no
caller-saved registers. That is, all registers are callee-saved except for
registers used for passing parameters to the function or returning parameters
from the function.
The compiler saves and restores any modified registers that were not used for
passing or returning arguments to the function.
The user can call functions specified with the 'no_caller_saved_registers'
attribute from an interrupt handler without saving and restoring all
call-clobbered registers.
Note that 'no_caller_saved_registers' attribute is not a calling convention.
In fact, it only overrides the decision of which registers should be saved by
the caller, but not how the parameters are passed from the caller to the callee.
For example:
.. code-block:: c
__attribute__ ((no_caller_saved_registers, fastcall))
void f (int arg1, int arg2) {
...
}
In this case parameters 'arg1' and 'arg2' will be passed in registers.
In this case, on 32-bit x86 targets, the function 'f' will use ECX and EDX as
register parameters. However, it will not assume any scratch registers and
should save and restore any modified registers except for ECX and EDX.
}];
}
def SwiftCallDocs : Documentation {
let Category = DocCatVariable;
let Content = [{
@ -2638,6 +2904,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 +3069,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.
}];
}

View File

@ -0,0 +1,32 @@
//===-- AttrSubjectMatchRules.h - Attribute subject match rules -*- 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_ATTR_SUBJECT_MATCH_RULES_H
#define LLVM_CLANG_BASIC_ATTR_SUBJECT_MATCH_RULES_H
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMap.h"
namespace clang {
namespace attr {
/// \brief A list of all the recognized kinds of attributes.
enum SubjectMatchRule {
#define ATTR_MATCH_RULE(X, Spelling, IsAbstract) X,
#include "clang/Basic/AttrSubMatchRulesList.inc"
};
const char *getSubjectMatchRuleSpelling(SubjectMatchRule Rule);
using ParsedSubjectMatchRuleSet = llvm::DenseMap<int, SourceRange>;
} // end namespace attr
} // end namespace clang
#endif

View File

@ -52,6 +52,7 @@
// LL -> long long
// LLL -> __int128_t (e.g. LLLi)
// W -> int64_t
// N -> 'int' size if target is LP64, 'L' otherwise.
// S -> signed
// U -> unsigned
// I -> Required to constant fold to an integer constant expression.
@ -718,11 +719,11 @@ BUILTIN(__builtin_rindex, "c*cC*i", "Fn")
LANGBUILTIN(_alloca, "v*z", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__assume, "vb", "n", ALL_MS_LANGUAGES)
LIBBUILTIN(_byteswap_ushort, "UsUs", "fnc", "stdlib.h", ALL_MS_LANGUAGES)
LIBBUILTIN(_byteswap_ulong, "ULiULi", "fnc", "stdlib.h", ALL_MS_LANGUAGES)
LIBBUILTIN(_byteswap_ulong, "UNiUNi", "fnc", "stdlib.h", ALL_MS_LANGUAGES)
LIBBUILTIN(_byteswap_uint64, "ULLiULLi", "fnc", "stdlib.h", ALL_MS_LANGUAGES)
LANGBUILTIN(__debugbreak, "v", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__exception_code, "ULi", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_exception_code, "ULi", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__exception_code, "UNi", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_exception_code, "UNi", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__exception_info, "v*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_exception_info, "v*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__abnormal_termination, "i", "n", ALL_MS_LANGUAGES)
@ -730,49 +731,50 @@ LANGBUILTIN(_abnormal_termination, "i", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__GetExceptionInfo, "v*.", "ntu", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedAnd8, "ccD*c", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedAnd16, "ssD*s", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedAnd, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedAnd, "NiNiD*Ni", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedCompareExchange8, "ccD*cc", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedCompareExchange16, "ssD*ss", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedCompareExchange, "LiLiD*LiLi", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedCompareExchange, "NiNiD*NiNi", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedCompareExchange64, "LLiLLiD*LLiLLi", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedCompareExchangePointer, "v*v*D*v*v*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedDecrement16, "ssD*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedDecrement, "LiLiD*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchange, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedDecrement, "NiNiD*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchange, "NiNiD*Ni", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchange8, "ccD*c", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchange16, "ssD*s", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchangeAdd8, "ccD*c", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchangeAdd16, "ssD*s", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchangeAdd, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchangeAdd, "NiNiD*Ni", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchangePointer, "v*v*D*v*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchangeSub8, "ccD*c", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchangeSub16, "ssD*s", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchangeSub, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchangeSub, "NiNiD*Ni", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedIncrement16, "ssD*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedIncrement, "LiLiD*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedIncrement, "NiNiD*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedOr8, "ccD*c", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedOr16, "ssD*s", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedOr, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedOr, "NiNiD*Ni", "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(_InterlockedXor, "NiNiD*Ni", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_interlockedbittestandset, "UcNiD*Ni", "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)
LANGBUILTIN(_rotl, "UiUii", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_lrotl, "ULiULii", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_lrotl, "UNiUNii", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_rotl64, "ULLiULLii", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_rotr8, "UcUcUc", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_rotr16, "UsUsUc", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_rotr, "UiUii", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_lrotr, "ULiULii", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_lrotr, "UNiUNii", "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 +1088,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 +1366,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.
@ -1406,6 +1410,14 @@ LANGBUILTIN(to_private, "v*v*", "tn", OCLC20_LANG)
BUILTIN(__builtin_os_log_format_buffer_size, "zcC*.", "p:0:nut")
BUILTIN(__builtin_os_log_format, "v*v*cC*.", "p:0:nt")
// Builtins for XRay
BUILTIN(__xray_customevent, "vcC*z", "")
// Win64-compatible va_list functions
BUILTIN(__builtin_ms_va_start, "vc*&.", "nt")
BUILTIN(__builtin_ms_va_end, "vc*&", "n")
BUILTIN(__builtin_ms_va_copy, "vc*&c*&", "n")
#undef BUILTIN
#undef LIBBUILTIN
#undef LANGBUILTIN

View File

@ -35,8 +35,15 @@ BUILTIN(__builtin_amdgcn_workitem_id_z, "Ui", "nc")
//===----------------------------------------------------------------------===//
// Instruction builtins.
//===----------------------------------------------------------------------===//
BUILTIN(__builtin_amdgcn_s_getreg, "UiIi", "n")
BUILTIN(__builtin_amdgcn_s_getpc, "LUi", "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 +87,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 +108,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.

View File

@ -25,11 +25,93 @@
// In libgcc
BUILTIN(__clear_cache, "vv*v*", "i")
// 16-bit multiplications
BUILTIN(__builtin_arm_smulbb, "iii", "nc")
BUILTIN(__builtin_arm_smulbt, "iii", "nc")
BUILTIN(__builtin_arm_smultb, "iii", "nc")
BUILTIN(__builtin_arm_smultt, "iii", "nc")
BUILTIN(__builtin_arm_smulwb, "iii", "nc")
BUILTIN(__builtin_arm_smulwt, "iii", "nc")
// Saturating arithmetic
BUILTIN(__builtin_arm_qadd, "iii", "nc")
BUILTIN(__builtin_arm_qsub, "iii", "nc")
BUILTIN(__builtin_arm_ssat, "iiUi", "nc")
BUILTIN(__builtin_arm_usat, "UiUiUi", "nc")
BUILTIN(__builtin_arm_usat, "UiiUi", "nc")
BUILTIN(__builtin_arm_smlabb, "iiii", "nc")
BUILTIN(__builtin_arm_smlabt, "iiii", "nc")
BUILTIN(__builtin_arm_smlatb, "iiii", "nc")
BUILTIN(__builtin_arm_smlatt, "iiii", "nc")
BUILTIN(__builtin_arm_smlawb, "iiii", "nc")
BUILTIN(__builtin_arm_smlawt, "iiii", "nc")
BUILTIN(__builtin_arm_ssat16, "iii", "nc")
BUILTIN(__builtin_arm_usat16, "iii", "nc")
BUILTIN(__builtin_arm_sxtab16, "iii", "nc")
BUILTIN(__builtin_arm_sxtb16, "ii", "nc")
BUILTIN(__builtin_arm_uxtab16, "iii", "nc")
BUILTIN(__builtin_arm_uxtb16, "ii", "nc")
BUILTIN(__builtin_arm_sel, "iii", "nc")
BUILTIN(__builtin_arm_qadd8, "iii", "nc")
BUILTIN(__builtin_arm_qsub8, "iii", "nc")
BUILTIN(__builtin_arm_sadd8, "iii", "nc")
BUILTIN(__builtin_arm_shadd8, "iii", "nc")
BUILTIN(__builtin_arm_shsub8, "iii", "nc")
BUILTIN(__builtin_arm_ssub8, "iii", "nc")
BUILTIN(__builtin_arm_uadd8, "UiUiUi", "nc")
BUILTIN(__builtin_arm_uhadd8, "UiUiUi", "nc")
BUILTIN(__builtin_arm_uhsub8, "UiUiUi", "nc")
BUILTIN(__builtin_arm_uqadd8, "UiUiUi", "nc")
BUILTIN(__builtin_arm_uqsub8, "UiUiUi", "nc")
BUILTIN(__builtin_arm_usub8, "UiUiUi", "nc")
// Sum of 8-bit absolute differences
BUILTIN(__builtin_arm_usad8, "UiUiUi", "nc")
BUILTIN(__builtin_arm_usada8, "UiUiUiUi", "nc")
// Parallel 16-bit addition and subtraction
BUILTIN(__builtin_arm_qadd16, "iii", "nc")
BUILTIN(__builtin_arm_qasx, "iii", "nc")
BUILTIN(__builtin_arm_qsax, "iii", "nc")
BUILTIN(__builtin_arm_qsub16, "iii", "nc")
BUILTIN(__builtin_arm_sadd16, "iii", "nc")
BUILTIN(__builtin_arm_sasx, "iii", "nc")
BUILTIN(__builtin_arm_shadd16, "iii", "nc")
BUILTIN(__builtin_arm_shasx, "iii", "nc")
BUILTIN(__builtin_arm_shsax, "iii", "nc")
BUILTIN(__builtin_arm_shsub16, "iii", "nc")
BUILTIN(__builtin_arm_ssax, "iii", "nc")
BUILTIN(__builtin_arm_ssub16, "iii", "nc")
BUILTIN(__builtin_arm_uadd16, "UiUiUi", "nc")
BUILTIN(__builtin_arm_uasx, "UiUiUi", "nc")
BUILTIN(__builtin_arm_uhadd16, "UiUiUi", "nc")
BUILTIN(__builtin_arm_uhasx, "UiUiUi", "nc")
BUILTIN(__builtin_arm_uhsax, "UiUiUi", "nc")
BUILTIN(__builtin_arm_uhsub16, "UiUiUi", "nc")
BUILTIN(__builtin_arm_uqadd16, "UiUiUi", "nc")
BUILTIN(__builtin_arm_uqasx, "UiUiUi", "nc")
BUILTIN(__builtin_arm_uqsax, "UiUiUi", "nc")
BUILTIN(__builtin_arm_uqsub16, "UiUiUi", "nc")
BUILTIN(__builtin_arm_usax, "UiUiUi", "nc")
BUILTIN(__builtin_arm_usub16, "UiUiUi", "nc")
// Parallel 16-bit multiplication
BUILTIN(__builtin_arm_smlad, "iiii", "nc")
BUILTIN(__builtin_arm_smladx, "iiii", "nc")
BUILTIN(__builtin_arm_smlald, "LLiiiLLi", "nc")
BUILTIN(__builtin_arm_smlaldx, "LLiiiLLi", "nc")
BUILTIN(__builtin_arm_smlsd, "iiii", "nc")
BUILTIN(__builtin_arm_smlsdx, "iiii", "nc")
BUILTIN(__builtin_arm_smlsld, "LLiiiLLi", "nc")
BUILTIN(__builtin_arm_smlsldx, "LLiiiLLi", "nc")
BUILTIN(__builtin_arm_smuad, "iii", "nc")
BUILTIN(__builtin_arm_smuadx, "iii", "nc")
BUILTIN(__builtin_arm_smusd, "iii", "nc")
BUILTIN(__builtin_arm_smusdx, "iii", "nc")
// Bit manipulation
BUILTIN(__builtin_arm_rbit, "UiUi", "nc")
@ -133,10 +215,10 @@ LANGBUILTIN(_MoveFromCoprocessor2, "UiIUiIUiIUiIUiIUi", "", ALL_MS_LANGUAGES)
LANGBUILTIN(_MoveToCoprocessor, "vUiIUiIUiIUiIUiIUi", "", ALL_MS_LANGUAGES)
LANGBUILTIN(_MoveToCoprocessor2, "vUiIUiIUiIUiIUiIUi", "", ALL_MS_LANGUAGES)
TARGET_HEADER_BUILTIN(_BitScanForward, "UcULi*ULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanReverse, "UcULi*ULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanForward64, "UcULi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanReverse64, "UcULi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanForward, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanReverse, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanForward64, "UcUNi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanReverse64, "UcUNi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement64, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")

View File

@ -882,6 +882,12 @@ BUILTIN(__builtin_HEXAGON_S2_ct0p,"iLLi","")
BUILTIN(__builtin_HEXAGON_S2_ct1p,"iLLi","")
BUILTIN(__builtin_HEXAGON_S2_interleave,"LLiLLi","")
BUILTIN(__builtin_HEXAGON_S2_deinterleave,"LLiLLi","")
BUILTIN(__builtin_HEXAGON_Y2_dccleana,"vv*","")
BUILTIN(__builtin_HEXAGON_Y2_dccleaninva,"vv*","")
BUILTIN(__builtin_HEXAGON_Y2_dcinva,"vv*","")
BUILTIN(__builtin_HEXAGON_Y2_dczeroa,"vv*","")
BUILTIN(__builtin_HEXAGON_Y4_l2fetch,"vv*Ui","")
BUILTIN(__builtin_HEXAGON_Y5_l2fetch,"vv*LLUi","")
BUILTIN(__builtin_HEXAGON_S6_rol_i_r,"iii","v:60:")
BUILTIN(__builtin_HEXAGON_S6_rol_i_p,"LLiLLii","v:60:")

View File

@ -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", "")

View File

@ -0,0 +1,70 @@
//===-- BuiltinsNios2.def - Nios2 Builtin function database --------*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the Nios2-specific builtin function database. Users of
// this file must define the BUILTIN macro to make use of this information.
//
//===----------------------------------------------------------------------===//
// The format of this database matches clang/Basic/Builtins.def.
#if defined(BUILTIN) && !defined(TARGET_BUILTIN)
# define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BUILTIN(ID, TYPE, ATTRS)
#endif
// Nios2 R1 builtins:
//int __builtin_ldbio(volatile const void *);
BUILTIN(__builtin_ldbio, "ivDC*", "")
//int __builtin_ldbuio(volatile const void *);
BUILTIN(__builtin_ldbuio, "ivDC*", "")
//int __builtin_ldhio(volatile const void *);
BUILTIN(__builtin_ldhio, "ivDC*", "")
//int __builtin_ldhuio(volatile const void *);
BUILTIN(__builtin_ldhuio, "ivDC*", "")
//int __builtin_ldwio(volatile const void *);
BUILTIN(__builtin_ldwio, "ivDC*", "")
//int __builtin_ldwuio(int);
BUILTIN(__builtin_ldwuio, "ii", "")
// int __builtin_rdctl(int);
BUILTIN(__builtin_rdctl, "iIi", "")
// void __builtin_wrctl(int, int);
BUILTIN(__builtin_wrctl, "vIii", "")
// int __builtin_rdprs(int, int);
BUILTIN(__builtin_rdprs, "iii", "")
//void __builtin_stbio(volatile void *, int);
BUILTIN(__builtin_stbio, "vvD*i", "")
//void __builtin_sthio(volatile void *, int);
BUILTIN(__builtin_sthio, "vvD*i", "")
//void __builtin_stwio(volatile void *, int);
BUILTIN(__builtin_stwio, "vvD*i", "")
//void __builtin_sync(void);
BUILTIN(__builtin_sync, "v", "")
// void __builtin_flushd(volatile void *);
BUILTIN(__builtin_flushd, "vvD*", "")
// void __builtin_flushda(volatile void *);
BUILTIN(__builtin_flushda, "vvD*", "")
// Nios2 R2 builtins:
// int __builtin_wrpie(int);
TARGET_BUILTIN(__builtin_wrpie, "ii", "", "nios2r2mandatory")
// void __builtin_eni(int);
TARGET_BUILTIN(__builtin_eni, "vi", "", "nios2r2mandatory")
// int __builtin_ldex(volatile const void *);
TARGET_BUILTIN(__builtin_ldex, "ivDC*", "", "nios2r2mandatory")
// int __builtin_stex(volatile void *, int);
TARGET_BUILTIN(__builtin_stex, "ivD*i", "", "nios2r2mandatory")
// int __builtin_ldsex(volatile const void *);
TARGET_BUILTIN(__builtin_ldsex, "ivDC*", "", "nios2r2mpx")
// int __builtin_stsex(volatile void *, int);
TARGET_BUILTIN(__builtin_stsex, "ivDC*i", "", "nios2r2mpx")
#undef BUILTIN
#undef TARGET_BUILTIN

Some files were not shown because too many files have changed in this diff Show More