Vendor import of clang release_30 branch r142614:

http://llvm.org/svn/llvm-project/cfe/branches/release_30@142614
This commit is contained in:
Dimitry Andric 2011-10-20 21:14:49 +00:00
parent 180abc3db9
commit 36981b17ed
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/clang/dist/; revision=226586
svn path=/vendor/clang/clang-r142614/; revision=226587; tag=vendor/clang/clang-r142614
2436 changed files with 101830 additions and 47860 deletions

25
.gitignore vendored Normal file
View File

@ -0,0 +1,25 @@
#==============================================================================#
# This file specifies intentionally untracked files that git should ignore.
# See: http://www.kernel.org/pub/software/scm/git/docs/gitignore.html
#
# This file is intentionally different from the output of `git svn show-ignore`,
# as most of those are useless.
#==============================================================================#
#==============================================================================#
# File extensions to be ignored anywhere in the tree.
#==============================================================================#
# Temp files created by most text editors.
*~
# Merge files created by git.
*.orig
# Byte compiled python modules.
*.pyc
# vim swap files
.*.swp
#==============================================================================#
# Explicit files to ignore (only matches one).
#==============================================================================#
cscope.files
cscope.out

View File

@ -19,10 +19,10 @@ if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR )
endif()
endif()
if( NOT EXISTS "${CLANG_PATH_TO_LLVM_BUILD}/bin/tblgen${CMAKE_EXECUTABLE_SUFFIX}" )
# Looking for bin/Debug/tblgen is a complete hack. How can we get
if( NOT EXISTS "${CLANG_PATH_TO_LLVM_BUILD}/bin/llvm-tblgen${CMAKE_EXECUTABLE_SUFFIX}" )
# Looking for bin/Debug/llvm-tblgen is a complete hack. How can we get
# around this?
if( NOT EXISTS "${CLANG_PATH_TO_LLVM_BUILD}/bin/Debug/tblgen${CMAKE_EXECUTABLE_SUFFIX}" )
if( NOT EXISTS "${CLANG_PATH_TO_LLVM_BUILD}/bin/Debug/llvm-tblgen${CMAKE_EXECUTABLE_SUFFIX}" )
message(FATAL_ERROR "Please set CLANG_PATH_TO_LLVM_BUILD to a directory containing a LLVM build.")
endif()
endif()
@ -46,11 +46,11 @@ if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR )
include_directories("${PATH_TO_LLVM_BUILD}/include" "${LLVM_MAIN_INCLUDE_DIR}")
link_directories("${PATH_TO_LLVM_BUILD}/lib")
if( EXISTS "${CLANG_PATH_TO_LLVM_BUILD}/bin/tblgen${CMAKE_EXECUTABLE_SUFFIX}" )
set(LLVM_TABLEGEN_EXE "${PATH_TO_LLVM_BUILD}/bin/tblgen")
if( EXISTS "${CLANG_PATH_TO_LLVM_BUILD}/bin/llvm-tblgen${CMAKE_EXECUTABLE_SUFFIX}" )
set(LLVM_TABLEGEN_EXE "${PATH_TO_LLVM_BUILD}/bin/llvm-tblgen${CMAKE_EXECUTABLE_SUFFIX}")
else()
# FIXME: This is an utter hack.
set(LLVM_TABLEGEN_EXE "${PATH_TO_LLVM_BUILD}/bin/Debug/tblgen")
set(LLVM_TABLEGEN_EXE "${PATH_TO_LLVM_BUILD}/bin/Debug/llvm-tblgen${CMAKE_EXECUTABLE_SUFFIX}")
endif()
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin )
@ -153,7 +153,7 @@ function(clang_tablegen)
endif()
set( LLVM_TARGET_DEFINITIONS ${CTG_SOURCE} )
tablegen( ${CTG_DEFAULT_ARGS} )
tablegen( CLANG ${CTG_DEFAULT_ARGS} )
list( GET CTG_DEFAULT_ARGS 0 output_file )
if( CTG_TARGET )
@ -244,6 +244,7 @@ set(LIBCLANG_LIBRARY_VERSION
"Version number that will be placed into the libclang library , in the form XX.YY")
mark_as_advanced(CLANG_EXECUTABLE_VERSION LIBCLANG_LIBRARY_VERSION)
add_subdirectory(utils/TableGen)
option(CLANG_BUILD_EXAMPLES "Build CLANG example programs." OFF)
if(CLANG_BUILD_EXAMPLES)
@ -272,3 +273,6 @@ if( CLANG_BUILT_STANDALONE AND MSVC_VERSION EQUAL 1600 )
file(APPEND "${CLANG_SLN_FILENAME}" "\n# This should be regenerated!\n")
endif()
endif()
set(BUG_REPORT_URL "http://llvm.org/bugs/" CACHE STRING
"Default URL where bug reports are to be submitted.")

View File

@ -0,0 +1,59 @@
// Hammer the CFG with large numbers of overlapping variable scopes, which
// implicit destructors triggered at each edge.
#define EXPAND_BASIC_STRUCT(i) struct X##i { X##i(int); ~X##i(); };
#define EXPAND_NORET_STRUCT(i) struct X##i { X##i(int); ~X##i() __attribute__((noreturn)); };
EXPAND_BASIC_STRUCT(0000); EXPAND_NORET_STRUCT(0001);
EXPAND_BASIC_STRUCT(0010); EXPAND_BASIC_STRUCT(0011);
EXPAND_BASIC_STRUCT(0100); EXPAND_NORET_STRUCT(0101);
EXPAND_NORET_STRUCT(0110); EXPAND_BASIC_STRUCT(0111);
EXPAND_BASIC_STRUCT(1000); EXPAND_NORET_STRUCT(1001);
EXPAND_BASIC_STRUCT(1010); EXPAND_BASIC_STRUCT(1011);
EXPAND_NORET_STRUCT(1100); EXPAND_NORET_STRUCT(1101);
EXPAND_BASIC_STRUCT(1110); EXPAND_BASIC_STRUCT(1111);
#define EXPAND_2_VARS(c, i, x) const X##i var_##c##_##i##0(x), &var_##c##_##i##1 = X##i(x)
#define EXPAND_4_VARS(c, i, x) EXPAND_2_VARS(c, i##0, x); EXPAND_2_VARS(c, i##1, x)
#define EXPAND_8_VARS(c, i, x) EXPAND_4_VARS(c, i##0, x); EXPAND_4_VARS(c, i##1, x)
#define EXPAND_16_VARS(c, i, x) EXPAND_8_VARS(c, i##0, x); EXPAND_8_VARS(c, i##1, x)
#define EXPAND_32_VARS(c, x) EXPAND_16_VARS(c, 0, x); EXPAND_16_VARS(c, 1, x)
#define EXPAND_2_INNER_CASES(i, x, y) INNER_CASE(i, x, y); INNER_CASE(i + 1, x, y);
#define EXPAND_4_INNER_CASES(i, x, y) EXPAND_2_INNER_CASES(i, x, y) EXPAND_2_INNER_CASES(i + 2, x, y)
#define EXPAND_8_INNER_CASES(i, x, y) EXPAND_4_INNER_CASES(i, x, y) EXPAND_4_INNER_CASES(i + 4, x, y)
#define EXPAND_16_INNER_CASES(i, x, y) EXPAND_8_INNER_CASES(i, x, y) EXPAND_8_INNER_CASES(i + 8, x, y)
#define EXPAND_32_INNER_CASES(i, x, y) EXPAND_16_INNER_CASES(i, x, y) EXPAND_16_INNER_CASES(i + 16, x, y)
#define EXPAND_2_OUTER_CASES(i, x, y) OUTER_CASE(i, x, y); OUTER_CASE(i + 1, x, y);
#define EXPAND_4_OUTER_CASES(i, x, y) EXPAND_2_OUTER_CASES(i, x, y) EXPAND_2_OUTER_CASES(i + 2, x, y)
#define EXPAND_8_OUTER_CASES(i, x, y) EXPAND_4_OUTER_CASES(i, x, y) EXPAND_4_OUTER_CASES(i + 4, x, y)
#define EXPAND_16_OUTER_CASES(i, x, y) EXPAND_8_OUTER_CASES(i, x, y) EXPAND_8_OUTER_CASES(i + 8, x, y)
#define EXPAND_32_OUTER_CASES(i, x, y) EXPAND_16_OUTER_CASES(i, x, y) EXPAND_16_OUTER_CASES(i + 16, x, y)
unsigned cfg_nested_vars(int x) {
int y = 0;
while (x > 0) {
EXPAND_32_VARS(a, x);
switch (x) {
#define INNER_CASE(i, x, y) \
case i: { \
int case_var = 3*x + i; \
EXPAND_32_VARS(c, case_var); \
y += case_var - 1; \
break; \
}
#define OUTER_CASE(i, x, y) \
case i: { \
int case_var = y >> 8; \
EXPAND_32_VARS(b, y); \
switch (case_var) { \
EXPAND_32_INNER_CASES(0, x, y); \
} \
break; \
}
EXPAND_32_OUTER_CASES(0, x, y);
}
--x;
}
return y;
}

View File

@ -14,7 +14,7 @@ ifndef CLANG_LEVEL
IS_TOP_LEVEL := 1
CLANG_LEVEL := .
DIRS := include lib tools runtime docs unittests
DIRS := utils/TableGen include lib tools runtime docs unittests
PARALLEL_DIRS :=
@ -60,6 +60,16 @@ endif
# We can revisit this when LLVM/Clang support it.
CXX.Flags += -fno-strict-aliasing
# Set up Clang's tblgen.
ifndef CLANG_TBLGEN
ifeq ($(LLVM_CROSS_COMPILING),1)
CLANG_TBLGEN := $(BuildLLVMToolDir)/clang-tblgen$(BUILD_EXEEXT)
else
CLANG_TBLGEN := $(LLVMToolDir)/clang-tblgen$(EXEEXT)
endif
endif
ClangTableGen = $(CLANG_TBLGEN) $(TableGen.Flags)
###
# Clang Top Level specific stuff.
@ -68,7 +78,7 @@ ifeq ($(IS_TOP_LEVEL),1)
ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT))
$(RecursiveTargets)::
$(Verb) for dir in test unittests; do \
if [ ! -f $${dir}/Makefile ]; then \
if [ -f $(PROJ_SRC_DIR)/$${dir}/Makefile ] && [ ! -f $${dir}/Makefile ]; then \
$(MKDIR) $${dir}; \
$(CP) $(PROJ_SRC_DIR)/$${dir}/Makefile $${dir}/Makefile; \
fi \

View File

@ -83,3 +83,21 @@ enum VerifyConstraintResult {
};
//===---------------------------------------------------------------------===//
Blocks should not capture variables that are only used in dead code.
The rule that we came up with is that blocks are required to capture
variables if they're referenced in evaluated code, even if that code
doesn't actually rely on the value of the captured variable.
For example, this requires a capture:
(void) var;
But this does not:
if (false) puts(var);
Summary of <rdar://problem/9851835>: if we implement this, we should
warn about non-POD variables that are referenced but not captured, but
only if the non-reachability is not due to macro or template
metaprogramming.
//===---------------------------------------------------------------------===//

View File

@ -1,75 +0,0 @@
//===---------------------------------------------------------------------===//
// Minor random things that can be improved
//===---------------------------------------------------------------------===//
Warn about "X && 0x1000" saying that the user may mean "X & 0x1000".
We should do this for any immediate except zero, so long as it doesn't come
from a macro expansion. Likewise for ||.
//===---------------------------------------------------------------------===//
Lexer-related diagnostics should point to the problematic character, not the
start of the token. For example:
int y = 0000\
00080;
diag.c:4:9: error: invalid digit '8' in octal constant
int y = 0000\
^
should be:
diag.c:4:9: error: invalid digit '8' in octal constant
00080;
^
This specific diagnostic is implemented, but others should be updated.
//===---------------------------------------------------------------------===//
C++ (checker): For iterators, warn of the use of "iterator++" instead
of "++iterator" when when the value returned by operator++(int) is
ignored.
//===---------------------------------------------------------------------===//
We want to keep more source range information in Declarator to help
produce better diagnostics. Declarator::getSourceRange() should be
implemented to give a range for the whole declarator with all of its
specifiers, and DeclaratorChunk::ParamInfo should also have a source
range covering the whole parameter, so that an error message like this:
overloaded-operator-decl.cpp:37:23: error: parameter of overloaded post-increment operator must have type 'int' (not 'float')
X operator++(X&, const float& f);
^
can be turned into something like this:
overloaded-operator-decl.cpp:37:23: error: parameter of overloaded post-increment operator must have type 'int' (not 'float')
X operator++(X&, const float& f);
^ ~~~~~~~~~~~~~~
//===---------------------------------------------------------------------===//
For terminal output, we should consider limiting the amount of
diagnostic text we print once the first error has been
encountered. For example, once we have produced an error diagnostic,
we should only continue producing diagnostics until we have produced a
page full of results (say, 50 lines of text). Beyond that, (1) the
remaining errors are likely to be less interesting, and (2) the poor
user has to scroll his terminal to find out where things went wrong.
//===---------------------------------------------------------------------===//
More ideas for code modification hints:
- If no member of a given name is found in a class/struct, search through the names of entities that do exist in the class and suggest the closest candidate. e.g., if I write "DS.setTypeSpecType", it would suggest "DS.SetTypeSpecType" (edit distance = 1).
- If a class member is defined out-of-line but isn't in the class declaration (and there are no close matches!), provide the option to add an in-class declaration.
- Fix-it hints for the inclusion of headers when needed for particular features (e.g., <typeinfo> for typeid)
//===---------------------------------------------------------------------===//
Options to support:
-ftabstop=width
-fpreprocessed mode.
-nostdinc++
-imultilib

View File

@ -112,7 +112,7 @@ def _get_instantiation(self):
f, l, c, o = c_object_p(), c_uint(), c_uint(), c_uint()
SourceLocation_loc(self, byref(f), byref(l), byref(c), byref(o))
f = File(f) if f else None
self._data = (f, int(l.value), int(c.value), int(c.value))
self._data = (f, int(l.value), int(c.value), int(o.value))
return self._data
@property
@ -451,6 +451,19 @@ def __repr__(self):
# A C++ using declaration
CursorKind.USING_DECLARATION = CursorKind(35)
# A Type alias decl.
CursorKind.TYPE_ALIAS_DECL = CursorKind(36)
# A Objective-C synthesize decl
CursorKind.OBJC_SYNTHESIZE_DECL = CursorKind(37)
# A Objective-C dynamic decl
CursorKind.OBJC_DYNAMIC_DECL = CursorKind(38)
# A C++ access specifier decl.
CursorKind.CXX_ACCESS_SPEC_DECL = CursorKind(39)
###
# Reference Kinds
@ -524,6 +537,154 @@ def __repr__(self):
# An expression that represents a block literal.
CursorKind.BLOCK_EXPR = CursorKind(105)
# An integer literal.
CursorKind.INTEGER_LITERAL = CursorKind(106)
# A floating point number literal.
CursorKind.FLOATING_LITERAL = CursorKind(107)
# An imaginary number literal.
CursorKind.IMAGINARY_LITERAL = CursorKind(108)
# A string literal.
CursorKind.STRING_LITERAL = CursorKind(109)
# A character literal.
CursorKind.CHARACTER_LITERAL = CursorKind(110)
# A parenthesized expression, e.g. "(1)".
#
# This AST node is only formed if full location information is requested.
CursorKind.PAREN_EXPR = CursorKind(111)
# This represents the unary-expression's (except sizeof and
# alignof).
CursorKind.UNARY_OPERATOR = CursorKind(112)
# [C99 6.5.2.1] Array Subscripting.
CursorKind.ARRAY_SUBSCRIPT_EXPR = CursorKind(113)
# A builtin binary operation expression such as "x + y" or
# "x <= y".
CursorKind.BINARY_OPERATOR = CursorKind(114)
# Compound assignment such as "+=".
CursorKind.COMPOUND_ASSIGNMENT_OPERATOR = CursorKind(115)
# The ?: ternary operator.
CursorKind.CONDITONAL_OPERATOR = CursorKind(116)
# An explicit cast in C (C99 6.5.4) or a C-style cast in C++
# (C++ [expr.cast]), which uses the syntax (Type)expr.
#
# For example: (int)f.
CursorKind.CSTYLE_CAST_EXPR = CursorKind(117)
# [C99 6.5.2.5]
CursorKind.COMPOUND_LITERAL_EXPR = CursorKind(118)
# Describes an C or C++ initializer list.
CursorKind.INIT_LIST_EXPR = CursorKind(119)
# The GNU address of label extension, representing &&label.
CursorKind.ADDR_LABEL_EXPR = CursorKind(120)
# This is the GNU Statement Expression extension: ({int X=4; X;})
CursorKind.StmtExpr = CursorKind(121)
# Represents a C1X generic selection.
CursorKind.GENERIC_SELECTION_EXPR = CursorKind(122)
# Implements the GNU __null extension, which is a name for a null
# pointer constant that has integral type (e.g., int or long) and is the same
# size and alignment as a pointer.
#
# The __null extension is typically only used by system headers, which define
# NULL as __null in C++ rather than using 0 (which is an integer that may not
# match the size of a pointer).
CursorKind.GNU_NULL_EXPR = CursorKind(123)
# C++'s static_cast<> expression.
CursorKind.CXX_STATIC_CAST_EXPR = CursorKind(124)
# C++'s dynamic_cast<> expression.
CursorKind.CXX_DYNAMIC_CAST_EXPR = CursorKind(125)
# C++'s reinterpret_cast<> expression.
CursorKind.CXX_REINTERPRET_CAST_EXPR = CursorKind(126)
# C++'s const_cast<> expression.
CursorKind.CXX_CONST_CAST_EXPR = CursorKind(127)
# Represents an explicit C++ type conversion that uses "functional"
# notion (C++ [expr.type.conv]).
#
# Example:
# \code
# x = int(0.5);
# \endcode
CursorKind.CXX_FUNCTIONAL_CAST_EXPR = CursorKind(128)
# A C++ typeid expression (C++ [expr.typeid]).
CursorKind.CXX_TYPEID_EXPR = CursorKind(129)
# [C++ 2.13.5] C++ Boolean Literal.
CursorKind.CXX_BOOL_LITERAL_EXPR = CursorKind(130)
# [C++0x 2.14.7] C++ Pointer Literal.
CursorKind.CXX_NULL_PTR_LITERAL_EXPR = CursorKind(131)
# Represents the "this" expression in C++
CursorKind.CXX_THIS_EXPR = CursorKind(132)
# [C++ 15] C++ Throw Expression.
#
# This handles 'throw' and 'throw' assignment-expression. When
# assignment-expression isn't present, Op will be null.
CursorKind.CXX_THROW_EXPR = CursorKind(133)
# A new expression for memory allocation and constructor calls, e.g:
# "new CXXNewExpr(foo)".
CursorKind.CXX_NEW_EXPR = CursorKind(134)
# A delete expression for memory deallocation and destructor calls,
# e.g. "delete[] pArray".
CursorKind.CXX_DELETE_EXPR = CursorKind(135)
# Represents a unary expression.
CursorKind.CXX_UNARY_EXPR = CursorKind(136)
# ObjCStringLiteral, used for Objective-C string literals i.e. "foo".
CursorKind.OBJC_STRING_LITERAL = CursorKind(137)
# ObjCEncodeExpr, used for in Objective-C.
CursorKind.OBJC_ENCODE_EXPR = CursorKind(138)
# ObjCSelectorExpr used for in Objective-C.
CursorKind.OBJC_SELECTOR_EXPR = CursorKind(139)
# Objective-C's protocol expression.
CursorKind.OBJC_PROTOCOL_EXPR = CursorKind(140)
# An Objective-C "bridged" cast expression, which casts between
# Objective-C pointers and C pointers, transferring ownership in the process.
#
# \code
# NSString *str = (__bridge_transfer NSString *)CFCreateString();
# \endcode
CursorKind.OBJC_BRIDGE_CAST_EXPR = CursorKind(141)
# Represents a C++0x pack expansion that produces a sequence of
# expressions.
#
# A pack expansion expression contains a pattern (which itself is an
# expression) followed by an ellipsis. For example:
CursorKind.PACK_EXPANSION_EXPR = CursorKind(142)
# Represents an expression that computes the length of a parameter
# pack.
CursorKind.SIZE_OF_PACK_EXPR = CursorKind(143)
# A statement whose specific kind is not exposed via this interface.
#
# Unexposed statements have the same operations as any other kind of statement;
@ -534,6 +695,92 @@ def __repr__(self):
# A labelled statement in a function.
CursorKind.LABEL_STMT = CursorKind(201)
# A compound statement
CursorKind.COMPOUND_STMT = CursorKind(202)
# A case statement.
CursorKind.CASE_STMT = CursorKind(203)
# A default statement.
CursorKind.DEFAULT_STMT = CursorKind(204)
# An if statement.
CursorKind.IF_STMT = CursorKind(205)
# A switch statement.
CursorKind.SWITCH_STMT = CursorKind(206)
# A while statement.
CursorKind.WHILE_STMT = CursorKind(207)
# A do statement.
CursorKind.DO_STMT = CursorKind(208)
# A for statement.
CursorKind.FOR_STMT = CursorKind(209)
# A goto statement.
CursorKind.GOTO_STMT = CursorKind(210)
# An indirect goto statement.
CursorKind.INDIRECT_GOTO_STMT = CursorKind(211)
# A continue statement.
CursorKind.CONTINUE_STMT = CursorKind(212)
# A break statement.
CursorKind.BREAK_STMT = CursorKind(213)
# A return statement.
CursorKind.RETURN_STMT = CursorKind(214)
# A GNU-style inline assembler statement.
CursorKind.ASM_STMT = CursorKind(215)
# Objective-C's overall @try-@catch-@finally statement.
CursorKind.OBJC_AT_TRY_STMT = CursorKind(216)
# Objective-C's @catch statement.
CursorKind.OBJC_AT_CATCH_STMT = CursorKind(217)
# Objective-C's @finally statement.
CursorKind.OBJC_AT_FINALLY_STMT = CursorKind(218)
# Objective-C's @throw statement.
CursorKind.OBJC_AT_THROW_STMT = CursorKind(219)
# Objective-C's @synchronized statement.
CursorKind.OBJC_AT_SYNCHRONIZED_STMT = CursorKind(220)
# Objective-C's autorealease pool statement.
CursorKind.OBJC_AUTORELEASE_POOL_STMT = CursorKind(221)
# Objective-C's for collection statement.
CursorKind.OBJC_FOR_COLLECTION_STMT = CursorKind(222)
# C++'s catch statement.
CursorKind.CXX_CATCH_STMT = CursorKind(223)
# C++'s try statement.
CursorKind.CXX_TRY_STMT = CursorKind(224)
# C++'s for (* : *) statement.
CursorKind.CXX_FOR_RANGE_STMT = CursorKind(225)
# Windows Structured Exception Handling's try statement.
CursorKind.SEH_TRY_STMT = CursorKind(226)
# Windows Structured Exception Handling's except statement.
CursorKind.SEH_EXCEPT_STMT = CursorKind(227)
# Windows Structured Exception Handling's finally statement.
CursorKind.SEH_FINALLY_STMT = CursorKind(228)
# The null statement.
CursorKind.NULL_STMT = CursorKind(230)
# Adaptor class for mixing declarations with statements and expressions.
CursorKind.DECL_STMT = CursorKind(231)
###
# Other Kinds
@ -616,7 +863,22 @@ def spelling(self):
# FIXME: clang_getCursorSpelling should be fixed to not assert on
# this, for consistency with clang_getCursorUSR.
return None
return Cursor_spelling(self)
if not hasattr(self, '_spelling'):
self._spelling = Cursor_spelling(self)
return self._spelling
@property
def displayname(self):
"""
Return the display name for the entity referenced by this cursor.
The display name contains extra information that helps identify the cursor,
such as the parameters of a function or template or the arguments of a
class template specialization.
"""
if not hasattr(self, '_displayname'):
self._displayname = Cursor_displayname(self)
return self._displayname
@property
def location(self):
@ -624,7 +886,9 @@ def location(self):
Return the source location (the starting character) of the entity
pointed at by the cursor.
"""
return Cursor_loc(self)
if not hasattr(self, '_loc'):
self._loc = Cursor_loc(self)
return self._loc
@property
def extent(self):
@ -632,7 +896,19 @@ def extent(self):
Return the source range (the range of text) occupied by the entity
pointed at by the cursor.
"""
return Cursor_extent(self)
if not hasattr(self, '_extent'):
self._extent = Cursor_extent(self)
return self._extent
@property
def type(self):
"""
Retrieve the type (if any) of of the entity pointed at by the
cursor.
"""
if not hasattr(self, '_type'):
self._type = Cursor_type(self)
return self._type
def get_children(self):
"""Return an iterator for accessing the children of this cursor."""
@ -656,6 +932,165 @@ def from_result(res, fn, args):
return None
return res
### Type Kinds ###
class TypeKind(object):
"""
Describes the kind of type.
"""
# The unique kind objects, indexed by id.
_kinds = []
_name_map = None
def __init__(self, value):
if value >= len(TypeKind._kinds):
TypeKind._kinds += [None] * (value - len(TypeKind._kinds) + 1)
if TypeKind._kinds[value] is not None:
raise ValueError,'TypeKind already loaded'
self.value = value
TypeKind._kinds[value] = self
TypeKind._name_map = None
def from_param(self):
return self.value
@property
def name(self):
"""Get the enumeration name of this cursor kind."""
if self._name_map is None:
self._name_map = {}
for key,value in TypeKind.__dict__.items():
if isinstance(value,TypeKind):
self._name_map[value] = key
return self._name_map[self]
@staticmethod
def from_id(id):
if id >= len(TypeKind._kinds) or TypeKind._kinds[id] is None:
raise ValueError,'Unknown cursor kind'
return TypeKind._kinds[id]
def __repr__(self):
return 'TypeKind.%s' % (self.name,)
TypeKind.INVALID = TypeKind(0)
TypeKind.UNEXPOSED = TypeKind(1)
TypeKind.VOID = TypeKind(2)
TypeKind.BOOL = TypeKind(3)
TypeKind.CHAR_U = TypeKind(4)
TypeKind.UCHAR = TypeKind(5)
TypeKind.CHAR16 = TypeKind(6)
TypeKind.CHAR32 = TypeKind(7)
TypeKind.USHORT = TypeKind(8)
TypeKind.UINT = TypeKind(9)
TypeKind.ULONG = TypeKind(10)
TypeKind.ULONGLONG = TypeKind(11)
TypeKind.UINT128 = TypeKind(12)
TypeKind.CHAR_S = TypeKind(13)
TypeKind.SCHAR = TypeKind(14)
TypeKind.WCHAR = TypeKind(15)
TypeKind.SHORT = TypeKind(16)
TypeKind.INT = TypeKind(17)
TypeKind.LONG = TypeKind(18)
TypeKind.LONGLONG = TypeKind(19)
TypeKind.INT128 = TypeKind(20)
TypeKind.FLOAT = TypeKind(21)
TypeKind.DOUBLE = TypeKind(22)
TypeKind.LONGDOUBLE = TypeKind(23)
TypeKind.NULLPTR = TypeKind(24)
TypeKind.OVERLOAD = TypeKind(25)
TypeKind.DEPENDENT = TypeKind(26)
TypeKind.OBJCID = TypeKind(27)
TypeKind.OBJCCLASS = TypeKind(28)
TypeKind.OBJCSEL = TypeKind(29)
TypeKind.COMPLEX = TypeKind(100)
TypeKind.POINTER = TypeKind(101)
TypeKind.BLOCKPOINTER = TypeKind(102)
TypeKind.LVALUEREFERENCE = TypeKind(103)
TypeKind.RVALUEREFERENCE = TypeKind(104)
TypeKind.RECORD = TypeKind(105)
TypeKind.ENUM = TypeKind(106)
TypeKind.TYPEDEF = TypeKind(107)
TypeKind.OBJCINTERFACE = TypeKind(108)
TypeKind.OBJCOBJECTPOINTER = TypeKind(109)
TypeKind.FUNCTIONNOPROTO = TypeKind(110)
TypeKind.FUNCTIONPROTO = TypeKind(111)
class Type(Structure):
"""
The type of an element in the abstract syntax tree.
"""
_fields_ = [("_kind_id", c_int), ("data", c_void_p * 2)]
@property
def kind(self):
"""Return the kind of this type."""
return TypeKind.from_id(self._kind_id)
@staticmethod
def from_result(res, fn, args):
assert isinstance(res, Type)
return res
def get_canonical(self):
"""
Return the canonical type for a Type.
Clang's type system explicitly models typedefs and all the
ways a specific type can be represented. The canonical type
is the underlying type with all the "sugar" removed. For
example, if 'T' is a typedef for 'int', the canonical type for
'T' would be 'int'.
"""
return Type_get_canonical(self)
def is_const_qualified(self):
"""
Determine whether a Type has the "const" qualifier set,
without looking through typedefs that may have added "const"
at a different level.
"""
return Type_is_const_qualified(self)
def is_volatile_qualified(self):
"""
Determine whether a Type has the "volatile" qualifier set,
without looking through typedefs that may have added
"volatile" at a different level.
"""
return Type_is_volatile_qualified(self)
def is_restrict_qualified(self):
"""
Determine whether a Type has the "restrict" qualifier set,
without looking through typedefs that may have added
"restrict" at a different level.
"""
return Type_is_restrict_qualified(self)
def get_pointee(self):
"""
For pointer types, returns the type of the pointee.
"""
return Type_get_pointee(self)
def get_declaration(self):
"""
Return the cursor for the declaration of the given type.
"""
return Type_get_declaration(self)
def get_result(self):
"""
Retrieve the result type associated with a function type.
"""
return Type_get_result(self)
## CIndex Objects ##
# CIndex objects (derived from ClangObject) are essentially lightweight
@ -1210,11 +1645,50 @@ def is_input_file(self):
Cursor_ref.restype = Cursor
Cursor_ref.errcheck = Cursor.from_result
Cursor_type = lib.clang_getCursorType
Cursor_type.argtypes = [Cursor]
Cursor_type.restype = Type
Cursor_type.errcheck = Type.from_result
Cursor_visit_callback = CFUNCTYPE(c_int, Cursor, Cursor, py_object)
Cursor_visit = lib.clang_visitChildren
Cursor_visit.argtypes = [Cursor, Cursor_visit_callback, py_object]
Cursor_visit.restype = c_uint
# Type Functions
Type_get_canonical = lib.clang_getCanonicalType
Type_get_canonical.argtypes = [Type]
Type_get_canonical.restype = Type
Type_get_canonical.errcheck = Type.from_result
Type_is_const_qualified = lib.clang_isConstQualifiedType
Type_is_const_qualified.argtypes = [Type]
Type_is_const_qualified.restype = bool
Type_is_volatile_qualified = lib.clang_isVolatileQualifiedType
Type_is_volatile_qualified.argtypes = [Type]
Type_is_volatile_qualified.restype = bool
Type_is_restrict_qualified = lib.clang_isRestrictQualifiedType
Type_is_restrict_qualified.argtypes = [Type]
Type_is_restrict_qualified.restype = bool
Type_get_pointee = lib.clang_getPointeeType
Type_get_pointee.argtypes = [Type]
Type_get_pointee.restype = Type
Type_get_pointee.errcheck = Type.from_result
Type_get_declaration = lib.clang_getTypeDeclaration
Type_get_declaration.argtypes = [Type]
Type_get_declaration.restype = Cursor
Type_get_declaration.errcheck = Cursor.from_result
Type_get_result = lib.clang_getResultType
Type_get_result.argtypes = [Type]
Type_get_result.restype = Type
Type_get_result.errcheck = Type.from_result
# Index Functions
Index_create = lib.clang_createIndex
Index_create.argtypes = [c_int, c_int]
@ -1313,6 +1787,6 @@ def is_input_file(self):
###
__all__ = ['Index', 'TranslationUnit', 'Cursor', 'CursorKind',
__all__ = ['Index', 'TranslationUnit', 'Cursor', 'CursorKind', 'Type', 'TypeKind',
'Diagnostic', 'FixIt', 'CodeCompletionResults', 'SourceRange',
'SourceLocation', 'File']

View File

@ -1,4 +1,4 @@
from clang.cindex import Index, CursorKind
from clang.cindex import Index, CursorKind, TypeKind
kInput = """\
// FIXME: Find nicer way to drop builtins and other cruft.
@ -47,13 +47,17 @@ def test_get_children():
assert len(s0_nodes) == 2
assert s0_nodes[0].kind == CursorKind.FIELD_DECL
assert s0_nodes[0].spelling == 'a'
assert s0_nodes[0].type.kind == TypeKind.INT
assert s0_nodes[1].kind == CursorKind.FIELD_DECL
assert s0_nodes[1].spelling == 'b'
assert s0_nodes[1].type.kind == TypeKind.INT
assert tu_nodes[1].kind == CursorKind.STRUCT_DECL
assert tu_nodes[1].spelling == 's1'
assert tu_nodes[1].displayname == 's1'
assert tu_nodes[1].is_definition() == False
assert tu_nodes[2].kind == CursorKind.FUNCTION_DECL
assert tu_nodes[2].spelling == 'f0'
assert tu_nodes[2].displayname == 'f0(int, int)'
assert tu_nodes[2].is_definition() == True

View File

@ -36,7 +36,7 @@ def test_diagnostic_fixit():
assert len(tu.diagnostics) == 1
assert tu.diagnostics[0].severity == Diagnostic.Warning
assert tu.diagnostics[0].location.line == 1
assert tu.diagnostics[0].location.column == 31
assert tu.diagnostics[0].location.column == 26
assert tu.diagnostics[0].spelling.startswith('use of GNU old-style')
assert len(tu.diagnostics[0].fixits) == 1
assert tu.diagnostics[0].fixits[0].range.start.line == 1

View File

@ -0,0 +1,50 @@
from clang.cindex import Index
baseInput="int one;\nint two;\n"
def assert_location(loc, line, column, offset):
assert loc.line == line
assert loc.column == column
assert loc.offset == offset
def test_location():
index = Index.create()
tu = index.parse('t.c', unsaved_files = [('t.c',baseInput)])
for n in tu.cursor.get_children():
if n.spelling == 'one':
assert_location(n.location,line=1,column=5,offset=4)
if n.spelling == 'two':
assert_location(n.location,line=2,column=5,offset=13)
# adding a linebreak at top should keep columns same
tu = index.parse('t.c', unsaved_files = [('t.c',"\n"+baseInput)])
for n in tu.cursor.get_children():
if n.spelling == 'one':
assert_location(n.location,line=2,column=5,offset=5)
if n.spelling == 'two':
assert_location(n.location,line=3,column=5,offset=14)
# adding a space should affect column on first line only
tu = index.parse('t.c', unsaved_files = [('t.c'," "+baseInput)])
for n in tu.cursor.get_children():
if n.spelling == 'one':
assert_location(n.location,line=1,column=6,offset=5)
if n.spelling == 'two':
assert_location(n.location,line=2,column=5,offset=14)
def test_extent():
index = Index.create()
tu = index.parse('t.c', unsaved_files = [('t.c',baseInput)])
for n in tu.cursor.get_children():
if n.spelling == 'one':
assert_location(n.extent.start,line=1,column=1,offset=0)
assert_location(n.extent.end,line=1,column=8,offset=7)
assert baseInput[n.extent.start.offset:n.extent.end.offset] == "int one"
if n.spelling == 'two':
assert_location(n.extent.start,line=2,column=1,offset=9)
assert_location(n.extent.end,line=2,column=8,offset=16)
assert baseInput[n.extent.start.offset:n.extent.end.offset] == "int two"

View File

@ -0,0 +1,76 @@
from clang.cindex import Index, CursorKind, TypeKind
kInput = """\
typedef int I;
struct teststruct {
int a;
I b;
long c;
unsigned long d;
signed long e;
const int f;
int *g;
int ***h;
};
"""
def test_a_struct():
index = Index.create()
tu = index.parse('t.c', unsaved_files = [('t.c',kInput)])
for n in tu.cursor.get_children():
if n.spelling == 'teststruct':
fields = list(n.get_children())
assert all(x.kind == CursorKind.FIELD_DECL for x in fields)
assert fields[0].spelling == 'a'
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[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[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[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[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[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[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[7].spelling == 'h'
assert not fields[7].type.is_const_qualified()
assert fields[7].type.kind == TypeKind.POINTER
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
break
else:
assert False, "Didn't find teststruct??"

File diff suppressed because it is too large Load Diff

View File

@ -1315,6 +1315,39 @@ and only if the value is not demonstrably already retained.</p>
<p>The complete optimization rules are quite complicated, but it would
still be useful to document them here.</p>
<div id="optimization.precise">
<h1>Precise lifetime semantics</h1>
<p>In general, ARC maintains an invariant that a retainable object
pointer held in a <tt>__strong</tt> object will be retained for the
full formal lifetime of the object. Objects subject to this invariant
have <span class="term">precise lifetime semantics</span>.</p>
<p>By default, local variables of automatic storage duration do not
have precise lifetime semantics. Such objects are simply strong
references which hold values of retainable object pointer type, and
these values are still fully subject to the optimizations on values
under local control.</p>
<div class="rationale"><p>Rationale: applying these precise-lifetime
semantics strictly would be prohibitive. Many useful optimizations
that might theoretically decrease the lifetime of an object would be
rendered impossible. Essentially, it promises too much.</p></div>
<p>A local variable of retainable object owner type and automatic
storage duration may be annotated with the <tt>objc_precise_lifetime</tt>
attribute to indicate that it should be considered to be an object
with precise lifetime semantics.</p>
<div class="rationale"><p>Rationale: nonetheless, it is sometimes
useful to be able to force an object to be released at a precise time,
even if that object does not appear to be used. This is likely to be
uncommon enough that the syntactic weight of explicitly requesting
these semantics will not be burdensome, and may even make the code
clearer.</p></div>
</div> <!-- optimization.precise -->
</div>
<div id="misc">
@ -1562,6 +1595,56 @@ from exceptions.</p></div>
</div> <!-- misc.exceptions -->
<div id="misc.interior">
<h1>Interior pointers</h1>
<p>An Objective-C method returning a non-retainable pointer may be
annotated with the <tt>objc_returns_inner_pointer</tt> attribute to
indicate that it returns a handle to the internal data of an object,
and that this reference will be invalidated if the object is
destroyed. When such a message is sent to an object, the object's
lifetime will be extended until at least the earliest of:</p>
<ul>
<li>the last use of the returned pointer, or any pointer derived from
it, in the calling function or</li>
<li>the autorelease pool is restored to a previous state.</li>
</ul>
<div class="rationale"><p>Rationale: not all memory and resources are
managed with reference counts; it is common for objects to manage
private resources in their own, private way. Typically these
resources are completely encapsulated within the object, but some
classes offer their users direct access for efficiency. If ARC is not
aware of methods that return such <q>interior</q> pointers, its
optimizations can cause the owning object to be reclaimed too soon.
This attribute informs ARC that it must tread lightly.</p>
<p>The extension rules are somewhat intentionally vague. The
autorelease pool limit is there to permit a simple implementation to
simply retain and autorelease the receiver. The other limit permits
some amount of optimization. The phrase <q>derived from</q> is
intended to encompass the results both of pointer transformations,
such as casts and arithmetic, and of loading from such derived
pointers; furthermore, it applies whether or not such derivations are
applied directly in the calling code or by other utility code (for
example, the C library routine <tt>strchr</tt>). However, the
implementation never need account for uses after a return from the
code which calls the method returning an interior pointer.</p></div>
<p>As an exception, no extension is required if the receiver is loaded
directly from a <tt>__strong</tt> object
with <a href="#optimization.precise">precise lifetime semantics</a>.</p>
<div class="rationale"><p>Rationale: implicit autoreleases carry the
risk of significantly inflating memory use, so it's important to
provide users a way of avoiding these autoreleases. Tying this to
precise lifetime semantics is ideal, as for local variables this
requires a very explicit annotation, which allows ARC to trust the
user with good cheer.</p></div>
</div> <!-- misc.interior -->
</div> <!-- misc -->
<div id="runtime">

View File

@ -71,6 +71,7 @@ td {
<li><a href="#Howtos">Howto guides</a>
<ul>
<li><a href="#AddingAttributes">How to add an attribute</a></li>
<li><a href="#AddingExprStmt">How to add a new expression or statement</a></li>
</ul>
</li>
</ul>
@ -1785,6 +1786,228 @@ Check for the attribute's presence using <tt>Decl::getAttr&lt;YourAttr>()</tt>.<
<p>Update the <a href="LanguageExtensions.html">Clang Language Extensions</a>
document to describe your new attribute.</p>
<!-- ======================================================================= -->
<h3 id="AddingExprStmt">How to add an expression or statement</h3>
<!-- ======================================================================= -->
<p>Expressions and statements are one of the most fundamental constructs within a
compiler, because they interact with many different parts of the AST,
semantic analysis, and IR generation. Therefore, adding a new
expression or statement kind into Clang requires some care. The following list
details the various places in Clang where an expression or statement needs to be
introduced, along with patterns to follow to ensure that the new
expression or statement works well across all of the C languages. We
focus on expressions, but statements are similar.</p>
<ol>
<li>Introduce parsing actions into the parser. Recursive-descent
parsing is mostly self-explanatory, but there are a few things that
are worth keeping in mind:
<ul>
<li>Keep as much source location information as possible! You'll
want it later to produce great diagnostics and support Clang's
various features that map between source code and the AST.</li>
<li>Write tests for all of the "bad" parsing cases, to make sure
your recovery is good. If you have matched delimiters (e.g.,
parentheses, square brackets, etc.), use
<tt>Parser::BalancedDelimiterTracker</tt> to give nice diagnostics when
things go wrong.</li>
</ul>
</li>
<li>Introduce semantic analysis actions into <tt>Sema</tt>. Semantic
analysis should always involve two functions: an <tt>ActOnXXX</tt>
function that will be called directly from the parser, and a
<tt>BuildXXX</tt> function that performs the actual semantic
analysis and will (eventually!) build the AST node. It's fairly
common for the <tt>ActOnCXX</tt> function to do very little (often
just some minor translation from the parser's representation to
<tt>Sema</tt>'s representation of the same thing), but the separation
is still important: C++ template instantiation, for example,
should always call the <tt>BuildXXX</tt> variant. Several notes on
semantic analysis before we get into construction of the AST:
<ul>
<li>Your expression probably involves some types and some
subexpressions. Make sure to fully check that those types, and the
types of those subexpressions, meet your expectations. Add
implicit conversions where necessary to make sure that all of the
types line up exactly the way you want them. Write extensive tests
to check that you're getting good diagnostics for mistakes and
that you can use various forms of subexpressions with your
expression.</li>
<li>When type-checking a type or subexpression, make sure to first
check whether the type is "dependent"
(<tt>Type::isDependentType()</tt>) or whether a subexpression is
type-dependent (<tt>Expr::isTypeDependent()</tt>). If any of these
return true, then you're inside a template and you can't do much
type-checking now. That's normal, and your AST node (when you get
there) will have to deal with this case. At this point, you can
write tests that use your expression within templates, but don't
try to instantiate the templates.</li>
<li>For each subexpression, be sure to call
<tt>Sema::CheckPlaceholderExpr()</tt> to deal with "weird"
expressions that don't behave well as subexpressions. Then,
determine whether you need to perform
lvalue-to-rvalue conversions
(<tt>Sema::DefaultLvalueConversion</tt>e) or
the usual unary conversions
(<tt>Sema::UsualUnaryConversions</tt>), for places where the
subexpression is producing a value you intend to use.</li>
<li>Your <tt>BuildXXX</tt> function will probably just return
<tt>ExprError()</tt> at this point, since you don't have an AST.
That's perfectly fine, and shouldn't impact your testing.</li>
</ul>
</li>
<li>Introduce an AST node for your new expression. This starts with
declaring the node in <tt>include/Basic/StmtNodes.td</tt> and
creating a new class for your expression in the appropriate
<tt>include/AST/Expr*.h</tt> header. It's best to look at the class
for a similar expression to get ideas, and there are some specific
things to watch for:
<ul>
<li>If you need to allocate memory, use the <tt>ASTContext</tt>
allocator to allocate memory. Never use raw <tt>malloc</tt> or
<tt>new</tt>, and never hold any resources in an AST node, because
the destructor of an AST node is never called.</li>
<li>Make sure that <tt>getSourceRange()</tt> covers the exact
source range of your expression. This is needed for diagnostics
and for IDE support.</li>
<li>Make sure that <tt>children()</tt> visits all of the
subexpressions. This is important for a number of features (e.g., IDE
support, C++ variadic templates). If you have sub-types, you'll
also need to visit those sub-types in the
<tt>RecursiveASTVisitor</tt>.</li>
<li>Add printing support (<tt>StmtPrinter.cpp</tt>) and dumping
support (<tt>StmtDumper.cpp</tt>) for your expression.</li>
<li>Add profiling support (<tt>StmtProfile.cpp</tt>) for your AST
node, noting the distinguishing (non-source location)
characteristics of an instance of your expression. Omitting this
step will lead to hard-to-diagnose failures regarding matching of
template declarations.</li>
</ul>
</li>
<li>Teach semantic analysis to build your AST node! At this point,
you can wire up your <tt>Sema::BuildXXX</tt> function to actually
create your AST. A few things to check at this point:
<ul>
<li>If your expression can construct a new C++ class or return a
new Objective-C object, be sure to update and then call
<tt>Sema::MaybeBindToTemporary</tt> for your just-created AST node
to be sure that the object gets properly destructed. An easy way
to test this is to return a C++ class with a private destructor:
semantic analysis should flag an error here with the attempt to
call the destructor.</li>
<li>Inspect the generated AST by printing it using <tt>clang -cc1
-ast-print</tt>, to make sure you're capturing all of the
important information about how the AST was written.</li>
<li>Inspect the generated AST under <tt>clang -cc1 -ast-dump</tt>
to verify that all of the types in the generated AST line up the
way you want them. Remember that clients of the AST should never
have to "think" to understand what's going on. For example, all
implicit conversions should show up explicitly in the AST.</li>
<li>Write tests that use your expression as a subexpression of
other, well-known expressions. Can you call a function using your
expression as an argument? Can you use the ternary operator?</li>
</ul>
</li>
<li>Teach code generation to create IR to your AST node. This step
is the first (and only) that requires knowledge of LLVM IR. There
are several things to keep in mind:
<ul>
<li>Code generation is separated into scalar/aggregate/complex and
lvalue/rvalue paths, depending on what kind of result your
expression produces. On occasion, this requires some careful
factoring of code to avoid duplication.</li>
<li><tt>CodeGenFunction</tt> contains functions
<tt>ConvertType</tt> and <tt>ConvertTypeForMem</tt> that convert
Clang's types (<tt>clang::Type*</tt> or <tt>clang::QualType</tt>)
to LLVM types.
Use the former for values, and the later for memory locations:
test with the C++ "bool" type to check this. If you find
that you are having to use LLVM bitcasts to make
the subexpressions of your expression have the type that your
expression expects, STOP! Go fix semantic analysis and the AST so
that you don't need these bitcasts.</li>
<li>The <tt>CodeGenFunction</tt> class has a number of helper
functions to make certain operations easy, such as generating code
to produce an lvalue or an rvalue, or to initialize a memory
location with a given value. Prefer to use these functions rather
than directly writing loads and stores, because these functions
take care of some of the tricky details for you (e.g., for
exceptions).</li>
<li>If your expression requires some special behavior in the event
of an exception, look at the <tt>push*Cleanup</tt> functions in
<tt>CodeGenFunction</tt> to introduce a cleanup. You shouldn't
have to deal with exception-handling directly.</li>
<li>Testing is extremely important in IR generation. Use <tt>clang
-cc1 -emit-llvm</tt> and <a
href="http://llvm.org/cmds/FileCheck.html">FileCheck</a> to verify
that you're generating the right IR.</li>
</ul>
</li>
<li>Teach template instantiation how to cope with your AST
node, which requires some fairly simple code:
<ul>
<li>Make sure that your expression's constructor properly
computes the flags for type dependence (i.e., the type your
expression produces can change from one instantiation to the
next), value dependence (i.e., the constant value your expression
produces can change from one instantiation to the next),
instantiation dependence (i.e., a template parameter occurs
anywhere in your expression), and whether your expression contains
a parameter pack (for variadic templates). Often, computing these
flags just means combining the results from the various types and
subexpressions.</li>
<li>Add <tt>TransformXXX</tt> and <tt>RebuildXXX</tt> functions to
the
<tt>TreeTransform</tt> class template in <tt>Sema</tt>.
<tt>TransformXXX</tt> should (recursively) transform all of the
subexpressions and types
within your expression, using <tt>getDerived().TransformYYY</tt>.
If all of the subexpressions and types transform without error, it
will then call the <tt>RebuildXXX</tt> function, which will in
turn call <tt>getSema().BuildXXX</tt> to perform semantic analysis
and build your expression.</li>
<li>To test template instantiation, take those tests you wrote to
make sure that you were type checking with type-dependent
expressions and dependent types (from step #2) and instantiate
those templates with various types, some of which type-check and
some that don't, and test the error messages in each case.</li>
</ul>
</li>
<li>There are some "extras" that make other features work better.
It's worth handling these extras to give your expression complete
integration into Clang:
<ul>
<li>Add code completion support for your expression in
<tt>SemaCodeComplete.cpp</tt>.</li>
<li>If your expression has types in it, or has any "interesting"
features other than subexpressions, extend libclang's
<tt>CursorVisitor</tt> to provide proper visitation for your
expression, enabling various IDE features such as syntax
highlighting, cross-referencing, and so on. The
<tt>c-index-test</tt> helper program can be used to test these
features.</li>
</ul>
</li>
</ol>
</div>
</body>
</html>

View File

@ -4,7 +4,7 @@
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Clang LanguageExtensions</title>
<title>Clang Language Extensions</title>
<link type="text/css" rel="stylesheet" href="../menu.css">
<link type="text/css" rel="stylesheet" href="../content.css">
<style type="text/css">
@ -38,29 +38,41 @@
<ul>
<li><a href="#cxx0x">C++0x</a>
<ul>
<li><a href="#cxx_decltype">C++0x <tt>decltype()</tt></a></li>
<li><a href="#cxx_access_control_sfinae">C++0x SFINAE includes access control</a></li>
<li><a href="#cxx_access_control_sfinae">C++0x SFINAE includes access control</a></li>
<li><a href="#cxx_alias_templates">C++0x alias templates</a></li>
<li><a href="#cxx_alignas">C++0x alignment specifiers</a></li>
<li><a href="#cxx_attributes">C++0x attributes</a></li>
<li><a href="#cxx_constexpr">C++0x generalized constant expressions</a></li>
<li><a href="#cxx_decltype">C++0x <tt>decltype()</tt></a></li>
<li><a href="#cxx_default_function_template_args">C++0x default template arguments in function templates</a></li>
<li><a href="#cxx_delegating_constructor">C++0x delegating constructors</a></li>
<li><a href="#cxx_deleted_functions">C++0x deleted functions</a></li>
<li><a href="#cxx_explicit_conversions">C++0x explicit conversion functions</a></li>
<li><a href="#cxx_generalized_initializers">C++0x generalized initializers</a></li>
<li><a href="#cxx_implicit_moves">C++0x implicit move constructors/assignment operators</a></li>
<li><a href="#cxx_inheriting_constructors">C++0x inheriting constructors</a></li>
<li><a href="#cxx_inline_namespaces">C++0x inline namespaces</a></li>
<li><a href="#cxx_lambdas">C++0x lambdas</a></li>
<li><a href="#cxx_noexcept">C++0x noexcept specification</a></li>
<li><a href="#cxx_nonstatic_member_init">C++0x in-class non-static data member initialization</a></li>
<li><a href="#cxx_nullptr">C++0x nullptr</a></li>
<li><a href="#cxx_override_control">C++0x override control</a></li>
<li><a href="#cxx_range_for">C++0x range-based for loop</a></li>
<li><a href="#cxx_raw_string_literals">C++0x raw string literals</a></li>
<li><a href="#cxx_rvalue_references">C++0x rvalue references</a></li>
<li><a href="#cxx_reference_qualified_functions">C++0x reference-qualified functions</a></li>
<li><a href="#cxx_static_assert">C++0x <tt>static_assert()</tt></a></li>
<li><a href="#cxx_auto_type">C++0x type inference</a></li>
<li><a href="#cxx_variadic_templates">C++0x variadic templates</a></li>
<li><a href="#cxx_inline_namespaces">C++0x inline namespaces</a></li>
<li><a href="#cxx_strong_enums">C++0x strongly-typed enumerations</a></li>
<li><a href="#cxx_strong_enums">C++0x strongly-typed enumerations</a></li>
<li><a href="#cxx_trailing_return">C++0x trailing return type</a></li>
<li><a href="#cxx_noexcept">C++0x noexcept specification</a></li>
</ul></li>
<li><a href="#cxx_unicode_literals">C++0x Unicode string literals</a></li>
<li><a href="#cxx_unrestricted_unions">C++0x unrestricted unions</a></li>
<li><a href="#cxx_user_literals">C++0x user-defined literals</a></li>
<li><a href="#cxx_variadic_templates">C++0x variadic templates</a></li>
</ul></li>
<li><a href="#c1x">C1X</a>
<ul>
<li><a href="#c_alignas">C1X alignment specifiers</a></li>
<li><a href="#c_generic_selections">C1X generic selections</a></li>
<li><a href="#c_static_assert">C1X <tt>_Static_assert()</tt></a></li>
</ul></li>
@ -71,9 +83,11 @@
<ul>
<li><a href="#objc_instancetype">Related result types</a></li>
<li><a href="#objc_arc">Automatic reference counting</a></li>
<li><a href="#objc_fixed_enum">Enumerations with a fixed underlying type</a></li>
</ul>
</li>
<li><a href="#overloading-in-c">Function Overloading in C</a></li>
<li><a href="#complex-list-init">Initializer lists for complex numbers in C</a></li>
<li><a href="#builtins">Builtin Functions</a>
<ul>
<li><a href="#__builtin_shufflevector">__builtin_shufflevector</a></li>
@ -87,6 +101,27 @@
</ul>
</li>
<li><a href="#analyzerspecific">Static Analysis-Specific Extensions</a></li>
<li><a href="#threadsafety">Thread Safety Annotation Checking</a></li>
<ul>
<li><a href="#ts_noanal"><tt>no_thread_safety_analysis</tt></a></li>
<li><a href="#ts_lockable"><tt>lockable</tt></a></li>
<li><a href="#ts_scopedlockable"><tt>scoped_lockable</tt></a></li>
<li><a href="#ts_guardedvar"><tt>guarded_var</tt></a></li>
<li><a href="#ts_ptguardedvar"><tt>pt_guarded_var</tt></a></li>
<li><a href="#ts_guardedby"><tt>guarded_by(l)</tt></a></li>
<li><a href="#ts_ptguardedby"><tt>pt_guarded_by(l)</tt></a></li>
<li><a href="#ts_acquiredbefore"><tt>acquired_before(...)</tt></a></li>
<li><a href="#ts_acquiredafter"><tt>acquired_after(...)</tt></a></li>
<li><a href="#ts_elf"><tt>exclusive_lock_function(...)</tt></a></li>
<li><a href="#ts_slf"><tt>shared_lock_function(...)</tt></a></li>
<li><a href="#ts_etf"><tt>exclusive_trylock_function(...)</tt></a></li>
<li><a href="#ts_stf"><tt>shared_trylock_function(...)</tt></a></li>
<li><a href="#ts_uf"><tt>unlock_function(...)</tt></a></li>
<li><a href="#ts_lr"><tt>lock_returned(l)</tt></a></li>
<li><a href="#ts_le"><tt>locks_excluded(...)</tt></a></li>
<li><a href="#ts_elr"><tt>exclusive_locks_required(...)</tt></a></li>
<li><a href="#ts_slr"><tt>shared_locks_required(...)</tt></a></li>
</ul>
</ul>
<!-- ======================================================================= -->
@ -267,6 +302,23 @@ and will issue a warning if used in the top-level compilation
file. A warning will also be issued if an absolute path
is used in the file argument.</p>
<!-- ======================================================================= -->
<h3><a name="__has_warning">__has_warning</a></h3>
<!-- ======================================================================= -->
<p>This function-like macro takes a string literal that represents a command
line option for a warning and returns true if that is a valid warning
option.</p>
<blockquote>
<pre>
#if __has_warning("-Wformat")
...
#endif
</pre>
</blockquote>
<!-- ======================================================================= -->
<h2 id="builtinmacros">Builtin Macros</h2>
<!-- ======================================================================= -->
@ -416,12 +468,6 @@ noted.</p>
C++0x standard. As a result, all these features are enabled
with the <tt>-std=c++0x</tt> option when compiling C++ code.</p>
<h4 id="cxx_decltype">C++0x <tt>decltype()</tt></h4>
<p>Use <tt>__has_feature(cxx_decltype)</tt> or
<tt>__has_extension(cxx_decltype)</tt> to determine if support for the
<tt>decltype()</tt> specifier is enabled.</p>
<h4 id="cxx_access_control_sfinae">C++0x SFINAE includes access control</h4>
<p>Use <tt>__has_feature(cxx_access_control_sfinae)</tt> or <tt>__has_extension(cxx_access_control_sfinae)</tt> to determine whether access-control errors (e.g., calling a private constructor) are considered to be template argument deduction errors (aka SFINAE errors), per <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1170">C++ DR1170</a>.</p>
@ -432,12 +478,30 @@ with the <tt>-std=c++0x</tt> option when compiling C++ code.</p>
<tt>__has_extension(cxx_alias_templates)</tt> to determine if support for
C++0x's alias declarations and alias templates is enabled.</p>
<h4 id="cxx_alignas">C++0x alignment specifiers</h4>
<p>Use <tt>__has_feature(cxx_alignas)</tt> or
<tt>__has_extension(cxx_alignas)</tt> to determine if support for alignment
specifiers using <tt>alignas</tt> is enabled.</p>
<h4 id="cxx_attributes">C++0x attributes</h4>
<p>Use <tt>__has_feature(cxx_attributes)</tt> or
<tt>__has_extension(cxx_attributes)</tt> to determine if support for attribute
parsing with C++0x's square bracket notation is enabled.</p>
<h4 id="cxx_constexpr">C++0x generalized constant expressions</h4>
<p>Use <tt>__has_feature(cxx_constexpr)</tt> to determine if support
for generalized constant expressions (e.g., <tt>constexpr</tt>) is
enabled. Clang does not currently implement this feature.</p>
<h4 id="cxx_decltype">C++0x <tt>decltype()</tt></h4>
<p>Use <tt>__has_feature(cxx_decltype)</tt> or
<tt>__has_extension(cxx_decltype)</tt> to determine if support for the
<tt>decltype()</tt> specifier is enabled.</p>
<h4 id="cxx_default_function_template_args">C++0x default template arguments in function templates</h4>
<p>Use <tt>__has_feature(cxx_default_function_template_args)</tt> or
@ -455,11 +519,46 @@ support for delegating constructors is enabled.</p>
<tt>__has_extension(cxx_deleted_functions)</tt> to determine if support for
deleted function definitions (with <tt>= delete</tt>) is enabled.</p>
<h4 id="cxx_explicit_conversions">C++0x explicit conversion functions</h3>
<p>Use <tt>__has_feature(cxx_explicit_conversions)</tt> to determine if support for <tt>explicit</tt> conversion functions is enabled.</p>
<h4 id="cxx_generalized_initializers">C++0x generalized initializers</h4>
<p>Use <tt>__has_feature(cxx_generalized_initializers)</tt> to determine if
support for generalized initializers (using braced lists and
<tt>std::initializer_list</tt>) is enabled. Clang does not currently implement
this feature.</p>
<h4 id="cxx_implicit_moves">C++0x implicit move constructors/assignment operators</h4>
<p>Use <tt>__has_feature(cxx_implicit_moves)</tt> to determine if Clang will
implicitly generate move constructors and move assignment operators where needed.</p>
<h4 id="cxx_inheriting_constructors">C++0x inheriting constructors</h4>
<p>Use <tt>__has_feature(cxx_inheriting_constructors)</tt> to determine if support for inheriting constructors is enabled. Clang does not currently implement this feature.</p>
<h4 id="cxx_inline_namespaces">C++0x inline namespaces</h4>
<p>Use <tt>__has_feature(cxx_inline_namespaces)</tt> or
<tt>__has_extension(cxx_inline_namespaces)</tt> to determine if support for
inline namespaces is enabled.</p>
<h4 id="cxx_lambdas">C++0x lambdas</h4>
<p>Use <tt>__has_feature(cxx_lambdas)</tt> or
<tt>__has_extension(cxx_lambdas)</tt> to determine if support for lambdas
is enabled. clang does not currently implement this feature.</p>
is enabled. Clang does not currently implement this feature.</p>
<h4 id="cxx_noexcept">C++0x noexcept</h4>
<p>Use <tt>__has_feature(cxx_noexcept)</tt> or
<tt>__has_extension(cxx_noexcept)</tt> to determine if support for noexcept
exception specifications is enabled.</p>
<h4 id="cxx_nonstatic_member_init">C++0x in-class non-static data member initialization</h4>
<p>Use <tt>__has_feature(cxx_nonstatic_member_init)</tt> to determine whether in-class initialization of non-static data members is enabled.</p>
<h4 id="cxx_nullptr">C++0x <tt>nullptr</tt></h4>
@ -486,6 +585,9 @@ is enabled.</p>
<tt>__has_extension(cxx_range_for)</tt> to determine if support for the
range-based for loop is enabled. </p>
<h4 id="cxx_raw_string_literals">C++0x raw string literals</h4>
<p>Use <tt>__has_feature(cxx_raw_string_literals)</tt> to determine if support for raw string literals (e.g., <tt>R"foo\bar"</tt>) is enabled.</p>
<h4 id="cxx_rvalue_references">C++0x rvalue references</h4>
<p>Use <tt>__has_feature(cxx_rvalue_references)</tt> or
@ -505,17 +607,11 @@ compile-time assertions using <tt>static_assert</tt> is enabled.</p>
supported using the <tt>auto</tt> specifier. If this is disabled, <tt>auto</tt>
will instead be a storage class specifier, as in C or C++98.</p>
<h4 id="cxx_variadic_templates">C++0x variadic templates</h4>
<h4 id="cxx_strong_enums">C++0x strongly typed enumerations</h4>
<p>Use <tt>__has_feature(cxx_variadic_templates)</tt> or
<tt>__has_extension(cxx_variadic_templates)</tt> to determine if support
for variadic templates is enabled.</p>
<h4 id="cxx_inline_namespaces">C++0x inline namespaces</h4>
<p>Use <tt>__has_feature(cxx_inline_namespaces)</tt> or
<tt>__has_extension(cxx_inline_namespaces)</tt> to determine if support for
inline namespaces is enabled.</p>
<p>Use <tt>__has_feature(cxx_strong_enums)</tt> or
<tt>__has_extension(cxx_strong_enums)</tt> to determine if support for
strongly typed, scoped enumerations is enabled.</p>
<h4 id="cxx_trailing_return">C++0x trailing return type</h4>
@ -523,17 +619,23 @@ inline namespaces is enabled.</p>
<tt>__has_extension(cxx_trailing_return)</tt> to determine if support for the
alternate function declaration syntax with trailing return type is enabled.</p>
<h4 id="cxx_noexcept">C++0x noexcept</h4>
<h4 id="cxx_unicode_literals">C++0x Unicode string literals</h4>
<p>Use <tt>__has_feature(cxx_unicode_literals)</tt> to determine if
support for Unicode string literals is enabled.</p>
<p>Use <tt>__has_feature(cxx_noexcept)</tt> or
<tt>__has_extension(cxx_noexcept)</tt> to determine if support for noexcept
exception specifications is enabled.</p>
<h4 id="cxx_unrestricted_unions">C++0x unrestricted unions</h4>
<h4 id="cxx_strong_enums">C++0x strongly typed enumerations</h4>
<p>Use <tt>__has_feature(cxx_unrestricted_unions)</tt> to determine if support for unrestricted unions is enabled. Clang does not currently support this feature.</p>
<p>Use <tt>__has_feature(cxx_strong_enums)</tt> or
<tt>__has_extension(cxx_strong_enums)</tt> to determine if support for
strongly typed, scoped enumerations is enabled.</p>
<h4 id="cxx_user_literals">C++0x user-defined literals</h4>
<p>Use <tt>__has_feature(cxx_user_literals)</tt> to determine if support for user-defined literals is enabled. Clang does not currently support this feature.</p>
<h4 id="cxx_variadic_templates">C++0x variadic templates</h4>
<p>Use <tt>__has_feature(cxx_variadic_templates)</tt> or
<tt>__has_extension(cxx_variadic_templates)</tt> to determine if support
for variadic templates is enabled.</p>
<h3 id="c1x">C1X</h3>
@ -541,6 +643,12 @@ strongly typed, scoped enumerations is enabled.</p>
C1X standard. As a result, all these features are enabled
with the <tt>-std=c1x</tt> option when compiling C code.</p>
<h4 id="c_alignas">C1X alignment specifiers</h4>
<p>Use <tt>__has_feature(c_alignas)</tt> or <tt>__has_extension(c_alignas)</tt>
to determine if support for alignment specifiers using <tt>_Alignas</tt>
is enabled.</p>
<h4 id="c_generic_selections">C1X generic selections</h4>
<p>Use <tt>__has_feature(c_generic_selections)</tt> or
@ -599,6 +707,7 @@ struct is_convertible_to {
<li><code>__is_polymorphic</code> (GNU, Microsoft)</li>
<li><code>__is_union</code> (GNU, Microsoft)</li>
<li><code>__is_literal(type)</code>: Determines whether the given type is a literal type</li>
<li><code>__underlying_type(type)</code>: Retrieves the underlying type for a given <code>enum</code> type. This trait is required to implement the C++0x standard library.</li>
</ul>
<!-- ======================================================================= -->
@ -648,7 +757,19 @@ related result type. Similarly, the type of the expression
<code>init</code> has a related result type and its receiver is known
to have the type <code>NSArray *</code>. If neither <code>alloc</code> nor <code>init</code> had a related result type, the expressions would have had type <code>id</code>, as declared in the method signature.</p>
<p>To determine whether a method has a related result type, the first
<p>A method with a related result type can be declared by using the
type <tt>instancetype</tt> as its result type. <tt>instancetype</tt>
is a contextual keyword that is only permitted in the result type of
an Objective-C method, e.g.</p>
<pre>
@interface A
+ (<b>instancetype</b>)constructAnA;
@end
</pre>
<p>The related result type can also be inferred for some methods.
To determine whether a method has an inferred related result type, the first
word in the camel-case selector (e.g., "init" in "initWithObjects") is
considered, and the method will a related result type if its return
type is compatible with the type of its class and if</p>
@ -677,8 +798,11 @@ with the subclass type. For example:</p>
<p>Related result types only affect the type of a message send or
property access via the given method. In all other respects, a method
with a related result type is treated the same way as method without a
related result type.</p>
with a related result type is treated the same way as method that
returns <tt>id</tt>.</p>
<p>Use <tt>__has_feature(objc_instancetype)</tt> to determine whether
the <tt>instancetype</tt> contextual keyword is available.</p>
<!-- ======================================================================= -->
<h2 id="objc_arc">Automatic reference counting </h2>
@ -686,6 +810,24 @@ related result type.</p>
<p>Clang provides support for <a href="AutomaticReferenceCounting.html">automated reference counting</a> in Objective-C, which eliminates the need for manual retain/release/autorelease message sends. There are two feature macros associated with automatic reference counting: <code>__has_feature(objc_arc)</code> indicates the availability of automated reference counting in general, while <code>__has_feature(objc_arc_weak)</code> indicates that automated reference counting also includes support for <code>__weak</code> pointers to Objective-C objects.</p>
<!-- ======================================================================= -->
<h2 id="objc_fixed_enum">Enumerations with a fixed underlying type</h2>
<!-- ======================================================================= -->
<p>Clang provides support for C++0x enumerations with a fixed
underlying type within Objective-C. For example, one can write an
enumeration type as:</p>
<pre>
typedef enum : unsigned char { Red, Green, Blue } Color;
</pre>
<p>This specifies that the underlying type, which is used to store the
enumeration value, is <tt>unsigned char</tt>.</p>
<p>Use <tt>__has_feature(objc_fixed_enum)</tt> to determine whether
support for fixed underlying types is available in Objective-C.</p>
<!-- ======================================================================= -->
<h2 id="overloading-in-c">Function Overloading in C</h2>
<!-- ======================================================================= -->
@ -786,6 +928,41 @@ caveats to this use of name mangling:</p>
<p>Query for this feature with __has_extension(attribute_overloadable).</p>
<!-- ======================================================================= -->
<h2 id="complex-list-init">Initializer lists for complex numbers in C</h2>
<!-- ======================================================================= -->
<p>clang supports an extension which allows the following in C:</p>
<blockquote>
<pre>
#include &lt;math.h&gt;
#include &lt;complex.h&gt;
complex float x = { 1.0f, INFINITY }; // Init to (1, Inf)
</pre>
</blockquote>
<p>This construct is useful because there is no way to separately
initialize the real and imaginary parts of a complex variable in
standard C, given that clang does not support <code>_Imaginary</code>.
(clang also supports the <code>__real__</code> and <code>__imag__</code>
extensions from gcc, which help in some cases, but are not usable in
static initializers.)
<p>Note that this extension does not allow eliding the braces; the
meaning of the following two lines is different:</p>
<blockquote>
<pre>
complex float x[] = { { 1.0f, 1.0f } }; // [0] = (1, 1)
complex float x[] = { 1.0f, 1.0f }; // [0] = (1, 0), [1] = (1, 0)
</pre>
</blockquote>
<p>This extension also works in C++ mode, as far as that goes, but does not
apply to the C++ <code>std::complex</code>. (In C++11, list
initialization allows the same syntax to be used with
<code>std::complex</code> with the same meaning.)
<!-- ======================================================================= -->
<h2 id="builtins">Builtin Functions</h2>
@ -1087,6 +1264,149 @@ balance in some way.</p>
<p>Query for these features with <tt>__has_attribute(ns_consumed)</tt>,
<tt>__has_attribute(ns_returns_retained)</tt>, etc.</p>
<!-- ======================================================================= -->
<h2 id="threadsafety">Thread-Safety Annotation Checking</h2>
<!-- ======================================================================= -->
<p>Clang supports additional attributes for checking basic locking policies in
multithreaded programs.
Clang currently parses the following list of attributes, although
<b>the implementation for these annotations is currently in development.</b>
For more details, see the
<a href="http://gcc.gnu.org/wiki/ThreadSafetyAnnotation">GCC implementation</a>.
</p>
<h4 id="ts_noanal">no_thread_safety_analysis</h4>
<p>Use <tt>__attribute__((no_thread_safety_analysis))</tt> on a function
declaration to specify that the thread safety analysis should not be run on that
function. This attribute provides an escape hatch (e.g. for situations when it
is difficult to annotate the locking policy). </p>
<h4 id="ts_lockable">lockable</h4>
<p>Use <tt>__attribute__((lockable))</tt> on a class definition to specify
that it has a lockable type (e.g. a Mutex class). This annotation is primarily
used to check consistency.</p>
<h4 id="ts_scopedlockable">scoped_lockable</h4>
<p>Use <tt>__attribute__((scoped_lockable))</tt> on a class definition to
specify that it has a "scoped" lockable type. Objects of this type will acquire
the lock upon construction and release it upon going out of scope.
This annotation is primarily used to check
consistency.</p>
<h4 id="ts_guardedvar">guarded_var</h4>
<p>Use <tt>__attribute__((guarded_var))</tt> on a variable declaration to
specify that the variable must be accessed while holding some lock.</p>
<h4 id="ts_ptguardedvar">pt_guarded_var</h4>
<p>Use <tt>__attribute__((pt_guarded_var))</tt> on a pointer declaration to
specify that the pointer must be dereferenced while holding some lock.</p>
<h4 id="ts_guardedby">guarded_by(l)</h4>
<p>Use <tt>__attribute__((guarded_by(l)))</tt> on a variable declaration to
specify that the variable must be accessed while holding lock <tt>l</tt>.</p>
<h4 id="ts_ptguardedby">pt_guarded_by(l)</h4>
<p>Use <tt>__attribute__((pt_guarded_by(l)))</tt> on a pointer declaration to
specify that the pointer must be dereferenced while holding lock <tt>l</tt>.</p>
<h4 id="ts_acquiredbefore">acquired_before(...)</h4>
<p>Use <tt>__attribute__((acquired_before(...)))</tt> on a declaration
of a lockable variable to specify that the lock must be acquired before all
attribute arguments. Arguments must be lockable type, and there must be at
least one argument.</p>
<h4 id="ts_acquiredafter">acquired_after(...)</h4>
<p>Use <tt>__attribute__((acquired_after(...)))</tt> on a declaration
of a lockable variable to specify that the lock must be acquired after all
attribute arguments. Arguments must be lockable type, and there must be at
least one argument.</p>
<h4 id="ts_elf">exclusive_lock_function(...)</h4>
<p>Use <tt>__attribute__((exclusive_lock_function(...)))</tt> on a function
declaration to specify that the function acquires all listed locks
exclusively. This attribute takes zero or more arguments: either of lockable
type or integers indexing into function parameters of lockable type. If no
arguments are given, the acquired lock is implicitly <tt>this</tt> of the
enclosing object.</p>
<h4 id="ts_slf">shared_lock_function(...)</h4>
<p>Use <tt>__attribute__((shared_lock_function(...)))</tt> on a function
declaration to specify that the function acquires all listed locks, although
the locks may be shared (e.g. read locks). This attribute takes zero or more
arguments: either of lockable type or integers indexing into function
parameters of lockable type. If no arguments are given, the acquired lock is
implicitly <tt>this</tt> of the enclosing object.</p>
<h4 id="ts_etf">exclusive_trylock_function(...)</h4>
<p>Use <tt>__attribute__((exclusive_lock_function(...)))</tt> on a function
declaration to specify that the function will try (without blocking) to acquire
all listed locks exclusively. This attribute takes one or more arguments. The
first argument is an integer or boolean value specifying the return value of a
successful lock acquisition. The remaining arugments are either of lockable type
or integers indexing into function parameters of lockable type. If only one
argument is given, the acquired lock is implicitly <tt>this</tt> of the
enclosing object.</p>
<h4 id="ts_stf">shared_trylock_function(...)</h4>
<p>Use <tt>__attribute__((shared_lock_function(...)))</tt> on a function
declaration to specify that the function will try (without blocking) to acquire
all listed locks, although the locks may be shared (e.g. read locks). This
attribute takes one or more arguments. The first argument is an integer or
boolean value specifying the return value of a successful lock acquisition. The
remaining arugments are either of lockable type or integers indexing into
function parameters of lockable type. If only one argument is given, the
acquired lock is implicitly <tt>this</tt> of the enclosing object.</p>
<h4 id="ts_uf">unlock_function(...)</h4>
<p>Use <tt>__attribute__((unlock_function(...)))</tt> on a function
declaration to specify that the function release all listed locks. This
attribute takes zero or more arguments: either of lockable type or integers
indexing into function parameters of lockable type. If no arguments are given,
the acquired lock is implicitly <tt>this</tt> of the enclosing object.</p>
<h4 id="ts_lr">lock_returned(l)</h4>
<p>Use <tt>__attribute__((lock_returned(l)))</tt> on a function
declaration to specify that the function returns lock <tt>l</tt> (<tt>l</tt>
must be of lockable type). This annotation is used to aid in resolving lock
expressions.</p>
<h4 id="ts_le">locks_excluded(...)</h4>
<p>Use <tt>__attribute__((locks_excluded(...)))</tt> on a function declaration
to specify that the function must not be called with the listed locks. Arguments
must be lockable type, and there must be at least one argument.</p>
<h4 id="ts_elr">exclusive_locks_required(...)</h4>
<p>Use <tt>__attribute__((exclusive_locks_required(...)))</tt> on a function
declaration to specify that the function must be called while holding the listed
exclusive locks. Arguments must be lockable type, and there must be at
least one argument.</p>
<h4 id="ts_slr">shared_locks_required(...)</h4>
<p>Use <tt>__attribute__((shared_locks_required(...)))</tt> on a function
declaration to specify that the function must be called while holding the listed
shared locks. Arguments must be lockable type, and there must be at
least one argument.</p>
</div>
</body>
</html>

View File

@ -39,6 +39,7 @@ td {
<li><a href="#diagnostics_categories">Diagnostic Categories</a></li>
<li><a href="#diagnostics_commandline">Controlling Diagnostics via Command Line Flags</a></li>
<li><a href="#diagnostics_pragmas">Controlling Diagnostics via Pragmas</a></li>
<li><a href="#diagnostics_enable_everything">Enabling All Warnings</a></li>
<li><a href="#analyzer_diagnositics">Controlling Static Analyzer Diagnostics</a></li>
</ul>
</li>
@ -626,6 +627,16 @@ GCC do not support the exact same set of warnings, so even when using GCC
compatible #pragmas there is no guarantee that they will have identical behaviour
on both compilers. </p>
<h4 id="diagnostics_enable_everything">Enabling All Warnings</h4>
<p>In addition to the traditional <tt>-W</tt> flags, one can enable <b>all</b>
warnings by passing <tt>-Weverything</tt>.
This works as expected with <tt>-Werror</tt>,
and also includes the warnings from <tt>-pedantic</tt>.</p>
<p>Note that when combined with <tt>-w</tt> (which disables all warnings), that
flag wins.</p>
<h4 id="analyzer_diagnositics">Controlling Static Analyzer Diagnostics</h4>
<p>While not strictly part of the compiler, the diagnostics from Clang's <a
@ -1059,18 +1070,28 @@ Clang assumes directories as below;</p>
<h5>MinGW-w64</h5>
<p>For x32(i686-w64-mingw32), it is not supported yet.</p>
<p>For x64(x86_64-w64-mingw32), <a href="http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20110321/118499.html">an essential patch(LLVM's r128206)</a> would be needed. It is incompatible to <a href="http://tdm-gcc.tdragon.net/development">TDM-GCC</a> due to the definition of symbol &quot;<code>___chkstk</code>&quot;. Clang assumes as below;<p>
<p>For 32-bit (i686-w64-mingw32), and 64-bit (x86_64-w64-mingw32), Clang assumes as below;<p>
<ul>
<li><tt>C:/mingw/x86_64-w64-mingw32/include</tt></li>
<li><tt>C:/mingw/x86_64-w64-mingw32/include/c++/4.5.[23]</tt></li>
<li>GCC driver &quot;gcc.exe&quot; to build x86_64-w64-mingw32 binary.</li>
<li><tt>GCC versions 4.5.0 to 4.5.3, 4.6.0 to 4.6.2, or 4.7.0 (for the C++ header search path)</tt></li>
<li><tt>some_directory/bin/gcc.exe</tt></li>
<li><tt>some_directory/bin/clang.exe</tt></li>
<li><tt>some_directory/bin/clang++.exe</tt></li>
<li><tt>some_directory/bin/../include/c++/GCC_version</tt></li>
<li><tt>some_directory/bin/../include/c++/GCC_version/x86_64-w64-mingw32</tt></li>
<li><tt>some_directory/bin/../include/c++/GCC_version/i686-w64-mingw32</tt></li>
<li><tt>some_directory/bin/../include/c++/GCC_version/backward</tt></li>
<li><tt>some_directory/bin/../x86_64-w64-mingw32/include</tt></li>
<li><tt>some_directory/bin/../i686-w64-mingw32/include</tt></li>
<li><tt>some_directory/bin/../include</tt></li>
</ul>
<p><a href="http://llvm.org/bugs/show_bug.cgi?id=8833">Some tests might fail</a>
on x64.</p>
<p>This directory layout is standard for any toolchain you will find on the official <a href="mingw-w64.sourceforge.net">MinGW-w64 website</a>.
<p>Clang expects the GCC executable &quot;gcc.exe&quot; compiled for i686-w64-mingw32 (or x86_64-w64-mingw32) to be present on PATH.</p>
<p><a href="http://llvm.org/bugs/show_bug.cgi?id=9072">Some tests might fail</a>
on x86_64-w64-mingw32.</p>
</div>
</body>

View File

@ -39,7 +39,7 @@ OUTPUT_DIRECTORY = @abs_builddir@/doxygen
# source files, where putting all generated files in the same directory would
# otherwise cause performance problems for the file system.
CREATE_SUBDIRS = NO
CREATE_SUBDIRS = YES
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this

View File

@ -370,9 +370,39 @@ H2 {
H3 {
font-size: 100%;
}
H2, H3 {
border-bottom: 2px solid;
margin-top: 2em;
}
A.qindex {}
A.qindexRef {}
A.el { text-decoration: none; font-weight: bold }
A.elRef { font-weight: bold }
A.code { text-decoration: none; font-weight: normal; color: #4444ee }
A.codeRef { font-weight: normal; color: #4444ee }
div.memitem {
border: 1px solid #999999;
margin-top: 1.0em;
margin-bottom: 1.0em;
-webkit-border-radius: 0.5em;
-webkit-box-shadow: 3px 3px 6px #777777;
-moz-border-radius: 0.5em;
-moz-box-shadow: black 3px 3px 3px;
}
div.memproto {
background-color: #E3E4E5;
padding: 0.25em 0.5em;
-webkit-border-top-left-radius: 0.5em;
-webkit-border-top-right-radius: 0.5em;
-moz-border-radius-topleft: 0.5em;
-moz-border-radius-topright: 0.5em;
}
div.memdoc {
padding-left: 1em;
padding-right: 1em;
}

View File

@ -459,7 +459,13 @@ Add the specified directory to the search path for framework include files.
=item B<-nostdinc>
Do not search the standard system directories for include files.
Do not search the standard system directories or compiler builtin directories
for include files.
=item B<-nostdlibinc>
Do not search the standard system directories for include files, but do search
compiler builting include directories.
=item B<-nobuiltininc>

View File

@ -45,9 +45,9 @@ class PrintFunctionNamesAction : public PluginASTAction {
// Example error handling.
if (args[i] == "-an-error") {
Diagnostic &D = CI.getDiagnostics();
DiagnosticsEngine &D = CI.getDiagnostics();
unsigned DiagID = D.getCustomDiagID(
Diagnostic::Error, "invalid argument '" + args[i] + "'");
DiagnosticsEngine::Error, "invalid argument '" + args[i] + "'");
D.Report(DiagID);
return false;
}

View File

@ -0,0 +1,14 @@
set(MODULE TRUE)
set( LLVM_USED_LIBS
clangStaticAnalyzerCore
)
set( LLVM_LINK_COMPONENTS support mc)
add_clang_library(SampleAnalyzerPlugin SampleAnalyzerPlugin)
set_target_properties(SampleAnalyzerPlugin
PROPERTIES
LINKER_LANGUAGE CXX
PREFIX "")

View File

@ -0,0 +1,52 @@
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/CheckerRegistry.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
using namespace clang;
using namespace ento;
namespace {
class MainCallChecker : public Checker < check::PreStmt<CallExpr> > {
mutable llvm::OwningPtr<BugType> BT;
public:
void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
};
} // end anonymous namespace
void MainCallChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {
const ProgramState *state = C.getState();
const Expr *Callee = CE->getCallee();
const FunctionDecl *FD = state->getSVal(Callee).getAsFunctionDecl();
if (!FD)
return;
// Get the name of the callee.
IdentifierInfo *II = FD->getIdentifier();
if (!II) // if no identifier, not a simple C function
return;
if (II->isStr("main")) {
ExplodedNode *N = C.generateSink();
if (!N)
return;
if (!BT)
BT.reset(new BugType("call to main", "example analyzer plugin"));
BugReport *report = new BugReport(*BT, BT->getName(), N);
report->addRange(Callee->getSourceRange());
C.EmitReport(report);
}
}
// Register plugin!
extern "C"
void clang_registerCheckers (CheckerRegistry &registry) {
registry.addChecker<MainCallChecker>("example.MainCallChecker", "Disallows calls to functions called main");
}
extern "C"
const char clang_analyzerAPIVersionString[] = CLANG_ANALYZER_API_VERSION_STRING;

View File

@ -0,0 +1,20 @@
##===- examples/analyzer-plugin/Makefile -------------------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
CLANG_LEVEL := ../..
LIBRARYNAME = SampleAnalyzerPlugin
LINK_LIBS_IN_SHARED = 0
SHARED_LIBRARY = 1
include $(CLANG_LEVEL)/Makefile
ifeq ($(OS),Darwin)
LDFLAGS=-Wl,-undefined,dynamic_lookup
endif

View File

@ -22,12 +22,13 @@
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Config/config.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/Path.h"
#include "llvm/Target/TargetSelect.h"
#include "llvm/Support/TargetSelect.h"
using namespace clang;
using namespace clang::driver;
@ -74,10 +75,9 @@ int main(int argc, const char **argv, char * const *envp) {
new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions());
llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
Diagnostic Diags(DiagID, DiagClient);
DiagnosticsEngine Diags(DiagID, DiagClient);
Driver TheDriver(Path.str(), llvm::sys::getHostTriple(),
"a.out", /*IsProduction=*/false, /*CXXIsProduction=*/false,
Diags);
"a.out", /*IsProduction=*/false, Diags);
TheDriver.setTitle("clang interpreter");
// FIXME: This is a hack to try to force the driver to do something we can

View File

@ -115,7 +115,12 @@ enum CXAvailabilityKind {
/**
* \brief The entity is not available; any use of it will be an error.
*/
CXAvailability_NotAvailable
CXAvailability_NotAvailable,
/**
* \brief The entity is available, but not accessible; any use of it will be
* an error.
*/
CXAvailability_NotAccessible
};
/**
@ -263,7 +268,7 @@ CINDEX_LINKAGE CXFile clang_getFile(CXTranslationUnit tu,
* \brief Identifies a specific source location within a translation
* unit.
*
* Use clang_getInstantiationLocation() or clang_getSpellingLocation()
* Use clang_getExpansionLocation() or clang_getSpellingLocation()
* to map a source location to a particular file, line, and column.
*/
typedef struct {
@ -327,12 +332,25 @@ CINDEX_LINKAGE CXSourceRange clang_getNullRange();
CINDEX_LINKAGE CXSourceRange clang_getRange(CXSourceLocation begin,
CXSourceLocation end);
/**
* \brief Determine whether two ranges are equivalent.
*
* \returns non-zero if the ranges are the same, zero if they differ.
*/
CINDEX_LINKAGE unsigned clang_equalRanges(CXSourceRange range1,
CXSourceRange range2);
/**
* \brief Returns non-zero if \arg range is null.
*/
CINDEX_LINKAGE int clang_Range_isNull(CXSourceRange range);
/**
* \brief Retrieve the file, line, column, and offset represented by
* the given source location.
*
* If the location refers into a macro instantiation, retrieves the
* location of the macro instantiation.
* If the location refers into a macro expansion, retrieves the
* location of the macro expansion.
*
* \param location the location within a source file that will be decomposed
* into its parts.
@ -349,6 +367,63 @@ CINDEX_LINKAGE CXSourceRange clang_getRange(CXSourceLocation begin,
* \param offset [out] if non-NULL, will be set to the offset into the
* buffer to which the given source location points.
*/
CINDEX_LINKAGE void clang_getExpansionLocation(CXSourceLocation location,
CXFile *file,
unsigned *line,
unsigned *column,
unsigned *offset);
/**
* \brief Retrieve the file, line, column, and offset represented by
* the given source location, as specified in a # line directive.
*
* Example: given the following source code in a file somefile.c
*
* #123 "dummy.c" 1
*
* static int func(void)
* {
* return 0;
* }
*
* the location information returned by this function would be
*
* File: dummy.c Line: 124 Column: 12
*
* whereas clang_getExpansionLocation would have returned
*
* File: somefile.c Line: 3 Column: 12
*
* \param location the location within a source file that will be decomposed
* into its parts.
*
* \param filename [out] if non-NULL, will be set to the filename of the
* source location. Note that filenames returned will be for "virtual" files,
* which don't necessarily exist on the machine running clang - e.g. when
* parsing preprocessed output obtained from a different environment. If
* a non-NULL value is passed in, remember to dispose of the returned value
* using \c clang_disposeString() once you've finished with it. For an invalid
* source location, an empty string is returned.
*
* \param line [out] if non-NULL, will be set to the line number of the
* source location. For an invalid source location, zero is returned.
*
* \param column [out] if non-NULL, will be set to the column number of the
* source location. For an invalid source location, zero is returned.
*/
CINDEX_LINKAGE void clang_getPresumedLocation(CXSourceLocation location,
CXString *filename,
unsigned *line,
unsigned *column);
/**
* \brief Legacy API to retrieve the file, line, column, and offset represented
* by the given source location.
*
* This interface has been replaced by the newer interface
* \see clang_getExpansionLocation(). See that interface's documentation for
* details.
*/
CINDEX_LINKAGE void clang_getInstantiationLocation(CXSourceLocation location,
CXFile *file,
unsigned *line,
@ -816,18 +891,18 @@ enum CXTranslationUnit_Flags {
*/
CXTranslationUnit_CacheCompletionResults = 0x08,
/**
* \brief Enable precompiled preambles in C++.
* \brief DEPRECATED: Enable precompiled preambles in C++.
*
* Note: this is a *temporary* option that is available only while
* we are testing C++ precompiled preamble support.
* we are testing C++ precompiled preamble support. It is deprecated.
*/
CXTranslationUnit_CXXPrecompiledPreamble = 0x10,
/**
* \brief Enabled chained precompiled preambles in C++.
* \brief DEPRECATED: Enabled chained precompiled preambles in C++.
*
* Note: this is a *temporary* option that is available only while
* we are testing C++ precompiled preamble support.
* we are testing C++ precompiled preamble support. It is deprecated.
*/
CXTranslationUnit_CXXChainedPCH = 0x20,
@ -1094,12 +1169,14 @@ enum CXTUResourceUsageKind {
CXTUResourceUsage_ExternalASTSource_Membuffer_MMap = 10,
CXTUResourceUsage_Preprocessor = 11,
CXTUResourceUsage_PreprocessingRecord = 12,
CXTUResourceUsage_SourceManager_DataStructures = 13,
CXTUResourceUsage_Preprocessor_HeaderSearch = 14,
CXTUResourceUsage_MEMORY_IN_BYTES_BEGIN = CXTUResourceUsage_AST,
CXTUResourceUsage_MEMORY_IN_BYTES_END =
CXTUResourceUsage_PreprocessingRecord,
CXTUResourceUsage_Preprocessor_HeaderSearch,
CXTUResourceUsage_First = CXTUResourceUsage_AST,
CXTUResourceUsage_Last = CXTUResourceUsage_PreprocessingRecord
CXTUResourceUsage_Last = CXTUResourceUsage_Preprocessor_HeaderSearch
};
/**
@ -1237,8 +1314,11 @@ enum CXCursorKind {
CXCursor_ObjCSynthesizeDecl = 37,
/** \brief An Objective-C @dynamic definition. */
CXCursor_ObjCDynamicDecl = 38,
/** \brief An access specifier. */
CXCursor_CXXAccessSpecifier = 39,
CXCursor_FirstDecl = CXCursor_UnexposedDecl,
CXCursor_LastDecl = CXCursor_ObjCDynamicDecl,
CXCursor_LastDecl = CXCursor_CXXAccessSpecifier,
/* References */
CXCursor_FirstRef = 40, /* Decl references */
@ -1377,7 +1457,207 @@ enum CXCursorKind {
/** \brief An expression that represents a block literal. */
CXCursor_BlockExpr = 105,
CXCursor_LastExpr = 105,
/** \brief An integer literal.
*/
CXCursor_IntegerLiteral = 106,
/** \brief A floating point number literal.
*/
CXCursor_FloatingLiteral = 107,
/** \brief An imaginary number literal.
*/
CXCursor_ImaginaryLiteral = 108,
/** \brief A string literal.
*/
CXCursor_StringLiteral = 109,
/** \brief A character literal.
*/
CXCursor_CharacterLiteral = 110,
/** \brief A parenthesized expression, e.g. "(1)".
*
* This AST node is only formed if full location information is requested.
*/
CXCursor_ParenExpr = 111,
/** \brief This represents the unary-expression's (except sizeof and
* alignof).
*/
CXCursor_UnaryOperator = 112,
/** \brief [C99 6.5.2.1] Array Subscripting.
*/
CXCursor_ArraySubscriptExpr = 113,
/** \brief A builtin binary operation expression such as "x + y" or
* "x <= y".
*/
CXCursor_BinaryOperator = 114,
/** \brief Compound assignment such as "+=".
*/
CXCursor_CompoundAssignOperator = 115,
/** \brief The ?: ternary operator.
*/
CXCursor_ConditionalOperator = 116,
/** \brief An explicit cast in C (C99 6.5.4) or a C-style cast in C++
* (C++ [expr.cast]), which uses the syntax (Type)expr.
*
* For example: (int)f.
*/
CXCursor_CStyleCastExpr = 117,
/** \brief [C99 6.5.2.5]
*/
CXCursor_CompoundLiteralExpr = 118,
/** \brief Describes an C or C++ initializer list.
*/
CXCursor_InitListExpr = 119,
/** \brief The GNU address of label extension, representing &&label.
*/
CXCursor_AddrLabelExpr = 120,
/** \brief This is the GNU Statement Expression extension: ({int X=4; X;})
*/
CXCursor_StmtExpr = 121,
/** \brief Represents a C1X generic selection.
*/
CXCursor_GenericSelectionExpr = 122,
/** \brief Implements the GNU __null extension, which is a name for a null
* pointer constant that has integral type (e.g., int or long) and is the same
* size and alignment as a pointer.
*
* The __null extension is typically only used by system headers, which define
* NULL as __null in C++ rather than using 0 (which is an integer that may not
* match the size of a pointer).
*/
CXCursor_GNUNullExpr = 123,
/** \brief C++'s static_cast<> expression.
*/
CXCursor_CXXStaticCastExpr = 124,
/** \brief C++'s dynamic_cast<> expression.
*/
CXCursor_CXXDynamicCastExpr = 125,
/** \brief C++'s reinterpret_cast<> expression.
*/
CXCursor_CXXReinterpretCastExpr = 126,
/** \brief C++'s const_cast<> expression.
*/
CXCursor_CXXConstCastExpr = 127,
/** \brief Represents an explicit C++ type conversion that uses "functional"
* notion (C++ [expr.type.conv]).
*
* Example:
* \code
* x = int(0.5);
* \endcode
*/
CXCursor_CXXFunctionalCastExpr = 128,
/** \brief A C++ typeid expression (C++ [expr.typeid]).
*/
CXCursor_CXXTypeidExpr = 129,
/** \brief [C++ 2.13.5] C++ Boolean Literal.
*/
CXCursor_CXXBoolLiteralExpr = 130,
/** \brief [C++0x 2.14.7] C++ Pointer Literal.
*/
CXCursor_CXXNullPtrLiteralExpr = 131,
/** \brief Represents the "this" expression in C++
*/
CXCursor_CXXThisExpr = 132,
/** \brief [C++ 15] C++ Throw Expression.
*
* This handles 'throw' and 'throw' assignment-expression. When
* assignment-expression isn't present, Op will be null.
*/
CXCursor_CXXThrowExpr = 133,
/** \brief A new expression for memory allocation and constructor calls, e.g:
* "new CXXNewExpr(foo)".
*/
CXCursor_CXXNewExpr = 134,
/** \brief A delete expression for memory deallocation and destructor calls,
* e.g. "delete[] pArray".
*/
CXCursor_CXXDeleteExpr = 135,
/** \brief A unary expression.
*/
CXCursor_UnaryExpr = 136,
/** \brief ObjCStringLiteral, used for Objective-C string literals i.e. "foo".
*/
CXCursor_ObjCStringLiteral = 137,
/** \brief ObjCEncodeExpr, used for in Objective-C.
*/
CXCursor_ObjCEncodeExpr = 138,
/** \brief ObjCSelectorExpr used for in Objective-C.
*/
CXCursor_ObjCSelectorExpr = 139,
/** \brief Objective-C's protocol expression.
*/
CXCursor_ObjCProtocolExpr = 140,
/** \brief An Objective-C "bridged" cast expression, which casts between
* Objective-C pointers and C pointers, transferring ownership in the process.
*
* \code
* NSString *str = (__bridge_transfer NSString *)CFCreateString();
* \endcode
*/
CXCursor_ObjCBridgedCastExpr = 141,
/** \brief Represents a C++0x pack expansion that produces a sequence of
* expressions.
*
* A pack expansion expression contains a pattern (which itself is an
* expression) followed by an ellipsis. For example:
*
* \code
* template<typename F, typename ...Types>
* void forward(F f, Types &&...args) {
* f(static_cast<Types&&>(args)...);
* }
* \endcode
*/
CXCursor_PackExpansionExpr = 142,
/** \brief Represents an expression that computes the length of a parameter
* pack.
*
* \code
* template<typename ...Types>
* struct count {
* static const unsigned value = sizeof...(Types);
* };
* \endcode
*/
CXCursor_SizeOfPackExpr = 143,
CXCursor_LastExpr = CXCursor_SizeOfPackExpr,
/* Statements */
CXCursor_FirstStmt = 200,
@ -1404,8 +1684,130 @@ enum CXCursorKind {
*
*/
CXCursor_LabelStmt = 201,
CXCursor_LastStmt = CXCursor_LabelStmt,
/** \brief A group of statements like { stmt stmt }.
*
* This cursor kind is used to describe compound statements, e.g. function
* bodies.
*/
CXCursor_CompoundStmt = 202,
/** \brief A case statment.
*/
CXCursor_CaseStmt = 203,
/** \brief A default statement.
*/
CXCursor_DefaultStmt = 204,
/** \brief An if statement
*/
CXCursor_IfStmt = 205,
/** \brief A switch statement.
*/
CXCursor_SwitchStmt = 206,
/** \brief A while statement.
*/
CXCursor_WhileStmt = 207,
/** \brief A do statement.
*/
CXCursor_DoStmt = 208,
/** \brief A for statement.
*/
CXCursor_ForStmt = 209,
/** \brief A goto statement.
*/
CXCursor_GotoStmt = 210,
/** \brief An indirect goto statement.
*/
CXCursor_IndirectGotoStmt = 211,
/** \brief A continue statement.
*/
CXCursor_ContinueStmt = 212,
/** \brief A break statement.
*/
CXCursor_BreakStmt = 213,
/** \brief A return statement.
*/
CXCursor_ReturnStmt = 214,
/** \brief A GNU inline assembly statement extension.
*/
CXCursor_AsmStmt = 215,
/** \brief Objective-C's overall @try-@catc-@finall statement.
*/
CXCursor_ObjCAtTryStmt = 216,
/** \brief Objective-C's @catch statement.
*/
CXCursor_ObjCAtCatchStmt = 217,
/** \brief Objective-C's @finally statement.
*/
CXCursor_ObjCAtFinallyStmt = 218,
/** \brief Objective-C's @throw statement.
*/
CXCursor_ObjCAtThrowStmt = 219,
/** \brief Objective-C's @synchronized statement.
*/
CXCursor_ObjCAtSynchronizedStmt = 220,
/** \brief Objective-C's autorelease pool statement.
*/
CXCursor_ObjCAutoreleasePoolStmt = 221,
/** \brief Objective-C's collection statement.
*/
CXCursor_ObjCForCollectionStmt = 222,
/** \brief C++'s catch statement.
*/
CXCursor_CXXCatchStmt = 223,
/** \brief C++'s try statement.
*/
CXCursor_CXXTryStmt = 224,
/** \brief C++'s for (* : *) statement.
*/
CXCursor_CXXForRangeStmt = 225,
/** \brief Windows Structured Exception Handling's try statement.
*/
CXCursor_SEHTryStmt = 226,
/** \brief Windows Structured Exception Handling's except statement.
*/
CXCursor_SEHExceptStmt = 227,
/** \brief Windows Structured Exception Handling's finally statement.
*/
CXCursor_SEHFinallyStmt = 228,
/** \brief The null satement ";": C99 6.8.3p3.
*
* This cursor kind is used to describe the null statement.
*/
CXCursor_NullStmt = 230,
/** \brief Adaptor class for mixing declarations with statements and
* expressions.
*/
CXCursor_DeclStmt = 231,
CXCursor_LastStmt = CXCursor_DeclStmt,
/**
* \brief Cursor that represents the translation unit itself.
@ -1426,7 +1828,10 @@ enum CXCursorKind {
CXCursor_IBActionAttr = 401,
CXCursor_IBOutletAttr = 402,
CXCursor_IBOutletCollectionAttr = 403,
CXCursor_LastAttr = CXCursor_IBOutletCollectionAttr,
CXCursor_CXXFinalAttr = 404,
CXCursor_CXXOverrideAttr = 405,
CXCursor_AnnotateAttr = 406,
CXCursor_LastAttr = CXCursor_AnnotateAttr,
/* Preprocessing */
CXCursor_PreprocessingDirective = 500,
@ -1458,6 +1863,7 @@ enum CXCursorKind {
*/
typedef struct {
enum CXCursorKind kind;
int xdata;
void *data[3];
} CXCursor;
@ -1485,6 +1891,11 @@ CINDEX_LINKAGE CXCursor clang_getTranslationUnitCursor(CXTranslationUnit);
*/
CINDEX_LINKAGE unsigned clang_equalCursors(CXCursor, CXCursor);
/**
* \brief Returns non-zero if \arg cursor is null.
*/
int clang_Cursor_isNull(CXCursor);
/**
* \brief Compute a hash value for the given cursor.
*/
@ -1600,6 +2011,11 @@ CINDEX_LINKAGE enum CXLanguageKind {
*/
CINDEX_LINKAGE enum CXLanguageKind clang_getCursorLanguage(CXCursor cursor);
/**
* \brief Returns the translation unit that a cursor originated from.
*/
CINDEX_LINKAGE CXTranslationUnit clang_Cursor_getTranslationUnit(CXCursor);
/**
* \brief A fast container representing a set of CXCursors.
@ -1886,7 +2302,8 @@ enum CXTypeKind {
CXType_ObjCInterface = 108,
CXType_ObjCObjectPointer = 109,
CXType_FunctionNoProto = 110,
CXType_FunctionProto = 111
CXType_FunctionProto = 111,
CXType_ConstantArray = 112
};
/**
@ -1977,6 +2394,20 @@ CINDEX_LINKAGE CXType clang_getCursorResultType(CXCursor C);
*/
CINDEX_LINKAGE unsigned clang_isPODType(CXType T);
/**
* \brief Return the element type of an array type.
*
* If a non-array type is passed in, an invalid type is returned.
*/
CINDEX_LINKAGE CXType clang_getArrayElementType(CXType T);
/**
* \brief Return the the array size of a constant array.
*
* If a non-array type is passed in, -1 is returned.
*/
CINDEX_LINKAGE long long clang_getArraySize(CXType T);
/**
* \brief Returns 1 if the base class specified by the cursor with kind
* CX_CXXBaseSpecifier is virtual.
@ -1996,7 +2427,8 @@ enum CX_CXXAccessSpecifier {
/**
* \brief Returns the access control level for the C++ base specifier
* represented by a cursor with kind CX_CXXBaseSpecifier.
* represented by a cursor with kind CXCursor_CXXBaseSpecifier or
* CXCursor_AccessSpecifier.
*/
CINDEX_LINKAGE enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor);
@ -2377,6 +2809,54 @@ CINDEX_LINKAGE enum CXCursorKind clang_getTemplateCursorKind(CXCursor C);
* from which it was instantiated. Otherwise, returns a NULL cursor.
*/
CINDEX_LINKAGE CXCursor clang_getSpecializedCursorTemplate(CXCursor C);
/**
* \brief Given a cursor that references something else, return the source range
* covering that reference.
*
* \param C A cursor pointing to a member reference, a declaration reference, or
* an operator call.
* \param NameFlags A bitset with three independent flags:
* CXNameRange_WantQualifier, CXNameRange_WantTemplateArgs, and
* CXNameRange_WantSinglePiece.
* \param PieceIndex For contiguous names or when passing the flag
* CXNameRange_WantSinglePiece, only one piece with index 0 is
* available. When the CXNameRange_WantSinglePiece flag is not passed for a
* non-contiguous names, this index can be used to retreive the individual
* pieces of the name. See also CXNameRange_WantSinglePiece.
*
* \returns The piece of the name pointed to by the given cursor. If there is no
* name, or if the PieceIndex is out-of-range, a null-cursor will be returned.
*/
CINDEX_LINKAGE CXSourceRange clang_getCursorReferenceNameRange(CXCursor C,
unsigned NameFlags,
unsigned PieceIndex);
enum CXNameRefFlags {
/**
* \brief Include the nested-name-specifier, e.g. Foo:: in x.Foo::y, in the
* range.
*/
CXNameRange_WantQualifier = 0x1,
/**
* \brief Include the explicit template arguments, e.g. <int> in x.f<int>, in
* the range.
*/
CXNameRange_WantTemplateArgs = 0x2,
/**
* \brief If the name is non-contiguous, return the full spanning range.
*
* Non-contiguous names occur in Objective-C when a selector with two or more
* parameters is used, or in C++ when using an operator:
* \code
* [object doSomething:here withValue:there]; // ObjC
* return some_vector[1]; // C++
* \endcode
*/
CXNameRange_WantSinglePiece = 0x4
};
/**
* @}
@ -2801,8 +3281,7 @@ clang_getCompletionChunkText(CXCompletionString completion_string,
* \param chunk_number the 0-based index of the chunk in the completion string.
*
* \returns the completion string associated with the chunk at index
* \c chunk_number, or NULL if that chunk is not represented by a completion
* string.
* \c chunk_number.
*/
CINDEX_LINKAGE CXCompletionString
clang_getCompletionChunkCompletionString(CXCompletionString completion_string,
@ -2840,6 +3319,45 @@ clang_getCompletionPriority(CXCompletionString completion_string);
CINDEX_LINKAGE enum CXAvailabilityKind
clang_getCompletionAvailability(CXCompletionString completion_string);
/**
* \brief Retrieve the number of annotations associated with the given
* completion string.
*
* \param completion_string the completion string to query.
*
* \returns the number of annotations associated with the given completion
* string.
*/
CINDEX_LINKAGE unsigned
clang_getCompletionNumAnnotations(CXCompletionString completion_string);
/**
* \brief Retrieve the annotation associated with the given completion string.
*
* \param completion_string the completion string to query.
*
* \param annotation_number the 0-based index of the annotation of the
* completion string.
*
* \returns annotation string associated with the completion at index
* \c annotation_number, or a NULL string if that annotation is not available.
*/
CINDEX_LINKAGE CXString
clang_getCompletionAnnotation(CXCompletionString completion_string,
unsigned annotation_number);
/**
* \brief Retrieve a completion string for an arbitrary declaration or macro
* definition cursor.
*
* \param cursor The cursor to query.
*
* \returns A non-context-sensitive completion string for declaration and macro
* definition cursors, or NULL for other kinds of cursors.
*/
CINDEX_LINKAGE CXCompletionString
clang_getCursorCompletionString(CXCursor cursor);
/**
* \brief Contains the results of code-completion.
*
@ -3144,6 +3662,54 @@ CXDiagnostic clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *Results,
CINDEX_LINKAGE
unsigned long long clang_codeCompleteGetContexts(
CXCodeCompleteResults *Results);
/**
* \brief Returns the cursor kind for the container for the current code
* completion context. The container is only guaranteed to be set for
* contexts where a container exists (i.e. member accesses or Objective-C
* message sends); if there is not a container, this function will return
* CXCursor_InvalidCode.
*
* \param Results the code completion results to query
*
* \param IsIncomplete on return, this value will be false if Clang has complete
* information about the container. If Clang does not have complete
* information, this value will be true.
*
* \returns the container kind, or CXCursor_InvalidCode if there is not a
* container
*/
CINDEX_LINKAGE
enum CXCursorKind clang_codeCompleteGetContainerKind(
CXCodeCompleteResults *Results,
unsigned *IsIncomplete);
/**
* \brief Returns the USR for the container for the current code completion
* context. If there is not a container for the current context, this
* function will return the empty string.
*
* \param Results the code completion results to query
*
* \returns the USR for the container
*/
CINDEX_LINKAGE
CXString clang_codeCompleteGetContainerUSR(CXCodeCompleteResults *Results);
/**
* \brief Returns the currently-entered selector for an Objective-C message
* send, formatted like "initWithFoo:bar:". Only guaranteed to return a
* non-empty string for CXCompletionContext_ObjCInstanceMessage and
* CXCompletionContext_ObjCClassMessage.
*
* \param Results the code completion results to query
*
* \returns the selector (or partial selector) that has been entered thus far
* for an Objective-C message send.
*/
CINDEX_LINKAGE
CXString clang_codeCompleteGetObjCSelector(CXCodeCompleteResults *Results);
/**
* @}
@ -3242,6 +3808,53 @@ CINDEX_LINKAGE void clang_remap_getFilenames(CXRemapping, unsigned index,
*/
CINDEX_LINKAGE void clang_remap_dispose(CXRemapping);
/**
* @}
*/
/** \defgroup CINDEX_HIGH Higher level API functions
*
* @{
*/
enum CXVisitorResult {
CXVisit_Break,
CXVisit_Continue
};
typedef struct {
void *context;
enum CXVisitorResult (*visit)(void *context, CXCursor, CXSourceRange);
} CXCursorAndRangeVisitor;
/**
* \brief Find references of a declaration in a specific file.
*
* \param cursor pointing to a declaration or a reference of one.
*
* \param file to search for references.
*
* \param visitor callback that will receive pairs of CXCursor/CXSourceRange for
* each reference found.
* The CXSourceRange will point inside the file; if the reference is inside
* a macro (and not a macro argument) the CXSourceRange will be invalid.
*/
CINDEX_LINKAGE void clang_findReferencesInFile(CXCursor cursor, CXFile file,
CXCursorAndRangeVisitor visitor);
#ifdef __has_feature
# if __has_feature(blocks)
typedef enum CXVisitorResult
(^CXCursorAndRangeVisitorBlock)(CXCursor, CXSourceRange);
CINDEX_LINKAGE
void clang_findReferencesInFileWithBlock(CXCursor, CXFile,
CXCursorAndRangeVisitorBlock);
# endif
#endif
/**
* @}
*/

View File

@ -15,7 +15,7 @@
namespace clang {
class ASTContext;
class DiagnosticClient;
class DiagnosticConsumer;
namespace arcmt {
class MigrationPass;
@ -28,35 +28,53 @@ namespace arcmt {
/// It then checks the AST and produces errors/warning for ARC migration issues
/// that the user needs to handle manually.
///
/// \param emitPremigrationARCErrors if true all ARC errors will get emitted
/// even if the migrator can fix them, but the function will still return false
/// if all ARC errors can be fixed.
///
/// \param plistOut if non-empty, it is the file path to store the plist with
/// the pre-migration ARC diagnostics.
///
/// \returns false if no error is produced, true otherwise.
bool checkForManualIssues(CompilerInvocation &CI,
llvm::StringRef Filename, InputKind Kind,
DiagnosticClient *DiagClient);
StringRef Filename, InputKind Kind,
DiagnosticConsumer *DiagClient,
bool emitPremigrationARCErrors = false,
StringRef plistOut = StringRef());
/// \brief Works similar to checkForManualIssues but instead of checking, it
/// applies automatic modifications to source files to conform to ARC.
///
/// \returns false if no error is produced, true otherwise.
bool applyTransformations(CompilerInvocation &origCI,
llvm::StringRef Filename, InputKind Kind,
DiagnosticClient *DiagClient);
StringRef Filename, InputKind Kind,
DiagnosticConsumer *DiagClient);
/// \brief Applies automatic modifications and produces temporary files
/// and metadata into the \arg outputDir path.
///
/// \param emitPremigrationARCErrors if true all ARC errors will get emitted
/// even if the migrator can fix them, but the function will still return false
/// if all ARC errors can be fixed.
///
/// \param plistOut if non-empty, it is the file path to store the plist with
/// the pre-migration ARC diagnostics.
///
/// \returns false if no error is produced, true otherwise.
bool migrateWithTemporaryFiles(CompilerInvocation &origCI,
llvm::StringRef Filename, InputKind Kind,
DiagnosticClient *DiagClient,
llvm::StringRef outputDir);
StringRef Filename, InputKind Kind,
DiagnosticConsumer *DiagClient,
StringRef outputDir,
bool emitPremigrationARCErrors,
StringRef plistOut);
/// \brief Get the set of file remappings from the \arg outputDir path that
/// migrateWithTemporaryFiles produced.
///
/// \returns false if no error is produced, true otherwise.
bool getFileRemappings(std::vector<std::pair<std::string,std::string> > &remap,
llvm::StringRef outputDir,
DiagnosticClient *DiagClient);
StringRef outputDir,
DiagnosticConsumer *DiagClient);
typedef void (*TransformFn)(MigrationPass &pass);
@ -64,12 +82,12 @@ std::vector<TransformFn> getAllTransformations();
class MigrationProcess {
CompilerInvocation OrigCI;
DiagnosticClient *DiagClient;
DiagnosticConsumer *DiagClient;
FileRemapper Remapper;
public:
MigrationProcess(const CompilerInvocation &CI, DiagnosticClient *diagClient,
llvm::StringRef outputDir = llvm::StringRef());
MigrationProcess(const CompilerInvocation &CI, DiagnosticConsumer *diagClient,
StringRef outputDir = StringRef());
class RewriteListener {
public:
@ -78,7 +96,7 @@ class MigrationProcess {
virtual void start(ASTContext &Ctx) { }
virtual void finish() { }
virtual void insert(SourceLocation loc, llvm::StringRef text) { }
virtual void insert(SourceLocation loc, StringRef text) { }
virtual void remove(CharSourceRange range) { }
};

View File

@ -34,11 +34,15 @@ class ModifyAction : public WrapperFrontendAction {
class MigrateAction : public WrapperFrontendAction {
std::string MigrateDir;
std::string PlistOut;
bool EmitPremigrationARCErros;
protected:
virtual bool BeginInvocation(CompilerInstance &CI);
public:
MigrateAction(FrontendAction *WrappedAction, llvm::StringRef migrateDir);
MigrateAction(FrontendAction *WrappedAction, StringRef migrateDir,
StringRef plistOut,
bool emitPremigrationARCErrors);
};
}

View File

@ -10,6 +10,7 @@
#ifndef LLVM_CLANG_ARCMIGRATE_FILEREMAPPER_H
#define LLVM_CLANG_ARCMIGRATE_FILEREMAPPER_H
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/DenseMap.h"
@ -22,7 +23,7 @@ namespace llvm {
namespace clang {
class FileManager;
class FileEntry;
class Diagnostic;
class DiagnosticsEngine;
class CompilerInvocation;
namespace arcmt {
@ -41,32 +42,32 @@ class FileRemapper {
FileRemapper();
~FileRemapper();
bool initFromDisk(llvm::StringRef outputDir, Diagnostic &Diag,
bool initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag,
bool ignoreIfFilesChanged);
bool flushToDisk(llvm::StringRef outputDir, Diagnostic &Diag);
bool flushToDisk(StringRef outputDir, DiagnosticsEngine &Diag);
bool overwriteOriginal(Diagnostic &Diag,
llvm::StringRef outputDir = llvm::StringRef());
bool overwriteOriginal(DiagnosticsEngine &Diag,
StringRef outputDir = StringRef());
void remap(llvm::StringRef filePath, llvm::MemoryBuffer *memBuf);
void remap(llvm::StringRef filePath, llvm::StringRef newPath);
void remap(StringRef filePath, llvm::MemoryBuffer *memBuf);
void remap(StringRef filePath, StringRef newPath);
void applyMappings(CompilerInvocation &CI) const;
void transferMappingsAndClear(CompilerInvocation &CI);
void clear(llvm::StringRef outputDir = llvm::StringRef());
void clear(StringRef outputDir = StringRef());
private:
void remap(const FileEntry *file, llvm::MemoryBuffer *memBuf);
void remap(const FileEntry *file, const FileEntry *newfile);
const FileEntry *getOriginalFile(llvm::StringRef filePath);
const FileEntry *getOriginalFile(StringRef filePath);
void resetTarget(Target &targ);
bool report(const std::string &err, Diagnostic &Diag);
bool report(const Twine &err, DiagnosticsEngine &Diag);
std::string getRemapInfoFile(llvm::StringRef outputDir);
std::string getRemapInfoFile(StringRef outputDir);
};
} // end namespace arcmt

View File

@ -14,11 +14,13 @@
#ifndef LLVM_CLANG_AST_APVALUE_H
#define LLVM_CLANG_AST_APVALUE_H
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/APFloat.h"
namespace clang {
class CharUnits;
class DiagnosticBuilder;
class Expr;
/// APValue - This class implements a discriminated union of [uninitialized]
@ -103,7 +105,7 @@ class APValue {
bool isLValue() const { return Kind == LValue; }
bool isVector() const { return Kind == Vector; }
void print(llvm::raw_ostream &OS) const;
void print(raw_ostream &OS) const;
void dump() const;
APSInt &getInt() {
@ -233,11 +235,15 @@ class APValue {
void MakeLValue();
};
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const APValue &V) {
inline raw_ostream &operator<<(raw_ostream &OS, const APValue &V) {
V.print(OS);
return OS;
}
// Writes a concise representation of V to DB, in a single << operation.
const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
const APValue &V);
} // end namespace clang.
#endif

View File

@ -37,7 +37,6 @@
namespace llvm {
struct fltSemantics;
class raw_ostream;
}
namespace clang {
@ -45,7 +44,7 @@ namespace clang {
class ASTRecordLayout;
class BlockExpr;
class CharUnits;
class Diagnostic;
class DiagnosticsEngine;
class Expr;
class ExternalASTSource;
class ASTMutationListener;
@ -64,6 +63,7 @@ namespace clang {
class ObjCIvarDecl;
class ObjCIvarRefExpr;
class ObjCPropertyDecl;
class ParmVarDecl;
class RecordDecl;
class StoredDeclsMap;
class TagDecl;
@ -120,6 +120,7 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
mutable llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes;
mutable llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
mutable llvm::FoldingSet<AutoType> AutoTypes;
mutable llvm::FoldingSet<AtomicType> AtomicTypes;
llvm::FoldingSet<AttributedType> AttributedTypes;
mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
@ -149,10 +150,19 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
/// \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*>
ClassScopeSpecializationPattern;
/// \brief Representation of a "canonical" template template parameter that
/// is used in canonical template names.
class CanonicalTemplateTemplateParm : public llvm::FoldingSetNode {
@ -175,34 +185,41 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
TemplateTemplateParmDecl *
getCanonicalTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTP) const;
/// \brief Whether __[u]int128_t identifier is installed.
bool IsInt128Installed;
/// \brief The typedef for the __int128_t type.
mutable TypedefDecl *Int128Decl;
/// \brief The typedef for the __uint128_t type.
mutable TypedefDecl *UInt128Decl;
/// BuiltinVaListType - built-in va list type.
/// This is initially null and set by Sema::LazilyCreateBuiltin when
/// a builtin that takes a valist is encountered.
QualType BuiltinVaListType;
/// ObjCIdType - a pseudo built-in typedef type (set by Sema).
QualType ObjCIdTypedefType;
/// \brief The typedef for the predefined 'id' type.
mutable TypedefDecl *ObjCIdDecl;
/// \brief The typedef for the predefined 'SEL' type.
mutable TypedefDecl *ObjCSelDecl;
/// ObjCSelType - another pseudo built-in typedef type (set by Sema).
QualType ObjCSelTypedefType;
/// ObjCProtoType - another pseudo built-in typedef type (set by Sema).
QualType ObjCProtoType;
const RecordType *ProtoStructType;
/// ObjCClassType - another pseudo built-in typedef type (set by Sema).
QualType ObjCClassTypedefType;
/// \brief The typedef for the predefined 'Class' type.
mutable TypedefDecl *ObjCClassDecl;
// Typedefs which may be provided defining the structure of Objective-C
// pseudo-builtins
QualType ObjCIdRedefinitionType;
QualType ObjCClassRedefinitionType;
QualType ObjCSelRedefinitionType;
QualType ObjCConstantStringType;
mutable RecordDecl *CFConstantStringTypeDecl;
mutable RecordDecl *NSConstantStringTypeDecl;
mutable RecordDecl *ObjCFastEnumerationStateTypeDecl;
/// \brief The typedef declaration for the Objective-C "instancetype" type.
TypedefDecl *ObjCInstanceTypeDecl;
/// \brief The type for the C FILE type.
TypeDecl *FILEDecl;
@ -213,9 +230,15 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
TypeDecl *sigjmp_bufDecl;
/// \brief Type for the Block descriptor for Blocks CodeGen.
///
/// Since this is only used for generation of debug info, it is not
/// serialized.
mutable RecordDecl *BlockDescriptorType;
/// \brief Type for the Block descriptor for Blocks CodeGen.
///
/// Since this is only used for generation of debug info, it is not
/// serialized.
mutable RecordDecl *BlockDescriptorExtendedType;
/// \brief Declaration for the CUDA cudaConfigureCall function.
@ -295,6 +318,12 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
typedef UsuallyTinyPtrVector<const CXXMethodDecl> CXXMethodVector;
llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector> OverriddenMethods;
/// \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;
TranslationUnitDecl *TUDecl;
/// SourceMgr - The associated SourceManager object.
@ -302,7 +331,7 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
/// LangOpts - The language options used to create the AST associated with
/// this ASTContext object.
LangOptions LangOpts;
LangOptions &LangOpts;
/// \brief The allocator used to create AST objects.
///
@ -318,26 +347,29 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
CXXABI *createCXXABI(const TargetInfo &T);
/// \brief The logical -> physical address space map.
const LangAS::Map &AddrSpaceMap;
const LangAS::Map *AddrSpaceMap;
friend class ASTDeclReader;
friend class ASTReader;
friend class ASTWriter;
const TargetInfo *Target;
clang::PrintingPolicy PrintingPolicy;
public:
const TargetInfo &Target;
IdentifierTable &Idents;
SelectorTable &Selectors;
Builtin::Context &BuiltinInfo;
mutable DeclarationNameTable DeclarationNames;
llvm::OwningPtr<ExternalASTSource> ExternalSource;
ASTMutationListener *Listener;
clang::PrintingPolicy PrintingPolicy;
// Typedefs which may be provided defining the structure of Objective-C
// pseudo-builtins
QualType ObjCIdRedefinitionType;
QualType ObjCClassRedefinitionType;
QualType ObjCSelRedefinitionType;
clang::PrintingPolicy getPrintingPolicy() const { return PrintingPolicy; }
void setPrintingPolicy(clang::PrintingPolicy Policy) {
PrintingPolicy = Policy;
}
SourceManager& getSourceManager() { return SourceMgr; }
const SourceManager& getSourceManager() const { return SourceMgr; }
void *Allocate(unsigned Size, unsigned Align = 8) const {
@ -357,9 +389,11 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
return DiagAllocator;
}
const TargetInfo &getTargetInfo() const { return *Target; }
const LangOptions& getLangOptions() const { return LangOpts; }
Diagnostic &getDiagnostics() const;
DiagnosticsEngine &getDiagnostics() const;
FullSourceLoc getFullLoc(SourceLocation Loc) const {
return FullSourceLoc(Loc,SourceMgr);
@ -377,6 +411,11 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
MemberSpecializationInfo *getInstantiatedFromStaticDataMember(
const VarDecl *Var);
FunctionDecl *getClassScopeSpecializationPattern(const FunctionDecl *FD);
void setClassScopeSpecializationPattern(FunctionDecl *FD,
FunctionDecl *Pattern);
/// \brief Note that the static data member \p Inst is an instantiation of
/// the static data member template \p Tmpl of a class template.
void setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl,
@ -413,17 +452,17 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
/// BitfieldFollowsBitfield - return 'true" if 'FD' is a
/// bitfield which follows the bitfield 'LastFD'.
bool BitfieldFollowsBitfield(const FieldDecl *FD,
const FieldDecl *LastFD) const;
const FieldDecl *LastFD) const;
/// NoneBitfieldFollowsBitfield - return 'true" if 'FD' is not a
/// NonBitfieldFollowsBitfield - return 'true" if 'FD' is not a
/// bitfield which follows the bitfield 'LastFD'.
bool NoneBitfieldFollowsBitfield(const FieldDecl *FD,
const FieldDecl *LastFD) const;
bool NonBitfieldFollowsBitfield(const FieldDecl *FD,
const FieldDecl *LastFD) const;
/// BitfieldFollowsNoneBitfield - return 'true" if 'FD' is a
/// BitfieldFollowsNonBitfield - return 'true" if 'FD' is a
/// bitfield which follows the none bitfield 'LastFD'.
bool BitfieldFollowsNoneBitfield(const FieldDecl *FD,
const FieldDecl *LastFD) const;
bool BitfieldFollowsNonBitfield(const FieldDecl *FD,
const FieldDecl *LastFD) const;
// Access to the set of methods overridden by the given C++ method.
typedef CXXMethodVector::iterator overridden_cxx_method_iterator;
@ -454,6 +493,7 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
CanQualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy;
CanQualType UnsignedLongLongTy, UnsignedInt128Ty;
CanQualType FloatTy, DoubleTy, LongDoubleTy;
CanQualType HalfTy; // [OpenCL 6.1.1.1], ARM NEON
CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
CanQualType VoidPtrTy, NullPtrTy;
CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy;
@ -463,10 +503,11 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
mutable QualType AutoDeductTy; // Deduction against 'auto'.
mutable QualType AutoRRefDeductTy; // Deduction against 'auto &&'.
ASTContext(const LangOptions& LOpts, SourceManager &SM, const TargetInfo &t,
ASTContext(LangOptions& LOpts, SourceManager &SM, const TargetInfo *t,
IdentifierTable &idents, SelectorTable &sels,
Builtin::Context &builtins,
unsigned size_reserve);
unsigned size_reserve,
bool DelayInitialization = false);
~ASTContext();
@ -497,6 +538,12 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
void PrintStats() const;
const std::vector<Type*>& getTypes() const { return Types; }
/// \brief Retrieve the declaration for the 128-bit signed integer type.
TypedefDecl *getInt128Decl() const;
/// \brief Retrieve the declaration for the 128-bit unsigned integer type.
TypedefDecl *getUInt128Decl() const;
//===--------------------------------------------------------------------===//
// Type Constructors
//===--------------------------------------------------------------------===//
@ -560,6 +607,10 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
return CanQualType::CreateUnsafe(getPointerType((QualType) T));
}
/// getAtomicType - Return the uniqued reference to the atomic type for
/// the specified type.
QualType getAtomicType(QualType T) const;
/// getBlockPointerType - Return the uniqued reference to the type for a block
/// of the specified type.
QualType getBlockPointerType(QualType T) const;
@ -568,29 +619,10 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
/// blocks.
QualType getBlockDescriptorType() const;
// Set the type for a Block descriptor type.
void setBlockDescriptorType(QualType T);
/// Get the BlockDescriptorType type, or NULL if it hasn't yet been built.
QualType getRawBlockdescriptorType() {
if (BlockDescriptorType)
return getTagDeclType(BlockDescriptorType);
return QualType();
}
/// This gets the struct used to keep track of the extended descriptor for
/// pointer to blocks.
QualType getBlockDescriptorExtendedType() const;
// Set the type for a Block descriptor extended type.
void setBlockDescriptorExtendedType(QualType T);
/// Get the BlockDescriptorExtendedType type, or NULL if it hasn't yet been
/// built.
QualType getRawBlockdescriptorExtendedType() const {
if (BlockDescriptorExtendedType)
return getTagDeclType(BlockDescriptorExtendedType);
return QualType();
}
void setcudaConfigureCallDecl(FunctionDecl *FD) {
cudaConfigureCallDecl = FD;
}
@ -599,7 +631,7 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
}
/// This builds the struct used for __block variables.
QualType BuildByRefType(llvm::StringRef DeclName, QualType Ty) const;
QualType BuildByRefType(StringRef DeclName, QualType Ty) const;
/// Returns true iff we need copy/dispose helpers for the given type.
bool BlockRequiresCopying(QualType Ty) const;
@ -824,19 +856,6 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
// constant CFStrings.
QualType getCFConstantStringType() const;
// getNSConstantStringType - Return the C structure type used to represent
// constant NSStrings.
QualType getNSConstantStringType() const;
/// Get the structure type used to representation NSStrings, or NULL
/// if it hasn't yet been built.
QualType getRawNSConstantStringType() const {
if (NSConstantStringTypeDecl)
return getTagDeclType(NSConstantStringTypeDecl);
return QualType();
}
void setNSConstantStringType(QualType T);
/// Get the structure type used to representation CFStrings, or NULL
/// if it hasn't yet been built.
QualType getRawCFConstantStringType() const {
@ -852,19 +871,56 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
return ObjCConstantStringType;
}
//// This gets the struct used to keep track of fast enumerations.
QualType getObjCFastEnumerationStateType() const;
/// Get the ObjCFastEnumerationState type, or NULL if it hasn't yet
/// been built.
QualType getRawObjCFastEnumerationStateType() const {
if (ObjCFastEnumerationStateTypeDecl)
return getTagDeclType(ObjCFastEnumerationStateTypeDecl);
return QualType();
/// \brief Retrieve the type that 'id' has been defined to, which may be
/// different from the built-in 'id' if 'id' has been typedef'd.
QualType getObjCIdRedefinitionType() const {
if (ObjCIdRedefinitionType.isNull())
return getObjCIdType();
return ObjCIdRedefinitionType;
}
/// \brief Set the user-written type that redefines 'id'.
void setObjCIdRedefinitionType(QualType RedefType) {
ObjCIdRedefinitionType = RedefType;
}
void setObjCFastEnumerationStateType(QualType T);
/// \brief Retrieve the type that 'Class' has been defined to, which may be
/// different from the built-in 'Class' if 'Class' has been typedef'd.
QualType getObjCClassRedefinitionType() const {
if (ObjCClassRedefinitionType.isNull())
return getObjCClassType();
return ObjCClassRedefinitionType;
}
/// \brief Set the user-written type that redefines 'SEL'.
void setObjCClassRedefinitionType(QualType RedefType) {
ObjCClassRedefinitionType = RedefType;
}
/// \brief Retrieve the type that 'SEL' has been defined to, which may be
/// different from the built-in 'SEL' if 'SEL' has been typedef'd.
QualType getObjCSelRedefinitionType() const {
if (ObjCSelRedefinitionType.isNull())
return getObjCSelType();
return ObjCSelRedefinitionType;
}
/// \brief Set the user-written type that redefines 'SEL'.
void setObjCSelRedefinitionType(QualType RedefType) {
ObjCSelRedefinitionType = RedefType;
}
/// \brief Retrieve the Objective-C "instancetype" type, if already known;
/// otherwise, returns a NULL type;
QualType getObjCInstanceType() {
return getTypeDeclType(getObjCInstanceTypeDecl());
}
/// \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; }
@ -950,26 +1006,39 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
/// purpose in characters.
CharUnits getObjCEncodingTypeSize(QualType t) const;
/// \brief Whether __[u]int128_t identifier is installed.
bool isInt128Installed() const { return IsInt128Installed; }
void setInt128Installed() { IsInt128Installed = true; }
/// \brief Retrieve the typedef corresponding to the predefined 'id' type
/// in Objective-C.
TypedefDecl *getObjCIdDecl() const;
/// This setter/getter represents the ObjC 'id' type. It is setup lazily, by
/// Sema. id is always a (typedef for a) pointer type, a pointer to a struct.
QualType getObjCIdType() const { return ObjCIdTypedefType; }
void setObjCIdType(QualType T);
QualType getObjCIdType() const {
return getTypeDeclType(getObjCIdDecl());
}
void setObjCSelType(QualType T);
QualType getObjCSelType() const { return ObjCSelTypedefType; }
/// \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 {
return getTypeDeclType(getObjCSelDecl());
}
void setObjCProtoType(QualType QT);
QualType getObjCProtoType() const { return ObjCProtoType; }
/// \brief Retrieve the typedef declaration corresponding to the predefined
/// Objective-C 'Class' type.
TypedefDecl *getObjCClassDecl() const;
/// This setter/getter repreents the ObjC 'Class' type. It is setup lazily, by
/// Sema. 'Class' is always a (typedef for a) pointer type, a pointer to a
/// struct.
QualType getObjCClassType() const { return ObjCClassTypedefType; }
void setObjCClassType(QualType T);
QualType getObjCClassType() const {
return getTypeDeclType(getObjCClassDecl());
}
void setBuiltinVaListType(QualType T);
QualType getBuiltinVaListType() const { return BuiltinVaListType; }
@ -1145,7 +1214,7 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
const ASTRecordLayout &getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D)
const;
void DumpRecordLayout(const RecordDecl *RD, llvm::raw_ostream &OS) const;
void DumpRecordLayout(const RecordDecl *RD, raw_ostream &OS) const;
/// getASTObjCImplementationLayout - Get or compute information about
/// the layout of the specified Objective-C implementation. This may
@ -1164,13 +1233,9 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
bool isNearlyEmpty(const CXXRecordDecl *RD) const;
MangleContext *createMangleContext();
void ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI,
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars)
const;
void DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, bool leafClass,
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) const;
SmallVectorImpl<const ObjCIvarDecl*> &Ivars) const;
unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI) const;
void CollectInheritedProtocols(const Decl *CDecl,
@ -1261,7 +1326,7 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
/// \brief Retrieves the canonical representation of the given
/// calling convention.
CallingConv getCanonicalCallConv(CallingConv CC) const {
if (CC == CC_C)
if (!LangOpts.MRTD && CC == CC_C)
return CC_Default;
return CC;
}
@ -1400,7 +1465,7 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
if (AS < LangAS::Offset || AS >= LangAS::Offset + LangAS::Count)
return AS;
else
return AddrSpaceMap[AS - LangAS::Offset];
return (*AddrSpaceMap)[AS - LangAS::Offset];
}
private:
@ -1421,13 +1486,13 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
bool typesAreBlockPointerCompatible(QualType, QualType);
bool isObjCIdType(QualType T) const {
return T == ObjCIdTypedefType;
return T == getObjCIdType();
}
bool isObjCClassType(QualType T) const {
return T == ObjCClassTypedefType;
return T == getObjCClassType();
}
bool isObjCSelType(QualType T) const {
return T == ObjCSelTypedefType;
return T == getObjCSelType();
}
bool QualifiedIdConformsQualifiedId(QualType LHS, QualType RHS);
bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS,
@ -1462,6 +1527,10 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
bool Unqualified = false);
QualType mergeObjCGCQualifiers(QualType, QualType);
bool FunctionTypesMatchOnNSConsumedAttrs(
const FunctionProtoType *FromFunctionType,
const FunctionProtoType *ToFunctionType);
void ResetObjCLayout(const ObjCContainerDecl *CD) {
ObjCLayouts[CD] = 0;
@ -1521,6 +1590,22 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
/// \brief Set the implementation of ObjCCategoryDecl.
void setObjCImplementation(ObjCCategoryDecl *CatD,
ObjCCategoryImplDecl *ImplD);
/// \brief Get the duplicate declaration of a ObjCMethod in the same
/// interface, or null if non exists.
const ObjCMethodDecl *getObjCMethodRedeclaration(
const ObjCMethodDecl *MD) const {
llvm::DenseMap<const ObjCMethodDecl*, const ObjCMethodDecl*>::const_iterator
I = ObjCMethodRedecls.find(MD);
if (I == ObjCMethodRedecls.end())
return 0;
return I->second;
}
void setObjCMethodRedeclaration(const ObjCMethodDecl *MD,
const ObjCMethodDecl *Redecl) {
ObjCMethodRedecls[MD] = Redecl;
}
/// \brief Set the copy inialization expression of a block var decl.
void setBlockVarCopyInits(VarDecl*VD, Expr* Init);
@ -1570,6 +1655,15 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
/// it is not used.
bool DeclMustBeEmitted(const Decl *D);
/// \brief Used by ParmVarDecl to store on the side the
/// index of the parameter when it exceeds the size of the normal bitfield.
void setParameterIndex(const ParmVarDecl *D, unsigned index);
/// \brief Used by ParmVarDecl to retrieve on the side the
/// index of the parameter when it exceeds the size of the normal bitfield.
unsigned getParameterIndex(const ParmVarDecl *D) const;
//===--------------------------------------------------------------------===//
// Statistics
//===--------------------------------------------------------------------===//
@ -1620,7 +1714,18 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
ASTContext(const ASTContext&); // DO NOT IMPLEMENT
void operator=(const ASTContext&); // DO NOT IMPLEMENT
void InitBuiltinTypes();
public:
/// \brief Initialize built-in types.
///
/// This routine may only be invoked once for a given ASTContext object.
/// It is normally invoked by the ASTContext constructor. However, the
/// constructor can be asked to delay initialization, which places the burden
/// of calling this function on the user of that object.
///
/// \param Target The target
void InitBuiltinTypes(const TargetInfo &Target);
private:
void InitBuiltinType(CanQualType &R, BuiltinType::Kind K);
// Return the ObjC type encoding for a given type.
@ -1644,7 +1749,7 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
private:
/// \brief A set of deallocations that should be performed when the
/// ASTContext is destroyed.
llvm::SmallVector<std::pair<void (*)(void*), void *>, 16> Deallocations;
SmallVector<std::pair<void (*)(void*), void *>, 16> Deallocations;
// FIXME: This currently contains the set of StoredDeclMaps used
// by DeclContext objects. This probably should not be in ASTContext,
@ -1660,13 +1765,13 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
};
/// @brief Utility function for constructing a nullary selector.
static inline Selector GetNullarySelector(llvm::StringRef name, ASTContext& Ctx) {
static inline Selector GetNullarySelector(StringRef name, ASTContext& Ctx) {
IdentifierInfo* II = &Ctx.Idents.get(name);
return Ctx.Selectors.getSelector(0, &II);
}
/// @brief Utility function for constructing an unary selector.
static inline Selector GetUnarySelector(llvm::StringRef name, ASTContext& Ctx) {
static inline Selector GetUnarySelector(StringRef name, ASTContext& Ctx) {
IdentifierInfo* II = &Ctx.Idents.get(name);
return Ctx.Selectors.getSelector(1, &II);
}

View File

@ -16,7 +16,7 @@ namespace clang {
namespace diag {
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
SFINAE,ACCESS,CATEGORY,BRIEF,FULL) ENUM,
SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY,BRIEF,FULL) ENUM,
#define ASTSTART
#include "clang/Basic/DiagnosticASTKinds.inc"
#undef DIAG
@ -24,27 +24,27 @@ namespace clang {
};
} // end namespace diag
/// \brief Diagnostic argument formatting function for diagnostics that
/// \brief DiagnosticsEngine argument formatting function for diagnostics that
/// involve AST nodes.
///
/// This function formats diagnostic arguments for various AST nodes,
/// including types, declaration names, nested name specifiers, and
/// declaration contexts, into strings that can be printed as part of
/// diagnostics. It is meant to be used as the argument to
/// \c Diagnostic::SetArgToStringFn(), where the cookie is an \c ASTContext
/// pointer.
/// \c DiagnosticsEngine::SetArgToStringFn(), where the cookie is an \c
/// ASTContext pointer.
void FormatASTNodeDiagnosticArgument(
Diagnostic::ArgumentKind Kind,
DiagnosticsEngine::ArgumentKind Kind,
intptr_t Val,
const char *Modifier,
unsigned ModLen,
const char *Argument,
unsigned ArgLen,
const Diagnostic::ArgumentValue *PrevArgs,
const DiagnosticsEngine::ArgumentValue *PrevArgs,
unsigned NumPrevArgs,
llvm::SmallVectorImpl<char> &Output,
SmallVectorImpl<char> &Output,
void *Cookie,
llvm::SmallVectorImpl<intptr_t> &QualTypeVals);
SmallVectorImpl<intptr_t> &QualTypeVals);
} // end namespace clang
#endif

View File

@ -25,7 +25,7 @@ namespace clang {
class ASTContext;
class Decl;
class DeclContext;
class Diagnostic;
class DiagnosticsEngine;
class Expr;
class FileManager;
class IdentifierInfo;
@ -67,7 +67,7 @@ namespace clang {
/// \brief Imported, anonymous tag declarations that are missing their
/// corresponding typedefs.
llvm::SmallVector<TagDecl *, 4> AnonTagsWithPendingTypedefs;
SmallVector<TagDecl *, 4> AnonTagsWithPendingTypedefs;
/// \brief Declaration (from, to) pairs that are known not to be equivalent
/// (which we have already complained about).

View File

@ -22,6 +22,8 @@ namespace clang {
class ClassTemplateSpecializationDecl;
class FunctionDecl;
class FunctionTemplateDecl;
class ObjCCategoryDecl;
class ObjCInterfaceDecl;
/// \brief An abstract interface that should be implemented by listeners
/// that want to be notified when an AST entity gets modified after its
@ -54,6 +56,10 @@ class ASTMutationListener {
/// \brief A static data member was implicitly instantiated.
virtual void StaticDataMemberInstantiated(const VarDecl *D) {}
/// \brief A new objc category class was added for an interface.
virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
const ObjCInterfaceDecl *IFD) {}
};
} // end namespace clang

View File

@ -14,18 +14,18 @@
#ifndef LLVM_CLANG_AST_ATTR_H
#define LLVM_CLANG_AST_ATTR_H
#include "llvm/Support/Casting.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/AttrKinds.h"
#include "clang/AST/Type.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/VersionTuple.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
#include <cassert>
#include <cstring>
#include <algorithm>
using llvm::dyn_cast;
namespace clang {
class ASTContext;
@ -58,7 +58,7 @@ namespace clang {
/// Attr - This represents one attribute.
class Attr {
private:
SourceLocation Loc;
SourceRange Range;
unsigned AttrKind : 16;
protected:
@ -67,11 +67,10 @@ class Attr {
virtual ~Attr();
void* operator new(size_t bytes) throw() {
assert(0 && "Attrs cannot be allocated with regular 'new'.");
return 0;
llvm_unreachable("Attrs cannot be allocated with regular 'new'.");
}
void operator delete(void* data) throw() {
assert(0 && "Attrs cannot be released with regular 'delete'.");
llvm_unreachable("Attrs cannot be released with regular 'delete'.");
}
public:
@ -86,8 +85,8 @@ class Attr {
}
protected:
Attr(attr::Kind AK, SourceLocation L)
: Loc(L), AttrKind(AK), Inherited(false) {}
Attr(attr::Kind AK, SourceRange R)
: Range(R), AttrKind(AK), Inherited(false) {}
public:
@ -95,8 +94,9 @@ class Attr {
return static_cast<attr::Kind>(AttrKind);
}
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
SourceLocation getLocation() const { return Range.getBegin(); }
SourceRange getRange() const { return Range; }
void setRange(SourceRange R) { Range = R; }
bool isInherited() const { return Inherited; }
@ -109,8 +109,8 @@ class Attr {
class InheritableAttr : public Attr {
protected:
InheritableAttr(attr::Kind AK, SourceLocation L)
: Attr(AK, L) {}
InheritableAttr(attr::Kind AK, SourceRange R)
: Attr(AK, R) {}
public:
void setInherited(bool I) { Inherited = I; }
@ -124,8 +124,8 @@ class InheritableAttr : public Attr {
class InheritableParamAttr : public InheritableAttr {
protected:
InheritableParamAttr(attr::Kind AK, SourceLocation L)
: InheritableAttr(AK, L) {}
InheritableParamAttr(attr::Kind AK, SourceRange R)
: InheritableAttr(AK, R) {}
public:
// Implement isa/cast/dyncast/etc.
@ -138,8 +138,8 @@ class InheritableParamAttr : public InheritableAttr {
#include "clang/AST/Attrs.inc"
/// AttrVec - A vector of Attr, which is how they are stored on the AST.
typedef llvm::SmallVector<Attr*, 2> AttrVec;
typedef llvm::SmallVector<const Attr*, 2> ConstAttrVec;
typedef SmallVector<Attr*, 2> AttrVec;
typedef SmallVector<const Attr*, 2> ConstAttrVec;
/// DestroyAttrs - Destroy the contents of an AttrVec.
inline void DestroyAttrs (AttrVec& V, ASTContext &C) {
@ -159,12 +159,12 @@ class specific_attr_iterator {
mutable AttrVec::const_iterator Current;
void AdvanceToNext() const {
while (!llvm::isa<SpecificAttr>(*Current))
while (!isa<SpecificAttr>(*Current))
++Current;
}
void AdvanceToNext(AttrVec::const_iterator I) const {
while (Current != I && !llvm::isa<SpecificAttr>(*Current))
while (Current != I && !isa<SpecificAttr>(*Current))
++Current;
}
@ -180,11 +180,11 @@ class specific_attr_iterator {
reference operator*() const {
AdvanceToNext();
return llvm::cast<SpecificAttr>(*Current);
return cast<SpecificAttr>(*Current);
}
pointer operator->() const {
AdvanceToNext();
return llvm::cast<SpecificAttr>(*Current);
return cast<SpecificAttr>(*Current);
}
specific_attr_iterator& operator++() {

View File

@ -0,0 +1,87 @@
//===--- BaseSubobject.h - BaseSubobject class ----------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides a definition of the BaseSubobject class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_BASESUBOBJECT_H
#define LLVM_CLANG_AST_BASESUBOBJECT_H
#include "clang/AST/CharUnits.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/type_traits.h"
namespace clang {
class CXXRecordDecl;
// BaseSubobject - Uniquely identifies a direct or indirect base class.
// Stores both the base class decl and the offset from the most derived class to
// the base class. Used for vtable and VTT generation.
class BaseSubobject {
/// Base - The base class declaration.
const CXXRecordDecl *Base;
/// BaseOffset - The offset from the most derived class to the base class.
CharUnits BaseOffset;
public:
BaseSubobject() { }
BaseSubobject(const CXXRecordDecl *Base, CharUnits BaseOffset)
: Base(Base), BaseOffset(BaseOffset) { }
/// getBase - Returns the base class declaration.
const CXXRecordDecl *getBase() const { return Base; }
/// getBaseOffset - Returns the base class offset.
CharUnits getBaseOffset() const { return BaseOffset; }
friend bool operator==(const BaseSubobject &LHS, const BaseSubobject &RHS) {
return LHS.Base == RHS.Base && LHS.BaseOffset == RHS.BaseOffset;
}
};
} // end namespace clang
namespace llvm {
template<> struct DenseMapInfo<clang::BaseSubobject> {
static clang::BaseSubobject getEmptyKey() {
return clang::BaseSubobject(
DenseMapInfo<const clang::CXXRecordDecl *>::getEmptyKey(),
clang::CharUnits::fromQuantity(DenseMapInfo<int64_t>::getEmptyKey()));
}
static clang::BaseSubobject getTombstoneKey() {
return clang::BaseSubobject(
DenseMapInfo<const clang::CXXRecordDecl *>::getTombstoneKey(),
clang::CharUnits::fromQuantity(DenseMapInfo<int64_t>::getTombstoneKey()));
}
static unsigned getHashValue(const clang::BaseSubobject &Base) {
return
DenseMapInfo<const clang::CXXRecordDecl *>::getHashValue(Base.getBase()) ^
DenseMapInfo<int64_t>::getHashValue(Base.getBaseOffset().getQuantity());
}
static bool isEqual(const clang::BaseSubobject &LHS,
const clang::BaseSubobject &RHS) {
return LHS == RHS;
}
};
// It's OK to treat BaseSubobject as a POD type.
template <> struct isPodLike<clang::BaseSubobject> {
static const bool value = true;
};
}
#endif

View File

@ -66,7 +66,7 @@ struct CXXBasePathElement {
/// structure, which captures both the link from a derived class to one of its
/// direct bases and identification describing which base class
/// subobject is being used.
class CXXBasePath : public llvm::SmallVector<CXXBasePathElement, 4> {
class CXXBasePath : public SmallVector<CXXBasePathElement, 4> {
public:
CXXBasePath() : Access(AS_public) {}
@ -80,7 +80,7 @@ class CXXBasePath : public llvm::SmallVector<CXXBasePathElement, 4> {
DeclContext::lookup_result Decls;
void clear() {
llvm::SmallVectorImpl<CXXBasePathElement>::clear();
SmallVectorImpl<CXXBasePathElement>::clear();
Access = AS_public;
}
};
@ -272,14 +272,14 @@ struct UniqueVirtualMethod {
/// pair is the virtual method that overrides it (including the
/// subobject in which that virtual function occurs).
class OverridingMethods {
llvm::DenseMap<unsigned, llvm::SmallVector<UniqueVirtualMethod, 4> >
llvm::DenseMap<unsigned, SmallVector<UniqueVirtualMethod, 4> >
Overrides;
public:
// Iterate over the set of subobjects that have overriding methods.
typedef llvm::DenseMap<unsigned, llvm::SmallVector<UniqueVirtualMethod, 4> >
typedef llvm::DenseMap<unsigned, SmallVector<UniqueVirtualMethod, 4> >
::iterator iterator;
typedef llvm::DenseMap<unsigned, llvm::SmallVector<UniqueVirtualMethod, 4> >
typedef llvm::DenseMap<unsigned, SmallVector<UniqueVirtualMethod, 4> >
::const_iterator const_iterator;
iterator begin() { return Overrides.begin(); }
const_iterator begin() const { return Overrides.begin(); }
@ -289,9 +289,9 @@ class OverridingMethods {
// Iterate over the set of overriding virtual methods in a given
// subobject.
typedef llvm::SmallVector<UniqueVirtualMethod, 4>::iterator
typedef SmallVector<UniqueVirtualMethod, 4>::iterator
overriding_iterator;
typedef llvm::SmallVector<UniqueVirtualMethod, 4>::const_iterator
typedef SmallVector<UniqueVirtualMethod, 4>::const_iterator
overriding_const_iterator;
// Add a new overriding method for a particular subobject.

View File

@ -125,6 +125,12 @@ namespace clang {
/// isNegative - Test whether the quantity is less than zero.
bool isNegative() const { return Quantity < 0; }
/// isPowerOfTwo - Test whether the quantity is a power of two.
/// Zero is not a power of two.
bool isPowerOfTwo() const {
return (Quantity & -Quantity) == Quantity;
}
// Arithmetic operators.
CharUnits operator* (QuantityType N) const {
return CharUnits(Quantity * N);

View File

@ -20,6 +20,7 @@
#include "clang/AST/DeclarationName.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/Basic/Linkage.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
namespace clang {
@ -32,6 +33,7 @@ class StringLiteral;
class NestedNameSpecifier;
class TemplateParameterList;
class TemplateArgumentList;
struct ASTTemplateArgumentListInfo;
class MemberSpecializationInfo;
class FunctionTemplateSpecializationInfo;
class DependentFunctionTemplateSpecializationInfo;
@ -115,7 +117,7 @@ class NamedDecl : public Decl {
/// getName - Get the name of identifier for this declaration as a StringRef.
/// This requires that the declaration have a name and that it be a simple
/// identifier.
llvm::StringRef getName() const {
StringRef getName() const {
assert(Name.isIdentifier() && "Name is not a simple identifier");
return getIdentifier() ? getIdentifier()->getName() : "";
}
@ -132,7 +134,7 @@ class NamedDecl : public Decl {
// FIXME: Deprecated, move clients to getName().
std::string getNameAsString() const { return Name.getAsString(); }
void printName(llvm::raw_ostream &os) const { return Name.printName(os); }
void printName(raw_ostream &os) const { return Name.printName(os); }
/// getDeclName - Get the actual, stored name of the declaration,
/// which may be a special name.
@ -180,6 +182,16 @@ class NamedDecl : public Decl {
/// \brief Determine whether this declaration has linkage.
bool hasLinkage() const;
/// \brief Whether this declaration was marked as being private to the
/// module in which it was defined.
bool isModulePrivate() const { return ModulePrivate; }
/// \brief Specify whether this declaration was marked as being private
/// to the module in which it was defined.
void setModulePrivate(bool MP = true) {
ModulePrivate = MP;
}
/// \brief Determine whether this declaration is a C++ class member.
bool isCXXClassMember() const {
const DeclContext *DC = getDeclContext();
@ -294,9 +306,8 @@ class NamedDecl : public Decl {
static bool classofKind(Kind K) { return K >= firstNamed && K <= lastNamed; }
};
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
const NamedDecl *ND) {
ND->getDeclName().printName(OS);
inline raw_ostream &operator<<(raw_ostream &OS, const NamedDecl &ND) {
ND.printName(OS);
return OS;
}
@ -706,13 +717,18 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
/// \brief Whether this variable is an ARC pseudo-__strong
/// variable; see isARCPseudoStrong() for details.
unsigned ARCPseudoStrong : 1;
/// \brief Whether this variable is (C++0x) constexpr.
unsigned IsConstexpr : 1;
};
enum { NumVarDeclBits = 13 }; // one reserved bit
enum { NumVarDeclBits = 13 };
friend class ASTDeclReader;
friend class StmtIteratorBase;
protected:
enum { NumParameterIndexBits = 8 };
class ParmVarDeclBitfields {
friend class ParmVarDecl;
friend class ASTDeclReader;
@ -737,7 +753,7 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
/// The number of parameters preceding this parameter in the
/// function parameter scope in which it was declared.
unsigned ParameterIndex : 8;
unsigned ParameterIndex : NumParameterIndexBits;
};
union {
@ -802,7 +818,7 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
return !isFileVarDecl();
// Return true for: Auto, Register.
// Return false for: Extern, Static, PrivateExtern.
// Return false for: Extern, Static, PrivateExtern, OpenCLWorkGroupLocal.
return getStorageClass() >= SC_Auto;
}
@ -1128,6 +1144,10 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
bool isARCPseudoStrong() const { return VarDeclBits.ARCPseudoStrong; }
void setARCPseudoStrong(bool ps) { VarDeclBits.ARCPseudoStrong = ps; }
/// Whether this variable is (C++0x) constexpr.
bool isConstexpr() const { return VarDeclBits.IsConstexpr; }
void setConstexpr(bool IC) { VarDeclBits.IsConstexpr = IC; }
/// \brief If this variable is an instantiated static data member of a
/// class template specialization, returns the templated static data member
/// from which it was instantiated.
@ -1198,11 +1218,11 @@ class ParmVarDecl : public VarDecl {
StorageClass S, StorageClass SCAsWritten,
Expr *DefArg);
virtual SourceRange getSourceRange() const;
void setObjCMethodScopeInfo(unsigned parameterIndex) {
ParmVarDeclBits.IsObjCMethodParam = true;
ParmVarDeclBits.ParameterIndex = parameterIndex;
assert(ParmVarDeclBits.ParameterIndex == parameterIndex && "truncation!");
setParameterIndex(parameterIndex);
}
void setScopeInfo(unsigned scopeDepth, unsigned parameterIndex) {
@ -1211,8 +1231,7 @@ class ParmVarDecl : public VarDecl {
ParmVarDeclBits.ScopeDepthOrObjCQuals = scopeDepth;
assert(ParmVarDeclBits.ScopeDepthOrObjCQuals == scopeDepth && "truncation!");
ParmVarDeclBits.ParameterIndex = parameterIndex;
assert(ParmVarDeclBits.ParameterIndex == parameterIndex && "truncation!");
setParameterIndex(parameterIndex);
}
bool isObjCMethodParameter() const {
@ -1226,7 +1245,7 @@ class ParmVarDecl : public VarDecl {
/// Returns the index of this parameter in its prototype or method scope.
unsigned getFunctionScopeIndex() const {
return ParmVarDeclBits.ParameterIndex;
return getParameterIndex();
}
ObjCDeclQualifier getObjCDeclQualifier() const {
@ -1343,6 +1362,26 @@ class ParmVarDecl : public VarDecl {
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const ParmVarDecl *D) { return true; }
static bool classofKind(Kind K) { return K == ParmVar; }
private:
enum { ParameterIndexSentinel = (1 << NumParameterIndexBits) - 1 };
void setParameterIndex(unsigned parameterIndex) {
if (parameterIndex >= ParameterIndexSentinel) {
setParameterIndexLarge(parameterIndex);
return;
}
ParmVarDeclBits.ParameterIndex = parameterIndex;
assert(ParmVarDeclBits.ParameterIndex == parameterIndex && "truncation!");
}
unsigned getParameterIndex() const {
unsigned d = ParmVarDeclBits.ParameterIndex;
return d == ParameterIndexSentinel ? getParameterIndexLarge() : d;
}
void setParameterIndexLarge(unsigned parameterIndex);
unsigned getParameterIndexLarge() const;
};
/// FunctionDecl - An instance of this class is created to represent a
@ -1394,6 +1433,7 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
bool IsExplicitlyDefaulted : 1; //sunk from CXXMethodDecl
bool HasImplicitReturnZero : 1;
bool IsLateTemplateParsed : 1;
bool IsConstexpr : 1;
/// \brief End part of this FunctionDecl's source range.
///
@ -1460,13 +1500,14 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
void setInstantiationOfMemberFunction(ASTContext &C, FunctionDecl *FD,
TemplateSpecializationKind TSK);
void setParams(ASTContext &C, ParmVarDecl **NewParamInfo, unsigned NumParams);
void setParams(ASTContext &C, llvm::ArrayRef<ParmVarDecl *> NewParamInfo);
protected:
FunctionDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc,
const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
StorageClass S, StorageClass SCAsWritten, bool isInlineSpecified)
StorageClass S, StorageClass SCAsWritten, bool isInlineSpecified,
bool isConstexprSpecified)
: DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo,
StartLoc),
DeclContext(DK),
@ -1477,7 +1518,7 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false),
IsDefaulted(false), IsExplicitlyDefaulted(false),
HasImplicitReturnZero(false), IsLateTemplateParsed(false),
EndRangeLoc(NameInfo.getEndLoc()),
IsConstexpr(isConstexprSpecified), EndRangeLoc(NameInfo.getEndLoc()),
TemplateOrSpecialization(),
DNLoc(NameInfo.getInfo()) {}
@ -1500,11 +1541,13 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
StorageClass SC = SC_None,
StorageClass SCAsWritten = SC_None,
bool isInlineSpecified = false,
bool hasWrittenPrototype = true) {
bool hasWrittenPrototype = true,
bool isConstexprSpecified = false) {
DeclarationNameInfo NameInfo(N, NLoc);
return FunctionDecl::Create(C, DC, StartLoc, NameInfo, T, TInfo,
SC, SCAsWritten,
isInlineSpecified, hasWrittenPrototype);
isInlineSpecified, hasWrittenPrototype,
isConstexprSpecified);
}
static FunctionDecl *Create(ASTContext &C, DeclContext *DC,
@ -1514,7 +1557,8 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
StorageClass SC = SC_None,
StorageClass SCAsWritten = SC_None,
bool isInlineSpecified = false,
bool hasWrittenPrototype = true);
bool hasWrittenPrototype = true,
bool isConstexprSpecified = false);
DeclarationNameInfo getNameInfo() const {
return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
@ -1600,10 +1644,6 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
bool isPure() const { return IsPure; }
void setPure(bool P = true);
/// Whether this is a constexpr function or constexpr constructor.
// FIXME: C++0x: Implement tracking of the constexpr specifier.
bool isConstExpr() const { return false; }
/// Whether this templated function will be late parsed.
bool isLateTemplateParsed() const { return IsLateTemplateParsed; }
void setLateTemplateParsed(bool ILT = true) { IsLateTemplateParsed = ILT; }
@ -1646,6 +1686,10 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
bool hasInheritedPrototype() const { return HasInheritedPrototype; }
void setHasInheritedPrototype(bool P = true) { HasInheritedPrototype = P; }
/// Whether this is a (C++0x) constexpr function or constexpr constructor.
bool isConstexpr() const { return IsConstexpr; }
void setConstexpr(bool IC) { IsConstexpr = IC; }
/// \brief Whether this function has been deleted.
///
/// A function that is "deleted" (via the C++0x "= delete" syntax)
@ -1726,8 +1770,8 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
assert(i < getNumParams() && "Illegal param #");
return ParamInfo[i];
}
void setParams(ParmVarDecl **NewParamInfo, unsigned NumParams) {
setParams(getASTContext(), NewParamInfo, NumParams);
void setParams(llvm::ArrayRef<ParmVarDecl *> NewParamInfo) {
setParams(getASTContext(), NewParamInfo);
}
/// getMinRequiredArguments - Returns the minimum number of arguments
@ -1768,11 +1812,13 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
}
/// \brief Determine whether this function should be inlined, because it is
/// either marked "inline" or is a member function of a C++ class that
/// was defined in the class body.
/// either marked "inline" or "constexpr" or is a member function of a class
/// that was defined in the class body.
bool isInlined() const;
bool isInlineDefinitionExternallyVisible() const;
bool doesDeclarationForceExternallyVisibleDefinition() const;
/// isOverloadedOperator - Whether this function declaration
/// represents an C++ overloaded operator, e.g., "operator+".
@ -1847,7 +1893,11 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
bool isFunctionTemplateSpecialization() const {
return getPrimaryTemplate() != 0;
}
/// \brief Retrieve the class scope template pattern that this function
/// template specialization is instantiated from.
FunctionDecl *getClassScopeSpecializationPattern() const;
/// \brief If this function is actually a function template specialization,
/// retrieve information about this function template specialization.
/// Otherwise, returns NULL.
@ -1887,7 +1937,7 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
/// or if it had no explicit template argument list, returns NULL.
/// Note that it an explicit template argument list may be written empty,
/// e.g., template<> void foo<>(char* s);
const TemplateArgumentListInfo*
const ASTTemplateArgumentListInfo*
getTemplateSpecializationArgsAsWritten() const;
/// \brief Specify that this function declaration is actually a function
@ -1945,7 +1995,7 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
/// specialization or a member of a class template specialization.
///
/// \returns the first point of instantiation, if this function was
/// instantiated from a template; otherwie, returns an invalid source
/// instantiated from a template; otherwise, returns an invalid source
/// location.
SourceLocation getPointOfInstantiation() const;
@ -2033,6 +2083,7 @@ class FieldDecl : public DeclaratorDecl {
Expr *getBitWidth() const {
return isBitField() ? InitializerOrBitWidth.getPointer() : 0;
}
unsigned getBitWidthValue(const ASTContext &Ctx) const;
void setBitWidth(Expr *BW) {
assert(!InitializerOrBitWidth.getPointer() &&
"bit width or initializer already set");
@ -2308,9 +2359,10 @@ class TagDecl
/// TagDeclKind - The TagKind enum.
unsigned TagDeclKind : 2;
/// IsDefinition - True if this is a definition ("struct foo {};"), false if
/// it is a declaration ("struct foo;").
bool IsDefinition : 1;
/// IsCompleteDefinition - True if this is a definition ("struct foo
/// {};"), false if it is a declaration ("struct foo;"). It is not
/// a definition until the definition has been fully processed.
bool IsCompleteDefinition : 1;
/// IsBeingDefined - True if this is currently being defined.
bool IsBeingDefined : 1;
@ -2320,6 +2372,9 @@ class TagDecl
/// in the syntax of a declarator.
bool IsEmbeddedInDeclarator : 1;
/// /brief True if this tag is free standing, e.g. "struct foo;".
bool IsFreeStanding : 1;
protected:
// These are used by (and only defined for) EnumDecl.
unsigned NumPositiveBits : 8;
@ -2367,9 +2422,10 @@ class TagDecl
assert((DK != Enum || TK == TTK_Enum) &&
"EnumDecl not matched with TTK_Enum");
TagDeclKind = TK;
IsDefinition = false;
IsCompleteDefinition = false;
IsBeingDefined = false;
IsEmbeddedInDeclarator = false;
IsFreeStanding = false;
setPreviousDeclaration(PrevDecl);
}
@ -2408,14 +2464,15 @@ class TagDecl
}
/// isThisDeclarationADefinition() - Return true if this declaration
/// defines the type. Provided for consistency.
/// is a completion definintion of the type. Provided for consistency.
bool isThisDeclarationADefinition() const {
return isDefinition();
return isCompleteDefinition();
}
/// isDefinition - Return true if this decl has its body specified.
bool isDefinition() const {
return IsDefinition;
/// isCompleteDefinition - Return true if this decl has its body
/// fully specified.
bool isCompleteDefinition() const {
return IsCompleteDefinition;
}
/// isBeingDefined - Return true if this decl is currently being defined.
@ -2430,6 +2487,11 @@ class TagDecl
IsEmbeddedInDeclarator = isInDeclarator;
}
bool isFreeStanding() const { return IsFreeStanding; }
void setFreeStanding(bool isFreeStanding = true) {
IsFreeStanding = isFreeStanding;
}
/// \brief Whether this declaration declares a type that is
/// dependent, i.e., a type that somehow depends on template
/// parameters.
@ -2444,14 +2506,15 @@ class TagDecl
/// getDefinition - Returns the TagDecl that actually defines this
/// struct/union/class/enum. When determining whether or not a
/// struct/union/class/enum is completely defined, one should use this method
/// as opposed to 'isDefinition'. 'isDefinition' indicates whether or not a
/// specific TagDecl is defining declaration, not whether or not the
/// struct/union/class/enum type is defined. This method returns NULL if
/// there is no TagDecl that defines the struct/union/class/enum.
TagDecl* getDefinition() const;
/// struct/union/class/enum has a definition, one should use this
/// method as opposed to 'isDefinition'. 'isDefinition' indicates
/// whether or not a specific TagDecl is defining declaration, not
/// whether or not the struct/union/class/enum type is defined.
/// This method returns NULL if there is no TagDecl that defines
/// the struct/union/class/enum.
TagDecl *getDefinition() const;
void setDefinition(bool V) { IsDefinition = V; }
void setCompleteDefinition(bool V) { IsCompleteDefinition = V; }
const char *getKindName() const {
return TypeWithKeyword::getTagTypeKindName(getTagKind());
@ -2691,7 +2754,7 @@ class EnumDecl : public TagDecl {
/// \brief Returns true if this can be considered a complete type.
bool isComplete() const {
return isDefinition() || isFixed();
return isCompleteDefinition() || isFixed();
}
/// \brief Returns the enumeration (declared within the template)
@ -2794,14 +2857,15 @@ class RecordDecl : public TagDecl {
/// \endcode
bool isInjectedClassName() const;
/// getDefinition - Returns the RecordDecl that actually defines this
/// struct/union/class. When determining whether or not a struct/union/class
/// is completely defined, one should use this method as opposed to
/// 'isDefinition'. 'isDefinition' indicates whether or not a specific
/// RecordDecl is defining declaration, not whether or not the record
/// type is defined. This method returns NULL if there is no RecordDecl
/// that defines the struct/union/tag.
RecordDecl* getDefinition() const {
/// getDefinition - Returns the RecordDecl that actually defines
/// this struct/union/class. When determining whether or not a
/// struct/union/class is completely defined, one should use this
/// method as opposed to 'isCompleteDefinition'.
/// 'isCompleteDefinition' indicates whether or not a specific
/// RecordDecl is a completed definition, not whether or not the
/// record type is defined. This method returns NULL if there is
/// no RecordDecl that defines the struct/union/tag.
RecordDecl *getDefinition() const {
return cast_or_null<RecordDecl>(TagDecl::getDefinition());
}
@ -2967,7 +3031,7 @@ class BlockDecl : public Decl, public DeclContext {
assert(i < getNumParams() && "Illegal param #");
return ParamInfo[i];
}
void setParams(ParmVarDecl **NewParamInfo, unsigned NumParams);
void setParams(llvm::ArrayRef<ParmVarDecl *> NewParamInfo);
/// hasCaptures - True if this block (or its nested blocks) captures
/// anything of local storage from its enclosing scopes.
@ -3010,8 +3074,9 @@ class BlockDecl : public Decl, public DeclContext {
/// Insertion operator for diagnostics. This allows sending NamedDecl's
/// into a diagnostic with <<.
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
NamedDecl* ND) {
DB.AddTaggedVal(reinterpret_cast<intptr_t>(ND), Diagnostic::ak_nameddecl);
const NamedDecl* ND) {
DB.AddTaggedVal(reinterpret_cast<intptr_t>(ND),
DiagnosticsEngine::ak_nameddecl);
return DB;
}

View File

@ -243,19 +243,23 @@ class Decl {
/// evaluated context or not, e.g. functions used in uninstantiated templates
/// are regarded as "referenced" but not "used".
unsigned Referenced : 1;
protected:
/// Access - Used by C++ decls for the access specifier.
// NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum
unsigned Access : 2;
friend class CXXClassMemberWrapper;
/// PCHLevel - the "level" of AST file from which this declaration was built.
unsigned PCHLevel : 2;
/// \brief Whether this declaration was loaded from an AST file.
unsigned FromASTFile : 1;
/// ChangedAfterLoad - if this declaration has changed since being loaded
unsigned ChangedAfterLoad : 1;
/// \brief Whether this declaration is private to the module in which it was
/// defined.
unsigned ModulePrivate : 1;
/// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
unsigned IdentifierNamespace : 12;
@ -269,7 +273,9 @@ class Decl {
/// This field is only valid for NamedDecls subclasses.
mutable unsigned CachedLinkage : 2;
friend class ASTDeclWriter;
friend class ASTDeclReader;
private:
void CheckAccessDeclContext() const;
@ -279,7 +285,8 @@ class Decl {
: NextDeclInContext(0), DeclCtx(DC),
Loc(L), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false), Used(false), Referenced(false),
Access(AS_none), PCHLevel(0), ChangedAfterLoad(false),
Access(AS_none), FromASTFile(0), ChangedAfterLoad(false),
ModulePrivate(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
HasCachedLinkage(0)
{
@ -289,7 +296,8 @@ class Decl {
Decl(Kind DK, EmptyShell Empty)
: NextDeclInContext(0), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false), Used(false), Referenced(false),
Access(AS_none), PCHLevel(0), ChangedAfterLoad(false),
Access(AS_none), FromASTFile(0), ChangedAfterLoad(false),
ModulePrivate(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
HasCachedLinkage(0)
{
@ -493,25 +501,10 @@ class Decl {
/// declaration cannot be weak-imported because it has a definition.
bool canBeWeakImported(bool &IsDefinition) const;
/// \brief Retrieve the level of precompiled header from which this
/// declaration was generated.
///
/// The PCH level of a declaration describes where the declaration originated
/// from. A PCH level of 0 indicates that the declaration was parsed from
/// source. A PCH level of 1 indicates that the declaration was loaded from
/// a top-level AST file. A PCH level 2 indicates that the declaration was
/// loaded from a PCH file the AST file depends on, and so on.
unsigned getPCHLevel() const { return PCHLevel; }
/// \brief The maximum PCH level that any declaration may have.
static const unsigned MaxPCHLevel = 3;
/// \brief Set the PCH level of this declaration.
void setPCHLevel(unsigned Level) {
assert(Level <= MaxPCHLevel && "PCH level exceeds the maximum");
PCHLevel = Level;
}
/// \brief Determine whether this declaration came from an AST file (such as
/// a precompiled header or module) rather than having been parsed.
bool isFromASTFile() const { return FromASTFile; }
/// \brief Query whether this declaration was changed in a significant way
/// since being loaded from an AST file.
///
@ -574,7 +567,17 @@ class Decl {
/// scoped decl is defined outside the current function or method. This is
/// roughly global variables and functions, but also handles enums (which
/// could be defined inside or outside a function etc).
bool isDefinedOutsideFunctionOrMethod() const;
bool isDefinedOutsideFunctionOrMethod() const {
return getParentFunctionOrMethod() == 0;
}
/// \brief If this decl is defined inside a function/method/block it returns
/// the corresponding DeclContext, otherwise it returns null.
const DeclContext *getParentFunctionOrMethod() const;
DeclContext *getParentFunctionOrMethod() {
return const_cast<DeclContext*>(
const_cast<const Decl*>(this)->getParentFunctionOrMethod());
}
/// \brief Retrieves the "canonical" declaration of the given declaration.
virtual Decl *getCanonicalDecl() { return this; }
@ -671,6 +674,9 @@ class Decl {
/// \brief Whether this declaration is a parameter pack.
bool isParameterPack() const;
/// \brief returns true if this declaration is a template
bool isTemplateDecl() const;
/// \brief Whether this declaration is a function or function template.
bool isFunctionOrFunctionTemplate() const;
@ -734,15 +740,16 @@ class Decl {
static DeclContext *castToDeclContext(const Decl *);
static Decl *castFromDeclContext(const DeclContext *);
void print(llvm::raw_ostream &Out, unsigned Indentation = 0) const;
void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy,
unsigned Indentation = 0) const;
void print(raw_ostream &Out, unsigned Indentation = 0,
bool PrintInstantiation = false) const;
void print(raw_ostream &Out, const PrintingPolicy &Policy,
unsigned Indentation = 0, bool PrintInstantiation = false) const;
static void printGroup(Decl** Begin, unsigned NumDecls,
llvm::raw_ostream &Out, const PrintingPolicy &Policy,
raw_ostream &Out, const PrintingPolicy &Policy,
unsigned Indentation = 0);
void dump() const;
void dumpXML() const;
void dumpXML(llvm::raw_ostream &OS) const;
void dumpXML(raw_ostream &OS) const;
private:
const Attr *getAttrsImpl() const;
@ -763,7 +770,7 @@ class PrettyStackTraceDecl : public llvm::PrettyStackTraceEntry {
SourceManager &sm, const char *Msg)
: TheDecl(theDecl), Loc(L), SM(sm), Message(Msg) {}
virtual void print(llvm::raw_ostream &OS) const;
virtual void print(raw_ostream &OS) const;
};
class DeclContextLookupResult
@ -839,7 +846,7 @@ class DeclContext {
///
/// \returns the first/last pair of declarations.
static std::pair<Decl *, Decl *>
BuildDeclChain(const llvm::SmallVectorImpl<Decl*> &Decls);
BuildDeclChain(const SmallVectorImpl<Decl*> &Decls, bool FieldsAlreadyLoaded);
DeclContext(Decl::Kind K)
: DeclKind(K), ExternalLexicalStorage(false),
@ -892,6 +899,18 @@ class DeclContext {
return DeclKind == Decl::Block;
}
bool isObjCContainer() const {
switch (DeclKind) {
case Decl::ObjCCategory:
case Decl::ObjCCategoryImpl:
case Decl::ObjCImplementation:
case Decl::ObjCInterface:
case Decl::ObjCProtocol:
return true;
}
return false;
}
bool isFunctionOrMethod() const {
switch (DeclKind) {
case Decl::Block:
@ -1243,6 +1262,15 @@ class DeclContext {
lookup_result lookup(DeclarationName Name);
lookup_const_result lookup(DeclarationName Name) const;
/// \brief A simplistic name lookup mechanism that performs name lookup
/// into this declaration context without consulting the external source.
///
/// This function should almost never be used, because it subverts the
/// usual relationship between a DeclContext and the external source.
/// See the ASTImporter for the (few, but important) use cases.
void localUncachedLookup(DeclarationName Name,
llvm::SmallVectorImpl<NamedDecl *> &Results);
/// @brief Makes a declaration visible within this context.
///
/// This routine makes the declaration D visible to name lookup
@ -1263,14 +1291,6 @@ class DeclContext {
/// the declaration chains.
void makeDeclVisibleInContext(NamedDecl *D, bool Recoverable = true);
/// \brief Deserialize all the visible declarations from external storage.
///
/// Name lookup deserializes visible declarations lazily, thus a DeclContext
/// may not have a complete name lookup table. This function deserializes
/// the rest of visible declarations from the external storage and completes
/// the name lookup table.
void MaterializeVisibleDeclsFromExternalStorage();
/// udir_iterator - Iterates through the using-directives stored
/// within this context.
typedef UsingDirectiveDecl * const * udir_iterator;
@ -1317,6 +1337,12 @@ class DeclContext {
ExternalVisibleStorage = ES;
}
/// \brief Determine whether the given declaration is stored in the list of
/// declarations lexically within this context.
bool isDeclInLexicalTraversal(const Decl *D) const {
return D && (D->NextDeclInContext || D == FirstDecl || D == LastDecl);
}
static bool classof(const Decl *D);
static bool classof(const DeclContext *D) { return true; }
#define DECL(NAME, BASE)

View File

@ -363,10 +363,10 @@ class CXXRecordDecl : public RecordDecl {
/// default constructor.
bool HasTrivialDefaultConstructor : 1;
/// HasConstExprNonCopyMoveConstructor - True when this class has at least
/// HasConstexprNonCopyMoveConstructor - True when this class has at least
/// one constexpr constructor which is neither the copy nor move
/// constructor.
bool HasConstExprNonCopyMoveConstructor : 1;
bool HasConstexprNonCopyMoveConstructor : 1;
/// HasTrivialCopyConstructor - True when this class has a trivial copy
/// constructor.
@ -468,6 +468,14 @@ class CXXRecordDecl : public RecordDecl {
/// \brief Whether we have already declared a destructor within the class.
bool DeclaredDestructor : 1;
/// \brief Whether an implicit move constructor was attempted to be declared
/// but would have been deleted.
bool FailedImplicitMoveConstructor : 1;
/// \brief Whether an implicit move assignment operator was attempted to be
/// declared but would have been deleted.
bool FailedImplicitMoveAssignment : 1;
/// NumBases - The number of base class specifiers in Bases.
unsigned NumBases;
@ -780,6 +788,33 @@ class CXXRecordDecl : public RecordDecl {
return data().DeclaredMoveConstructor;
}
/// \brief Determine whether implicit move constructor generation for this
/// class has failed before.
bool hasFailedImplicitMoveConstructor() const {
return data().FailedImplicitMoveConstructor;
}
/// \brief Set whether implicit move constructor generation for this class
/// has failed before.
void setFailedImplicitMoveConstructor(bool Failed = true) {
data().FailedImplicitMoveConstructor = Failed;
}
/// \brief Determine whether this class should get an implicit move
/// constructor or if any existing special member function inhibits this.
///
/// Covers all bullets of C++0x [class.copy]p9 except the last, that the
/// constructor wouldn't be deleted, which is only looked up from a cached
/// result.
bool needsImplicitMoveConstructor() const {
return !hasFailedImplicitMoveConstructor() &&
!hasDeclaredMoveConstructor() &&
!hasUserDeclaredCopyConstructor() &&
!hasUserDeclaredCopyAssignment() &&
!hasUserDeclaredMoveAssignment() &&
!hasUserDeclaredDestructor();
}
/// hasUserDeclaredCopyAssignment - Whether this class has a
/// user-declared copy assignment operator. When false, a copy
/// assigment operator will be implicitly declared.
@ -807,6 +842,33 @@ class CXXRecordDecl : public RecordDecl {
return data().DeclaredMoveAssignment;
}
/// \brief Determine whether implicit move assignment generation for this
/// class has failed before.
bool hasFailedImplicitMoveAssignment() const {
return data().FailedImplicitMoveAssignment;
}
/// \brief Set whether implicit move assignment generation for this class
/// has failed before.
void setFailedImplicitMoveAssignment(bool Failed = true) {
data().FailedImplicitMoveAssignment = Failed;
}
/// \brief Determine whether this class should get an implicit move
/// assignment operator or if any existing special member function inhibits
/// this.
///
/// Covers all bullets of C++0x [class.copy]p20 except the last, that the
/// constructor wouldn't be deleted.
bool needsImplicitMoveAssignment() const {
return !hasFailedImplicitMoveAssignment() &&
!hasDeclaredMoveAssignment() &&
!hasUserDeclaredCopyConstructor() &&
!hasUserDeclaredCopyAssignment() &&
!hasUserDeclaredMoveConstructor() &&
!hasUserDeclaredDestructor();
}
/// hasUserDeclaredDestructor - Whether this class has a
/// user-declared destructor. When false, a destructor will be
/// implicitly declared.
@ -889,10 +951,10 @@ class CXXRecordDecl : public RecordDecl {
data().DeclaredDefaultConstructor);
}
// hasConstExprNonCopyMoveConstructor - Whether this class has at least one
// constexpr constructor other than the copy or move constructors
bool hasConstExprNonCopyMoveConstructor() const {
return data().HasConstExprNonCopyMoveConstructor;
// hasConstexprNonCopyMoveConstructor - Whether this class has at least one
// constexpr constructor other than the copy or move constructors.
bool hasConstexprNonCopyMoveConstructor() const {
return data().HasConstexprNonCopyMoveConstructor;
}
// hasTrivialCopyConstructor - Whether this class has a trivial copy
@ -942,6 +1004,25 @@ class CXXRecordDecl : public RecordDecl {
return isTriviallyCopyable() && hasTrivialDefaultConstructor();
}
// isLiteral - Whether this class is a literal type.
//
// C++0x [basic.types]p10
// A class type that has all the following properties:
// -- a trivial destructor
// -- every constructor call and full-expression in the
// brace-or-equal-intializers for non-static data members (if any) is
// a constant expression.
// -- it is an aggregate type or has at least one constexpr constructor or
// constructor template that is not a copy or move constructor, and
// -- all non-static data members and base classes of literal types
//
// We resolve DR1361 by ignoring the second bullet.
bool isLiteral() const {
return hasTrivialDestructor() &&
(isAggregate() || hasConstexprNonCopyMoveConstructor()) &&
!hasNonLiteralTypeFieldsOrBases();
}
/// \brief If this record is an instantiation of a member class,
/// retrieves the member class from which it was instantiated.
///
@ -1237,10 +1318,10 @@ class CXXMethodDecl : public FunctionDecl {
const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isStatic, StorageClass SCAsWritten, bool isInline,
SourceLocation EndLocation)
bool isConstexpr, SourceLocation EndLocation)
: FunctionDecl(DK, RD, StartLoc, NameInfo, T, TInfo,
(isStatic ? SC_Static : SC_None),
SCAsWritten, isInline) {
SCAsWritten, isInline, isConstexpr) {
if (EndLocation.isValid())
setRangeEnd(EndLocation);
}
@ -1253,6 +1334,7 @@ class CXXMethodDecl : public FunctionDecl {
bool isStatic,
StorageClass SCAsWritten,
bool isInline,
bool isConstexpr,
SourceLocation EndLocation);
bool isStatic() const { return getStorageClass() == SC_Static; }
@ -1333,6 +1415,7 @@ class CXXMethodDecl : public FunctionDecl {
/// void g() &&;
/// void h();
/// };
/// \endcode
RefQualifierKind getRefQualifier() const {
return getType()->getAs<FunctionProtoType>()->getRefQualifier();
}
@ -1630,9 +1713,9 @@ class CXXConstructorDecl : public CXXMethodDecl {
const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isExplicitSpecified, bool isInline,
bool isImplicitlyDeclared)
bool isImplicitlyDeclared, bool isConstexpr)
: CXXMethodDecl(CXXConstructor, RD, StartLoc, NameInfo, T, TInfo, false,
SC_None, isInline, SourceLocation()),
SC_None, isInline, isConstexpr, SourceLocation()),
IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false),
CtorInitializers(0), NumCtorInitializers(0) {
setImplicit(isImplicitlyDeclared);
@ -1645,7 +1728,8 @@ class CXXConstructorDecl : public CXXMethodDecl {
const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isExplicit,
bool isInline, bool isImplicitlyDeclared);
bool isInline, bool isImplicitlyDeclared,
bool isConstexpr);
/// isExplicitSpecified - Whether this constructor declaration has the
/// 'explicit' keyword specified.
@ -1853,7 +1937,7 @@ class CXXDestructorDecl : public CXXMethodDecl {
QualType T, TypeSourceInfo *TInfo,
bool isInline, bool isImplicitlyDeclared)
: CXXMethodDecl(CXXDestructor, RD, StartLoc, NameInfo, T, TInfo, false,
SC_None, isInline, SourceLocation()),
SC_None, isInline, /*isConstexpr=*/false, SourceLocation()),
ImplicitlyDefined(false), OperatorDelete(0) {
setImplicit(isImplicitlyDeclared);
}
@ -1916,9 +2000,9 @@ class CXXConversionDecl : public CXXMethodDecl {
const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isInline, bool isExplicitSpecified,
SourceLocation EndLocation)
bool isConstexpr, SourceLocation EndLocation)
: CXXMethodDecl(CXXConversion, RD, StartLoc, NameInfo, T, TInfo, false,
SC_None, isInline, EndLocation),
SC_None, isInline, isConstexpr, EndLocation),
IsExplicitSpecified(isExplicitSpecified) { }
public:
@ -1928,6 +2012,7 @@ class CXXConversionDecl : public CXXMethodDecl {
const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isInline, bool isExplicit,
bool isConstexpr,
SourceLocation EndLocation);
/// IsExplicitSpecified - Whether this conversion function declaration is

View File

@ -31,7 +31,7 @@ class DependentDiagnostic;
struct StoredDeclsList {
/// DeclsTy - When in vector form, this is what the Data pointer points to.
typedef llvm::SmallVector<NamedDecl *, 4> DeclsTy;
typedef SmallVector<NamedDecl *, 4> DeclsTy;
/// \brief The stored data, which will be either a pointer to a NamedDecl,
/// or a pointer to a vector.

View File

@ -15,6 +15,7 @@
#define LLVM_CLANG_AST_DECLOBJC_H
#include "clang/AST/Decl.h"
#include "clang/AST/SelectorLocationsKind.h"
#include "llvm/ADT/STLExtras.h"
namespace clang {
@ -127,6 +128,12 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
// Method has a definition.
unsigned IsDefined : 1;
/// \brief Method redeclaration in the same interface.
unsigned IsRedeclaration : 1;
/// \brief Is redeclared in the same interface.
mutable unsigned HasRedeclaration : 1;
// NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum
/// @required/@optional
unsigned DeclImplementation : 2;
@ -138,8 +145,9 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
/// \brief Indicates whether this method has a related result type.
unsigned RelatedResultType : 1;
// Number of args separated by ':' in a method declaration.
unsigned NumSelectorArgs;
/// \brief Whether the locations of the selector identifiers are in a
/// "standard" position, a enum SelectorLocationsKind.
unsigned SelLocsKind : 2;
// Result type of this method.
QualType MethodDeclType;
@ -147,9 +155,10 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
// Type source information for the result type.
TypeSourceInfo *ResultTInfo;
/// ParamInfo - List of pointers to VarDecls for the formal parameters of this
/// Method.
ObjCList<ParmVarDecl> ParamInfo;
/// \brief Array of ParmVarDecls for the formal parameters of this method
/// and optionally followed by selector locations.
void *ParamsAndSelLocs;
unsigned NumParams;
/// List of attributes for this method declaration.
SourceLocation EndLoc; // the location of the ';' or '}'.
@ -165,6 +174,43 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
/// constructed by createImplicitParams.
ImplicitParamDecl *CmdDecl;
SelectorLocationsKind getSelLocsKind() const {
return (SelectorLocationsKind)SelLocsKind;
}
bool hasStandardSelLocs() const {
return getSelLocsKind() != SelLoc_NonStandard;
}
/// \brief Get a pointer to the stored selector identifiers locations array.
/// No locations will be stored if HasStandardSelLocs is true.
SourceLocation *getStoredSelLocs() {
return reinterpret_cast<SourceLocation*>(getParams() + NumParams);
}
const SourceLocation *getStoredSelLocs() const {
return reinterpret_cast<const SourceLocation*>(getParams() + NumParams);
}
/// \brief Get a pointer to the stored selector identifiers locations array.
/// No locations will be stored if HasStandardSelLocs is true.
ParmVarDecl **getParams() {
return reinterpret_cast<ParmVarDecl **>(ParamsAndSelLocs);
}
const ParmVarDecl *const *getParams() const {
return reinterpret_cast<const ParmVarDecl *const *>(ParamsAndSelLocs);
}
/// \brief Get the number of stored selector identifiers locations.
/// No locations will be stored if HasStandardSelLocs is true.
unsigned getNumStoredSelLocs() const {
if (hasStandardSelLocs())
return 0;
return getNumSelectorLocs();
}
void setParamsAndSelLocs(ASTContext &C,
ArrayRef<ParmVarDecl*> Params,
ArrayRef<SourceLocation> SelLocs);
ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
Selector SelInfo, QualType T,
TypeSourceInfo *ResultTInfo,
@ -172,19 +218,23 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
bool isInstance = true,
bool isVariadic = false,
bool isSynthesized = false,
bool isImplicitlyDeclared = false,
bool isDefined = false,
ImplementationControl impControl = None,
bool HasRelatedResultType = false,
unsigned numSelectorArgs = 0)
bool HasRelatedResultType = false)
: NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
DeclContext(ObjCMethod), Family(InvalidObjCMethodFamily),
IsInstance(isInstance), IsVariadic(isVariadic),
IsSynthesized(isSynthesized),
IsDefined(isDefined),
IsDefined(isDefined), IsRedeclaration(0), HasRedeclaration(0),
DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None),
RelatedResultType(HasRelatedResultType), NumSelectorArgs(numSelectorArgs),
RelatedResultType(HasRelatedResultType),
SelLocsKind(SelLoc_StandardNoSpace),
MethodDeclType(T), ResultTInfo(ResultTInfo),
EndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) {}
ParamsAndSelLocs(0), NumParams(0),
EndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) {
setImplicit(isImplicitlyDeclared);
}
/// \brief A definition will return its interface declaration.
/// An interface declaration will return its definition.
@ -194,17 +244,18 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
public:
static ObjCMethodDecl *Create(ASTContext &C,
SourceLocation beginLoc,
SourceLocation endLoc, Selector SelInfo,
SourceLocation endLoc,
Selector SelInfo,
QualType T,
TypeSourceInfo *ResultTInfo,
DeclContext *contextDecl,
bool isInstance = true,
bool isVariadic = false,
bool isSynthesized = false,
bool isImplicitlyDeclared = false,
bool isDefined = false,
ImplementationControl impControl = None,
bool HasRelatedResultType = false,
unsigned numSelectorArgs = 0);
bool HasRelatedResultType = false);
virtual ObjCMethodDecl *getCanonicalDecl();
const ObjCMethodDecl *getCanonicalDecl() const {
@ -222,11 +273,10 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
/// \brief Note whether this method has a related result type.
void SetRelatedResultType(bool RRT = true) { RelatedResultType = RRT; }
unsigned getNumSelectorArgs() const { return NumSelectorArgs; }
void setNumSelectorArgs(unsigned numSelectorArgs) {
NumSelectorArgs = numSelectorArgs;
}
/// \brief True if this is a method redeclaration in the same interface.
bool isRedeclaration() const { return IsRedeclaration; }
void setAsRedeclaration(const ObjCMethodDecl *PrevMethod);
// Location information, modeled after the Stmt API.
SourceLocation getLocStart() const { return getLocation(); }
@ -236,6 +286,29 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
return SourceRange(getLocation(), EndLoc);
}
SourceLocation getSelectorStartLoc() const { return getSelectorLoc(0); }
SourceLocation getSelectorLoc(unsigned Index) const {
assert(Index < getNumSelectorLocs() && "Index out of range!");
if (hasStandardSelLocs())
return getStandardSelectorLoc(Index, getSelector(),
getSelLocsKind() == SelLoc_StandardWithSpace,
llvm::makeArrayRef(const_cast<ParmVarDecl**>(getParams()),
NumParams),
EndLoc);
return getStoredSelLocs()[Index];
}
void getSelectorLocs(SmallVectorImpl<SourceLocation> &SelLocs) const;
unsigned getNumSelectorLocs() const {
if (isImplicit())
return 0;
Selector Sel = getSelector();
if (Sel.isUnarySelector())
return 1;
return Sel.getNumArgs();
}
ObjCInterfaceDecl *getClassInterface();
const ObjCInterfaceDecl *getClassInterface() const {
return const_cast<ObjCMethodDecl*>(this)->getClassInterface();
@ -256,25 +329,31 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
void setResultTypeSourceInfo(TypeSourceInfo *TInfo) { ResultTInfo = TInfo; }
// Iterator access to formal parameters.
unsigned param_size() const { return ParamInfo.size(); }
typedef ObjCList<ParmVarDecl>::iterator param_iterator;
param_iterator param_begin() const { return ParamInfo.begin(); }
param_iterator param_end() const { return ParamInfo.end(); }
unsigned param_size() const { return NumParams; }
typedef const ParmVarDecl *const *param_const_iterator;
typedef ParmVarDecl *const *param_iterator;
param_const_iterator param_begin() const { return getParams(); }
param_const_iterator param_end() const { return getParams() + NumParams; }
param_iterator param_begin() { return getParams(); }
param_iterator param_end() { return getParams() + NumParams; }
// This method returns and of the parameters which are part of the selector
// name mangling requirements.
param_iterator sel_param_end() const {
return ParamInfo.begin() + NumSelectorArgs;
param_const_iterator sel_param_end() const {
return param_begin() + getSelector().getNumArgs();
}
void setMethodParams(ASTContext &C, ParmVarDecl *const *List, unsigned Num,
unsigned numSelectorArgs) {
ParamInfo.set(List, Num, C);
NumSelectorArgs = numSelectorArgs;
}
/// \brief Sets the method's parameters and selector source locations.
/// If the method is implicit (not coming from source) \arg SelLocs is
/// ignored.
void setMethodParams(ASTContext &C,
ArrayRef<ParmVarDecl*> Params,
ArrayRef<SourceLocation> SelLocs =
ArrayRef<SourceLocation>());
// Iterator access to parameter types.
typedef std::const_mem_fun_t<QualType, ParmVarDecl> deref_fun;
typedef llvm::mapped_iterator<param_iterator, deref_fun> arg_type_iterator;
typedef llvm::mapped_iterator<param_const_iterator, deref_fun>
arg_type_iterator;
arg_type_iterator arg_type_begin() const {
return llvm::map_iterator(param_begin(), deref_fun(&ParmVarDecl::getType));
@ -337,6 +416,9 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
static ObjCMethodDecl *castFromDeclContext(const DeclContext *DC) {
return static_cast<ObjCMethodDecl *>(const_cast<DeclContext*>(DC));
}
friend class ASTDeclReader;
friend class ASTDeclWriter;
};
/// ObjCContainerDecl - Represents a container for method declarations.
@ -344,14 +426,17 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
/// ObjCProtocolDecl, and ObjCImplDecl.
///
class ObjCContainerDecl : public NamedDecl, public DeclContext {
SourceLocation AtStart;
// These two locations in the range mark the end of the method container.
// The first points to the '@' token, and the second to the 'end' token.
SourceRange AtEnd;
public:
ObjCContainerDecl(Kind DK, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id)
: NamedDecl(DK, DC, L, Id), DeclContext(DK) {}
ObjCContainerDecl(Kind DK, DeclContext *DC,
IdentifierInfo *Id, SourceLocation nameLoc,
SourceLocation atStartLoc)
: NamedDecl(DK, DC, nameLoc, Id), DeclContext(DK), AtStart(atStartLoc) {}
// Iterator access to properties.
typedef specific_decl_iterator<ObjCPropertyDecl> prop_iterator;
@ -403,6 +488,9 @@ class ObjCContainerDecl : public NamedDecl, public DeclContext {
ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const;
SourceLocation getAtStartLoc() const { return AtStart; }
void setAtStartLoc(SourceLocation Loc) { AtStart = Loc; }
// Marks the end of the container.
SourceRange getAtEndRange() const {
return AtEnd;
@ -412,7 +500,7 @@ class ObjCContainerDecl : public NamedDecl, public DeclContext {
}
virtual SourceRange getSourceRange() const {
return SourceRange(getLocation(), getAtEndRange().getEnd());
return SourceRange(AtStart, getAtEndRange().getEnd());
}
// Implement isa/cast/dyncast/etc.
@ -485,7 +573,6 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
/// completed by the external AST source when required.
mutable bool ExternallyCompleted : 1;
SourceLocation ClassLoc; // location of the class identifier.
SourceLocation SuperClassLoc; // location of the super class identifier.
SourceLocation EndLoc; // marks the '>', '}', or identifier.
@ -576,7 +663,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
ivar_iterator ivar_begin() const { return ivar_iterator(decls_begin()); }
ivar_iterator ivar_begin() const { return ivar_iterator(decls_begin()); }
ivar_iterator ivar_end() const { return ivar_iterator(decls_end()); }
unsigned ivar_size() const {
@ -585,7 +672,12 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
bool ivar_empty() const { return ivar_begin() == ivar_end(); }
ObjCIvarDecl *all_declared_ivar_begin();
ObjCIvarDecl *all_declared_ivar_begin();
const ObjCIvarDecl *all_declared_ivar_begin() const {
// Even though this modifies IvarList, it's conceptually const:
// the ivar chain is essentially a cached property of ObjCInterfaceDecl.
return const_cast<ObjCInterfaceDecl *>(this)->all_declared_ivar_begin();
}
void setIvarList(ObjCIvarDecl *ivar) { IvarList = ivar; }
/// setProtocolList - Set the list of protocols that this interface
@ -675,12 +767,10 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
ObjCMethodDecl *lookupPrivateMethod(const Selector &Sel, bool Instance=true);
// Location information, modeled after the Stmt API.
SourceLocation getLocStart() const { return getLocation(); } // '@'interface
SourceLocation getLocStart() const { return getAtStartLoc(); } // '@'interface
SourceLocation getLocEnd() const { return EndLoc; }
void setLocEnd(SourceLocation LE) { EndLoc = LE; }
void setClassLoc(SourceLocation Loc) { ClassLoc = Loc; }
SourceLocation getClassLoc() const { return ClassLoc; }
void setSuperClassLoc(SourceLocation Loc) { SuperClassLoc = Loc; }
SourceLocation getSuperClassLoc() const { return SuperClassLoc; }
@ -754,6 +844,7 @@ class ObjCIvarDecl : public FieldDecl {
const ObjCInterfaceDecl *getContainingInterface() const;
ObjCIvarDecl *getNextIvar() { return NextIvar; }
const ObjCIvarDecl *getNextIvar() const { return NextIvar; }
void setNextIvar(ObjCIvarDecl *ivar) { NextIvar = ivar; }
void setAccessControl(AccessControl ac) { DeclAccess = ac; }
@ -837,14 +928,17 @@ class ObjCProtocolDecl : public ObjCContainerDecl {
SourceLocation EndLoc; // marks the '>' or identifier.
ObjCProtocolDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id)
: ObjCContainerDecl(ObjCProtocol, DC, L, Id),
ObjCProtocolDecl(DeclContext *DC, IdentifierInfo *Id,
SourceLocation nameLoc, SourceLocation atStartLoc)
: ObjCContainerDecl(ObjCProtocol, DC, Id, nameLoc, atStartLoc),
isForwardProtoDecl(true) {
}
public:
static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id);
IdentifierInfo *Id,
SourceLocation nameLoc,
SourceLocation atStartLoc);
const ObjCProtocolList &getReferencedProtocols() const {
return ReferencedProtocols;
@ -884,7 +978,7 @@ class ObjCProtocolDecl : public ObjCContainerDecl {
void setForwardDecl(bool val) { isForwardProtoDecl = val; }
// Location information, modeled after the Stmt API.
SourceLocation getLocStart() const { return getLocation(); } // '@'protocol
SourceLocation getLocStart() const { return getAtStartLoc(); } // '@'protocol
SourceLocation getLocEnd() const { return EndLoc; }
void setLocEnd(SourceLocation LE) { EndLoc = LE; }
@ -908,29 +1002,23 @@ class ObjCClassDecl : public Decl {
ObjCInterfaceDecl *getInterface() const { return ID; }
};
private:
ObjCClassRef *ForwardDecls;
unsigned NumDecls;
ObjCClassRef *ForwardDecl;
ObjCClassDecl(DeclContext *DC, SourceLocation L,
ObjCInterfaceDecl *const *Elts, const SourceLocation *Locs,
unsigned nElts, ASTContext &C);
ObjCInterfaceDecl *const Elt, const SourceLocation Loc,
ASTContext &C);
public:
static ObjCClassDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
ObjCInterfaceDecl *const *Elts = 0,
const SourceLocation *Locs = 0,
unsigned nElts = 0);
ObjCInterfaceDecl *const Elt = 0,
const SourceLocation Locs = SourceLocation());
ObjCInterfaceDecl *getForwardInterfaceDecl() { return ForwardDecl->getInterface(); }
ObjCClassRef *getForwardDecl() { return ForwardDecl; }
void setClass(ASTContext &C, ObjCInterfaceDecl*const Cls,
const SourceLocation Locs);
virtual SourceRange getSourceRange() const;
typedef const ObjCClassRef* iterator;
iterator begin() const { return ForwardDecls; }
iterator end() const { return ForwardDecls + NumDecls; }
unsigned size() const { return NumDecls; }
/// setClassList - Set the list of forward classes.
void setClassList(ASTContext &C, ObjCInterfaceDecl*const*List,
const SourceLocation *Locs, unsigned Num);
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const ObjCClassDecl *D) { return true; }
static bool classofKind(Kind K) { return K == ObjCClass; }
@ -1013,19 +1101,16 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
/// true of class extension has at least one bitfield ivar.
bool HasSynthBitfield : 1;
/// \brief The location of the '@' in '@interface'
SourceLocation AtLoc;
/// \brief The location of the category name in this declaration.
SourceLocation CategoryNameLoc;
ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc,
SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc,
IdentifierInfo *Id)
: ObjCContainerDecl(ObjCCategory, DC, ClassNameLoc, Id),
ClassInterface(0), NextClassCategory(0), HasSynthBitfield(false),
AtLoc(AtLoc), CategoryNameLoc(CategoryNameLoc) {
IdentifierInfo *Id, ObjCInterfaceDecl *IDecl)
: ObjCContainerDecl(ObjCCategory, DC, Id, ClassNameLoc, AtLoc),
ClassInterface(IDecl), NextClassCategory(0), HasSynthBitfield(false),
CategoryNameLoc(CategoryNameLoc) {
}
public:
@ -1033,11 +1118,12 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
SourceLocation AtLoc,
SourceLocation ClassNameLoc,
SourceLocation CategoryNameLoc,
IdentifierInfo *Id);
IdentifierInfo *Id,
ObjCInterfaceDecl *IDecl);
static ObjCCategoryDecl *Create(ASTContext &C, EmptyShell Empty);
ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
void setClassInterface(ObjCInterfaceDecl *IDecl) { ClassInterface = IDecl; }
ObjCCategoryImplDecl *getImplementation() const;
void setImplementation(ObjCCategoryImplDecl *ImplD);
@ -1066,14 +1152,6 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
}
ObjCCategoryDecl *getNextClassCategory() const { return NextClassCategory; }
void setNextClassCategory(ObjCCategoryDecl *Cat) {
NextClassCategory = Cat;
}
void insertNextClassCategory() {
NextClassCategory = ClassInterface->getCategoryList();
ClassInterface->setCategoryList(this);
ClassInterface->setChangedSinceDeserialization(true);
}
bool IsClassExtension() const { return getIdentifier() == 0; }
const ObjCCategoryDecl *getNextClassExtension() const;
@ -1094,20 +1172,16 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
bool ivar_empty() const {
return ivar_begin() == ivar_end();
}
SourceLocation getAtLoc() const { return AtLoc; }
void setAtLoc(SourceLocation At) { AtLoc = At; }
SourceLocation getCategoryNameLoc() const { return CategoryNameLoc; }
void setCategoryNameLoc(SourceLocation Loc) { CategoryNameLoc = Loc; }
virtual SourceRange getSourceRange() const {
return SourceRange(AtLoc, getAtEndRange().getEnd());
}
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const ObjCCategoryDecl *D) { return true; }
static bool classofKind(Kind K) { return K == ObjCCategory; }
friend class ASTDeclReader;
friend class ASTDeclWriter;
};
class ObjCImplDecl : public ObjCContainerDecl {
@ -1115,10 +1189,12 @@ class ObjCImplDecl : public ObjCContainerDecl {
ObjCInterfaceDecl *ClassInterface;
protected:
ObjCImplDecl(Kind DK, DeclContext *DC, SourceLocation L,
ObjCInterfaceDecl *classInterface)
: ObjCContainerDecl(DK, DC, L,
classInterface? classInterface->getIdentifier() : 0),
ObjCImplDecl(Kind DK, DeclContext *DC,
ObjCInterfaceDecl *classInterface,
SourceLocation nameLoc, SourceLocation atStartLoc)
: ObjCContainerDecl(DK, DC,
classInterface? classInterface->getIdentifier() : 0,
nameLoc, atStartLoc),
ClassInterface(classInterface) {}
public:
@ -1175,13 +1251,17 @@ class ObjCCategoryImplDecl : public ObjCImplDecl {
// Category name
IdentifierInfo *Id;
ObjCCategoryImplDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
ObjCInterfaceDecl *classInterface)
: ObjCImplDecl(ObjCCategoryImpl, DC, L, classInterface), Id(Id) {}
ObjCCategoryImplDecl(DeclContext *DC, IdentifierInfo *Id,
ObjCInterfaceDecl *classInterface,
SourceLocation nameLoc, SourceLocation atStartLoc)
: ObjCImplDecl(ObjCCategoryImpl, DC, classInterface, nameLoc, atStartLoc),
Id(Id) {}
public:
static ObjCCategoryImplDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
ObjCInterfaceDecl *classInterface);
IdentifierInfo *Id,
ObjCInterfaceDecl *classInterface,
SourceLocation nameLoc,
SourceLocation atStartLoc);
/// getIdentifier - Get the identifier that names the category
/// interface associated with this implementation.
@ -1203,7 +1283,7 @@ class ObjCCategoryImplDecl : public ObjCImplDecl {
//
// FIXME: This is a bad API, we are overriding the NamedDecl::getName, to mean
// something different.
llvm::StringRef getName() const {
StringRef getName() const {
return Id ? Id->getNameStart() : "";
}
@ -1228,7 +1308,7 @@ class ObjCCategoryImplDecl : public ObjCImplDecl {
static bool classofKind(Kind K) { return K == ObjCCategoryImpl;}
};
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
raw_ostream &operator<<(raw_ostream &OS,
const ObjCCategoryImplDecl *CID);
/// ObjCImplementationDecl - Represents a class definition - this is where
@ -1259,17 +1339,19 @@ class ObjCImplementationDecl : public ObjCImplDecl {
/// true of class extension has at least one bitfield ivar.
bool HasSynthBitfield : 1;
ObjCImplementationDecl(DeclContext *DC, SourceLocation L,
ObjCImplementationDecl(DeclContext *DC,
ObjCInterfaceDecl *classInterface,
ObjCInterfaceDecl *superDecl)
: ObjCImplDecl(ObjCImplementation, DC, L, classInterface),
ObjCInterfaceDecl *superDecl,
SourceLocation nameLoc, SourceLocation atStartLoc)
: ObjCImplDecl(ObjCImplementation, DC, classInterface, nameLoc, atStartLoc),
SuperClass(superDecl), IvarInitializers(0), NumIvarInitializers(0),
HasCXXStructors(false), HasSynthBitfield(false) {}
public:
static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
ObjCInterfaceDecl *classInterface,
ObjCInterfaceDecl *superDecl);
ObjCInterfaceDecl *superDecl,
SourceLocation nameLoc,
SourceLocation atStartLoc);
/// init_iterator - Iterates through the ivar initializer list.
typedef CXXCtorInitializer **init_iterator;
@ -1320,7 +1402,7 @@ class ObjCImplementationDecl : public ObjCImplDecl {
//
// FIXME: This is a bad API, we are overriding the NamedDecl::getName, to mean
// something different.
llvm::StringRef getName() const {
StringRef getName() const {
assert(getIdentifier() && "Name is not a simple identifier");
return getIdentifier()->getName();
}
@ -1368,7 +1450,7 @@ class ObjCImplementationDecl : public ObjCImplDecl {
friend class ASTDeclWriter;
};
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
raw_ostream &operator<<(raw_ostream &OS,
const ObjCImplementationDecl *ID);
/// ObjCCompatibleAliasDecl - Represents alias of a class. This alias is
@ -1423,7 +1505,7 @@ class ObjCPropertyDecl : public NamedDecl {
NumPropertyAttrsBits = 12
};
enum SetterKind { Assign, Retain, Copy };
enum SetterKind { Assign, Retain, Copy, Weak };
enum PropertyControl { None, Required, Optional };
private:
SourceLocation AtLoc; // location of @property
@ -1495,14 +1577,29 @@ class ObjCPropertyDecl : public NamedDecl {
return (PropertyAttributes & OBJC_PR_readonly);
}
/// isAtomic - Return true if the property is atomic.
bool isAtomic() const {
return (PropertyAttributes & OBJC_PR_atomic);
}
/// isRetaining - Return true if the property retains its value.
bool isRetaining() const {
return (PropertyAttributes &
(OBJC_PR_retain | OBJC_PR_strong | OBJC_PR_copy));
}
/// getSetterKind - Return the method used for doing assignment in
/// the property setter. This is only valid if the property has been
/// defined to have a setter.
SetterKind getSetterKind() const {
if (PropertyAttributes & (OBJC_PR_retain|OBJC_PR_strong))
if (PropertyAttributes & OBJC_PR_strong)
return getType()->isBlockPointerType() ? Copy : Retain;
if (PropertyAttributes & OBJC_PR_retain)
return Retain;
if (PropertyAttributes & OBJC_PR_copy)
return Copy;
if (PropertyAttributes & OBJC_PR_weak)
return Weak;
return Assign;
}

View File

@ -264,7 +264,7 @@ class FunctionTemplateSpecializationInfo : public llvm::FoldingSetNode {
FunctionTemplateDecl *Template,
TemplateSpecializationKind TSK,
const TemplateArgumentList *TemplateArgs,
const TemplateArgumentListInfo *TemplateArgsAsWritten,
const ASTTemplateArgumentListInfo *TemplateArgsAsWritten,
SourceLocation POI)
: Function(FD),
Template(Template, TSK - 1),
@ -278,12 +278,7 @@ class FunctionTemplateSpecializationInfo : public llvm::FoldingSetNode {
TemplateSpecializationKind TSK,
const TemplateArgumentList *TemplateArgs,
const TemplateArgumentListInfo *TemplateArgsAsWritten,
SourceLocation POI) {
return new (C) FunctionTemplateSpecializationInfo(FD, Template, TSK,
TemplateArgs,
TemplateArgsAsWritten,
POI);
}
SourceLocation POI);
/// \brief The function template specialization that this structure
/// describes.
@ -300,7 +295,7 @@ class FunctionTemplateSpecializationInfo : public llvm::FoldingSetNode {
const TemplateArgumentList *TemplateArguments;
/// \brief The template arguments as written in the sources, if provided.
const TemplateArgumentListInfo *TemplateArgumentsAsWritten;
const ASTTemplateArgumentListInfo *TemplateArgumentsAsWritten;
/// \brief The point at which this function template specialization was
/// first instantiated.
@ -913,7 +908,7 @@ class TemplateParmPosition {
// FIXME: This should probably never be called, but it's here as
TemplateParmPosition()
: Depth(0), Position(0)
{ /* assert(0 && "Cannot create positionless template parameter"); */ }
{ /* llvm_unreachable("Cannot create positionless template parameter"); */ }
TemplateParmPosition(unsigned D, unsigned P)
: Depth(D), Position(P)
@ -1864,7 +1859,7 @@ class ClassTemplateDecl : public RedeclarableTemplateDecl,
/// \brief Retrieve the partial specializations as an ordered list.
void getPartialSpecializations(
llvm::SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS);
SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS);
/// \brief Find a class template partial specialization with the given
/// type T.
@ -2097,6 +2092,58 @@ class TypeAliasTemplateDecl : public RedeclarableTemplateDecl,
friend class ASTDeclWriter;
};
/// Declaration of a function specialization at template class scope.
/// This is a non standard extension needed to support MSVC.
/// For example:
/// template <class T>
/// class A {
/// template <class U> void foo(U a) { }
/// template<> void foo(int a) { }
/// }
///
/// "template<> foo(int a)" will be saved in Specialization as a normal
/// CXXMethodDecl. Then during an instantiation of class A, it will be
/// transformed into an actual function specialization.
class ClassScopeFunctionSpecializationDecl : public Decl {
private:
ClassScopeFunctionSpecializationDecl(DeclContext *DC, SourceLocation Loc,
CXXMethodDecl *FD)
: Decl(Decl::ClassScopeFunctionSpecialization, DC, Loc),
Specialization(FD) {}
ClassScopeFunctionSpecializationDecl(EmptyShell Empty)
: Decl(Decl::ClassScopeFunctionSpecialization, Empty) {}
CXXMethodDecl *Specialization;
public:
CXXMethodDecl *getSpecialization() const { return Specialization; }
static ClassScopeFunctionSpecializationDecl *Create(ASTContext &C,
DeclContext *DC,
SourceLocation Loc,
CXXMethodDecl *FD) {
return new (C) ClassScopeFunctionSpecializationDecl(DC , Loc, FD);
}
static ClassScopeFunctionSpecializationDecl *Create(ASTContext &Context,
EmptyShell Empty) {
return new (Context)ClassScopeFunctionSpecializationDecl(0,
SourceLocation(), 0);
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) {
return K == Decl::ClassScopeFunctionSpecialization;
}
static bool classof(const ClassScopeFunctionSpecializationDecl *D) {
return true;
}
friend class ASTDeclReader;
friend class ASTDeclWriter;
};
/// Implementation of inline functions that require the template declarations
inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD)
: Function(FTD) { }

View File

@ -30,7 +30,7 @@ class DeclVisitor {
public:
RetTy Visit(Decl *D) {
switch (D->getKind()) {
default: assert(false && "Decl that isn't part of DeclNodes.inc!");
default: llvm_unreachable("Decl that isn't part of DeclNodes.inc!");
#define DECL(DERIVED, BASE) \
case Decl::DERIVED: DISPATCH(DERIVED##Decl, DERIVED##Decl);
#define ABSTRACT_DECL(DECL)

View File

@ -203,7 +203,7 @@ class DeclarationName {
std::string getAsString() const;
/// printName - Print the human-readable name to a stream.
void printName(llvm::raw_ostream &OS) const;
void printName(raw_ostream &OS) const;
/// getAsIdentifierInfo - Retrieve the IdentifierInfo * stored in
/// this declaration name, or NULL if this declaration name isn't a
@ -503,7 +503,7 @@ struct DeclarationNameInfo {
std::string getAsString() const;
/// printName - Print the human-readable name to a stream.
void printName(llvm::raw_ostream &OS) const;
void printName(raw_ostream &OS) const;
/// getBeginLoc - Retrieve the location of the first token.
SourceLocation getBeginLoc() const { return NameLoc; }
@ -520,7 +520,7 @@ struct DeclarationNameInfo {
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
DeclarationName N) {
DB.AddTaggedVal(N.getAsOpaqueInteger(),
Diagnostic::ak_declarationname);
DiagnosticsEngine::ak_declarationname);
return DB;
}
@ -529,11 +529,11 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
DeclarationName N) {
PD.AddTaggedVal(N.getAsOpaqueInteger(),
Diagnostic::ak_declarationname);
DiagnosticsEngine::ak_declarationname);
return PD;
}
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
inline raw_ostream &operator<<(raw_ostream &OS,
DeclarationNameInfo DNInfo) {
DNInfo.printName(OS);
return OS;

View File

@ -20,6 +20,7 @@
#include "clang/AST/DeclAccessPair.h"
#include "clang/AST/OperationKinds.h"
#include "clang/AST/ASTVector.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/UsuallyTinyPtrVector.h"
#include "clang/Basic/TypeTraits.h"
#include "llvm/ADT/APSInt.h"
@ -41,12 +42,10 @@ namespace clang {
class CXXOperatorCallExpr;
class CXXMemberCallExpr;
class ObjCPropertyRefExpr;
class TemplateArgumentLoc;
class TemplateArgumentListInfo;
class OpaqueValueExpr;
/// \brief A simple array of base specifiers.
typedef llvm::SmallVector<CXXBaseSpecifier*, 4> CXXCastPath;
typedef SmallVector<CXXBaseSpecifier*, 4> CXXCastPath;
/// Expr - This represents one expression. Note that Expr's are subclasses of
/// Stmt. This allows an expression to be transparently used any place a Stmt
@ -454,9 +453,14 @@ class Expr : public Stmt {
/// EvaluateAsBooleanCondition - Return true if this is a constant
/// which we we can fold and convert to a boolean condition using
/// any crazy technique that we want to.
/// any crazy technique that we want to, even if the expression has
/// side-effects.
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const;
/// EvaluateAsInt - Return true if this is a constant which we can fold and
/// convert to an integer using any crazy technique that we want to.
bool EvaluateAsInt(llvm::APSInt &Result, const ASTContext &Ctx) const;
/// isEvaluatable - Call Evaluate to see if this expression can be constant
/// folded, but discard the result.
bool isEvaluatable(const ASTContext &Ctx) const;
@ -467,9 +471,9 @@ class Expr : public Stmt {
/// variable read.
bool HasSideEffects(const ASTContext &Ctx) const;
/// EvaluateAsInt - Call Evaluate and return the folded integer. This
/// EvaluateKnownConstInt - Call Evaluate and return the folded integer. This
/// must be called on an expression that constant folds to an integer.
llvm::APSInt EvaluateAsInt(const ASTContext &Ctx) const;
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const;
/// EvaluateAsLValue - Evaluate an expression to see if it's a lvalue
/// with link time known address.
@ -688,39 +692,6 @@ class OpaqueValueExpr : public Expr {
static bool classof(const OpaqueValueExpr *) { return true; }
};
/// \brief Represents an explicit template argument list in C++, e.g.,
/// the "<int>" in "sort<int>".
struct ExplicitTemplateArgumentList {
/// \brief The source location of the left angle bracket ('<');
SourceLocation LAngleLoc;
/// \brief The source location of the right angle bracket ('>');
SourceLocation RAngleLoc;
/// \brief The number of template arguments in TemplateArgs.
/// The actual template arguments (if any) are stored after the
/// ExplicitTemplateArgumentList structure.
unsigned NumTemplateArgs;
/// \brief Retrieve the template arguments
TemplateArgumentLoc *getTemplateArgs() {
return reinterpret_cast<TemplateArgumentLoc *> (this + 1);
}
/// \brief Retrieve the template arguments
const TemplateArgumentLoc *getTemplateArgs() const {
return reinterpret_cast<const TemplateArgumentLoc *> (this + 1);
}
void initializeFrom(const TemplateArgumentListInfo &List);
void initializeFrom(const TemplateArgumentListInfo &List,
bool &Dependent, bool &InstantiationDependent,
bool &ContainsUnexpandedParameterPack);
void copyInto(TemplateArgumentListInfo &List) const;
static std::size_t sizeFor(unsigned NumTemplateArgs);
static std::size_t sizeFor(const TemplateArgumentListInfo &List);
};
/// \brief A reference to a declared variable, function, enum, etc.
/// [C99 6.5.1p2]
///
@ -804,6 +775,7 @@ class DeclRefExpr : public Expr {
DeclRefExprBits.HasQualifier = 0;
DeclRefExprBits.HasExplicitTemplateArgs = 0;
DeclRefExprBits.HasFoundDecl = 0;
DeclRefExprBits.HadMultipleCandidates = 0;
computeDependence();
}
@ -887,29 +859,29 @@ class DeclRefExpr : public Expr {
/// \brief Retrieve the explicit template argument list that followed the
/// member template name.
ExplicitTemplateArgumentList &getExplicitTemplateArgs() {
ASTTemplateArgumentListInfo &getExplicitTemplateArgs() {
assert(hasExplicitTemplateArgs());
if (hasFoundDecl())
return *reinterpret_cast<ExplicitTemplateArgumentList *>(
return *reinterpret_cast<ASTTemplateArgumentListInfo *>(
&getInternalFoundDecl() + 1);
if (hasQualifier())
return *reinterpret_cast<ExplicitTemplateArgumentList *>(
return *reinterpret_cast<ASTTemplateArgumentListInfo *>(
&getInternalQualifierLoc() + 1);
return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
return *reinterpret_cast<ASTTemplateArgumentListInfo *>(this + 1);
}
/// \brief Retrieve the explicit template argument list that followed the
/// member template name.
const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const {
return const_cast<DeclRefExpr *>(this)->getExplicitTemplateArgs();
}
/// \brief Retrieves the optional explicit template arguments.
/// This points to the same data as getExplicitTemplateArgs(), but
/// returns null if there are no explicit template arguments.
const ExplicitTemplateArgumentList *getExplicitTemplateArgsOpt() const {
const ASTTemplateArgumentListInfo *getExplicitTemplateArgsOpt() const {
if (!hasExplicitTemplateArgs()) return 0;
return &getExplicitTemplateArgs();
}
@ -957,6 +929,18 @@ class DeclRefExpr : public Expr {
return getExplicitTemplateArgs().RAngleLoc;
}
/// \brief Returns true if this expression refers to a function that
/// was resolved from an overloaded set having size greater than 1.
bool hadMultipleCandidates() const {
return DeclRefExprBits.HadMultipleCandidates;
}
/// \brief Sets the flag telling whether this expression refers to
/// a function that was resolved from an overloaded set having size
/// greater than 1.
void setHadMultipleCandidates(bool V = true) {
DeclRefExprBits.HadMultipleCandidates = V;
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == DeclRefExprClass;
}
@ -1112,29 +1096,39 @@ class IntegerLiteral : public Expr {
};
class CharacterLiteral : public Expr {
public:
enum CharacterKind {
Ascii,
Wide,
UTF16,
UTF32
};
private:
unsigned Value;
SourceLocation Loc;
bool IsWide;
unsigned Kind : 2;
public:
// type should be IntTy
CharacterLiteral(unsigned value, bool iswide, QualType type, SourceLocation l)
CharacterLiteral(unsigned value, CharacterKind kind, QualType type,
SourceLocation l)
: Expr(CharacterLiteralClass, type, VK_RValue, OK_Ordinary, false, false,
false, false),
Value(value), Loc(l), IsWide(iswide) {
Value(value), Loc(l), Kind(kind) {
}
/// \brief Construct an empty character literal.
CharacterLiteral(EmptyShell Empty) : Expr(CharacterLiteralClass, Empty) { }
SourceLocation getLocation() const { return Loc; }
bool isWide() const { return IsWide; }
CharacterKind getKind() const { return static_cast<CharacterKind>(Kind); }
SourceRange getSourceRange() const { return SourceRange(Loc); }
unsigned getValue() const { return Value; }
void setLocation(SourceLocation Location) { Loc = Location; }
void setWide(bool W) { IsWide = W; }
void setKind(CharacterKind kind) { Kind = kind; }
void setValue(unsigned Val) { Value = Val; }
static bool classof(const Stmt *T) {
@ -1243,13 +1237,23 @@ class ImaginaryLiteral : public Expr {
/// In this case, getByteLength() will return 6, but the string literal will
/// have type "char[2]".
class StringLiteral : public Expr {
public:
enum StringKind {
Ascii,
Wide,
UTF8,
UTF16,
UTF32
};
private:
friend class ASTStmtReader;
const char *StrData;
unsigned ByteLength;
bool IsWide;
bool IsPascal;
unsigned NumConcatenated;
unsigned Kind : 3;
bool IsPascal : 1;
SourceLocation TokLocs[1];
StringLiteral(QualType Ty) :
@ -1259,33 +1263,39 @@ class StringLiteral : public Expr {
public:
/// This is the "fully general" constructor that allows representation of
/// strings formed from multiple concatenated tokens.
static StringLiteral *Create(ASTContext &C, llvm::StringRef Str, bool Wide,
static StringLiteral *Create(ASTContext &C, StringRef Str, StringKind Kind,
bool Pascal, QualType Ty,
const SourceLocation *Loc, unsigned NumStrs);
/// Simple constructor for string literals made from one token.
static StringLiteral *Create(ASTContext &C, llvm::StringRef Str, bool Wide,
bool Pascal, QualType Ty, SourceLocation Loc) {
return Create(C, Str, Wide, Pascal, Ty, &Loc, 1);
static StringLiteral *Create(ASTContext &C, StringRef Str, StringKind Kind,
bool Pascal, QualType Ty,
SourceLocation Loc) {
return Create(C, Str, Kind, Pascal, Ty, &Loc, 1);
}
/// \brief Construct an empty string literal.
static StringLiteral *CreateEmpty(ASTContext &C, unsigned NumStrs);
llvm::StringRef getString() const {
return llvm::StringRef(StrData, ByteLength);
StringRef getString() const {
return StringRef(StrData, ByteLength);
}
unsigned getByteLength() const { return ByteLength; }
/// \brief Sets the string data to the given string data.
void setString(ASTContext &C, llvm::StringRef Str);
void setString(ASTContext &C, StringRef Str);
bool isWide() const { return IsWide; }
StringKind getKind() const { return static_cast<StringKind>(Kind); }
bool isAscii() const { return Kind == Ascii; }
bool isWide() const { return Kind == Wide; }
bool isUTF8() const { return Kind == UTF8; }
bool isUTF16() const { return Kind == UTF16; }
bool isUTF32() const { return Kind == UTF32; }
bool isPascal() const { return IsPascal; }
bool containsNonAsciiOrNull() const {
llvm::StringRef Str = getString();
StringRef Str = getString();
for (unsigned i = 0, e = Str.size(); i != e; ++i)
if (!isascii(Str[i]) || !Str[i])
return true;
@ -2029,6 +2039,10 @@ class MemberExpr : public Expr {
/// the MemberNameQualifier structure.
bool HasExplicitTemplateArgumentList : 1;
/// \brief True if this member expression refers to a method that
/// was resolved from an overloaded set having size greater than 1.
bool HadMultipleCandidates : 1;
/// \brief Retrieve the qualifier that preceded the member name, if any.
MemberNameQualifier *getMemberQualifier() {
assert(HasQualifierOrFoundDecl);
@ -2051,7 +2065,8 @@ class MemberExpr : public Expr {
base->containsUnexpandedParameterPack()),
Base(base), MemberDecl(memberdecl), MemberLoc(NameInfo.getLoc()),
MemberDNLoc(NameInfo.getInfo()), IsArrow(isarrow),
HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) {
HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false),
HadMultipleCandidates(false) {
assert(memberdecl->getDeclName() == NameInfo.getName());
}
@ -2068,7 +2083,8 @@ class MemberExpr : public Expr {
base->containsUnexpandedParameterPack()),
Base(base), MemberDecl(memberdecl), MemberLoc(l), MemberDNLoc(),
IsArrow(isarrow),
HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) {}
HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false),
HadMultipleCandidates(false) {}
static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow,
NestedNameSpecifierLoc QualifierLoc,
@ -2136,26 +2152,26 @@ class MemberExpr : public Expr {
/// \brief Retrieve the explicit template argument list that
/// follow the member template name. This must only be called on an
/// expression with explicit template arguments.
ExplicitTemplateArgumentList &getExplicitTemplateArgs() {
ASTTemplateArgumentListInfo &getExplicitTemplateArgs() {
assert(HasExplicitTemplateArgumentList);
if (!HasQualifierOrFoundDecl)
return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
return *reinterpret_cast<ASTTemplateArgumentListInfo *>(this + 1);
return *reinterpret_cast<ExplicitTemplateArgumentList *>(
return *reinterpret_cast<ASTTemplateArgumentListInfo *>(
getMemberQualifier() + 1);
}
/// \brief Retrieve the explicit template argument list that
/// followed the member template name. This must only be called on
/// an expression with explicit template arguments.
const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const {
return const_cast<MemberExpr *>(this)->getExplicitTemplateArgs();
}
/// \brief Retrieves the optional explicit template arguments.
/// This points to the same data as getExplicitTemplateArgs(), but
/// returns null if there are no explicit template arguments.
const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() const {
const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const {
if (!hasExplicitTemplateArgs()) return 0;
return &getExplicitTemplateArgs();
}
@ -2218,7 +2234,19 @@ class MemberExpr : public Expr {
bool isImplicitAccess() const {
return getBase() && getBase()->isImplicitCXXThis();
}
/// \brief Returns true if this member expression refers to a method that
/// was resolved from an overloaded set having size greater than 1.
bool hadMultipleCandidates() const {
return HadMultipleCandidates;
}
/// \brief Sets the flag telling whether this expression refers to
/// a method that was resolved from an overloaded set having size
/// greater than 1.
void setHadMultipleCandidates(bool V = true) {
HadMultipleCandidates = V;
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == MemberExprClass;
}
@ -2301,68 +2329,7 @@ class CastExpr : public Expr {
private:
Stmt *Op;
void CheckCastConsistency() const {
#ifndef NDEBUG
switch (getCastKind()) {
case CK_DerivedToBase:
case CK_UncheckedDerivedToBase:
case CK_DerivedToBaseMemberPointer:
case CK_BaseToDerived:
case CK_BaseToDerivedMemberPointer:
assert(!path_empty() && "Cast kind should have a base path!");
break;
// These should not have an inheritance path.
case CK_BitCast:
case CK_Dynamic:
case CK_ToUnion:
case CK_ArrayToPointerDecay:
case CK_FunctionToPointerDecay:
case CK_NullToMemberPointer:
case CK_NullToPointer:
case CK_ConstructorConversion:
case CK_IntegralToPointer:
case CK_PointerToIntegral:
case CK_ToVoid:
case CK_VectorSplat:
case CK_IntegralCast:
case CK_IntegralToFloating:
case CK_FloatingToIntegral:
case CK_FloatingCast:
case CK_AnyPointerToObjCPointerCast:
case CK_AnyPointerToBlockPointerCast:
case CK_ObjCObjectLValueCast:
case CK_FloatingRealToComplex:
case CK_FloatingComplexToReal:
case CK_FloatingComplexCast:
case CK_FloatingComplexToIntegralComplex:
case CK_IntegralRealToComplex:
case CK_IntegralComplexToReal:
case CK_IntegralComplexCast:
case CK_IntegralComplexToFloatingComplex:
case CK_ObjCProduceObject:
case CK_ObjCConsumeObject:
case CK_ObjCReclaimReturnedObject:
assert(!getType()->isBooleanType() && "unheralded conversion to bool");
// fallthrough to check for null base path
case CK_Dependent:
case CK_LValueToRValue:
case CK_GetObjCProperty:
case CK_NoOp:
case CK_PointerToBoolean:
case CK_IntegralToBoolean:
case CK_FloatingToBoolean:
case CK_MemberPointerToBoolean:
case CK_FloatingComplexToBoolean:
case CK_IntegralComplexToBoolean:
case CK_LValueBitCast: // -> bool&
case CK_UserDefinedConversion: // operator bool()
assert(path_empty() && "Cast kind should not have a base path!");
break;
}
#endif
}
void CheckCastConsistency() const;
const CXXBaseSpecifier * const *path_buffer() const {
return const_cast<CastExpr*>(this)->path_buffer();
@ -2393,7 +2360,9 @@ class CastExpr : public Expr {
assert(kind != CK_Invalid && "creating cast with invalid cast kind");
CastExprBits.Kind = kind;
setBasePathSize(BasePathSize);
#ifndef NDEBUG
CheckCastConsistency();
#endif
}
/// \brief Construct an empty cast.
@ -2746,7 +2715,7 @@ class BinaryOperator : public Expr {
/// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
/// track of the type the operation is performed in. Due to the semantics of
/// these operators, the operands are promoted, the aritmetic performed, an
/// these operators, the operands are promoted, the arithmetic performed, an
/// implicit conversion back to the result type done, then the assignment takes
/// place. This captures the intermediate type which the computation is done
/// in.
@ -3134,7 +3103,7 @@ class ShuffleVectorExpr : public Expr {
unsigned getShuffleMaskIdx(ASTContext &Ctx, unsigned N) {
assert((N < NumExprs - 2) && "Shuffle idx out of range!");
return getExpr(N+2)->EvaluateAsInt(Ctx).getZExtValue();
return getExpr(N+2)->EvaluateKnownConstInt(Ctx).getZExtValue();
}
// Iterators
@ -4045,7 +4014,7 @@ class ExtVectorElementExpr : public Expr {
/// getEncodedElementAccess - Encode the elements accessed into an llvm
/// aggregate Constant of ConstantInt(s).
void getEncodedElementAccess(llvm::SmallVectorImpl<unsigned> &Elts) const;
void getEncodedElementAccess(SmallVectorImpl<unsigned> &Elts) const;
SourceRange getSourceRange() const {
return SourceRange(getBase()->getLocStart(), AccessorLoc);
@ -4193,6 +4162,101 @@ class AsTypeExpr : public Expr { // Should this be an ExplicitCastExpr?
// Iterators
child_range children() { return child_range(&SrcExpr, &SrcExpr+1); }
};
/// AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*,
/// __atomic_load, __atomic_store, and __atomic_compare_exchange_*, for the
/// similarly-named C++0x instructions. All of these instructions take one
/// primary pointer and at least one memory order.
class AtomicExpr : public Expr {
public:
enum AtomicOp { Load, Store, CmpXchgStrong, CmpXchgWeak, Xchg,
Add, Sub, And, Or, Xor };
private:
enum { PTR, ORDER, VAL1, ORDER_FAIL, VAL2, END_EXPR };
Stmt* SubExprs[END_EXPR];
unsigned NumSubExprs;
SourceLocation BuiltinLoc, RParenLoc;
AtomicOp Op;
public:
AtomicExpr(SourceLocation BLoc, Expr **args, unsigned nexpr, QualType t,
AtomicOp op, SourceLocation RP);
/// \brief Build an empty AtomicExpr.
explicit AtomicExpr(EmptyShell Empty) : Expr(AtomicExprClass, Empty) { }
Expr *getPtr() const {
return cast<Expr>(SubExprs[PTR]);
}
void setPtr(Expr *E) {
SubExprs[PTR] = E;
}
Expr *getOrder() const {
return cast<Expr>(SubExprs[ORDER]);
}
void setOrder(Expr *E) {
SubExprs[ORDER] = E;
}
Expr *getVal1() const {
assert(NumSubExprs >= 3);
return cast<Expr>(SubExprs[VAL1]);
}
void setVal1(Expr *E) {
assert(NumSubExprs >= 3);
SubExprs[VAL1] = E;
}
Expr *getOrderFail() const {
assert(NumSubExprs == 5);
return cast<Expr>(SubExprs[ORDER_FAIL]);
}
void setOrderFail(Expr *E) {
assert(NumSubExprs == 5);
SubExprs[ORDER_FAIL] = E;
}
Expr *getVal2() const {
assert(NumSubExprs == 5);
return cast<Expr>(SubExprs[VAL2]);
}
void setVal2(Expr *E) {
assert(NumSubExprs == 5);
SubExprs[VAL2] = E;
}
AtomicOp getOp() const { return Op; }
void setOp(AtomicOp op) { Op = op; }
unsigned getNumSubExprs() { return NumSubExprs; }
void setNumSubExprs(unsigned num) { NumSubExprs = num; }
Expr **getSubExprs() { return reinterpret_cast<Expr **>(SubExprs); }
bool isVolatile() const {
return getPtr()->getType()->getPointeeType().isVolatileQualified();
}
bool isCmpXChg() const {
return getOp() == AtomicExpr::CmpXchgStrong ||
getOp() == AtomicExpr::CmpXchgWeak;
}
SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
SourceRange getSourceRange() const {
return SourceRange(BuiltinLoc, RParenLoc);
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == AtomicExprClass;
}
static bool classof(const AtomicExpr *) { return true; }
// Iterators
child_range children() {
return child_range(SubExprs, SubExprs+NumSubExprs);
}
};
} // end namespace clang
#endif

View File

@ -807,37 +807,41 @@ class CXXConstructExpr : public Expr {
SourceLocation Loc;
SourceRange ParenRange;
unsigned NumArgs : 16;
bool Elidable : 1;
bool HadMultipleCandidates : 1;
bool ZeroInitialization : 1;
unsigned ConstructKind : 2;
Stmt **Args;
unsigned NumArgs;
protected:
CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
SourceLocation Loc,
CXXConstructorDecl *d, bool elidable,
Expr **args, unsigned numargs,
bool HadMultipleCandidates,
bool ZeroInitialization = false,
ConstructionKind ConstructKind = CK_Complete,
SourceRange ParenRange = SourceRange());
/// \brief Construct an empty C++ construction expression.
CXXConstructExpr(StmtClass SC, EmptyShell Empty)
: Expr(SC, Empty), Constructor(0), Elidable(0), ZeroInitialization(0),
ConstructKind(0), Args(0), NumArgs(0) { }
: Expr(SC, Empty), Constructor(0), NumArgs(0), Elidable(0),
HadMultipleCandidates(false), ZeroInitialization(0),
ConstructKind(0), Args(0) { }
public:
/// \brief Construct an empty C++ construction expression.
explicit CXXConstructExpr(EmptyShell Empty)
: Expr(CXXConstructExprClass, Empty), Constructor(0),
Elidable(0), ZeroInitialization(0),
ConstructKind(0), Args(0), NumArgs(0) { }
NumArgs(0), Elidable(0), HadMultipleCandidates(false),
ZeroInitialization(0), ConstructKind(0), Args(0) { }
static CXXConstructExpr *Create(ASTContext &C, QualType T,
SourceLocation Loc,
CXXConstructorDecl *D, bool Elidable,
Expr **Args, unsigned NumArgs,
bool HadMultipleCandidates,
bool ZeroInitialization = false,
ConstructionKind ConstructKind = CK_Complete,
SourceRange ParenRange = SourceRange());
@ -852,7 +856,12 @@ class CXXConstructExpr : public Expr {
/// \brief Whether this construction is elidable.
bool isElidable() const { return Elidable; }
void setElidable(bool E) { Elidable = E; }
/// \brief Whether the referred constructor was resolved from
/// an overloaded set having size greater than 1.
bool hadMultipleCandidates() const { return HadMultipleCandidates; }
void setHadMultipleCandidates(bool V) { HadMultipleCandidates = V; }
/// \brief Whether this construction first requires
/// zero-initialization before the initializer is called.
bool requiresZeroInitialization() const { return ZeroInitialization; }
@ -980,6 +989,7 @@ class CXXTemporaryObjectExpr : public CXXConstructExpr {
TypeSourceInfo *Type,
Expr **Args,unsigned NumArgs,
SourceRange parenRange,
bool HadMultipleCandidates,
bool ZeroInitialization = false);
explicit CXXTemporaryObjectExpr(EmptyShell Empty)
: CXXConstructExpr(CXXTemporaryObjectExprClass, Empty), Type() { }
@ -1049,8 +1059,11 @@ class CXXNewExpr : public Expr {
// If this is an array allocation, does the usual deallocation
// function for the allocated type want to know the allocated size?
bool UsualArrayDeleteWantsSize : 1;
// Whether the referred constructor (if any) was resolved from an
// overload set having size greater than 1.
bool HadMultipleCandidates : 1;
// The number of placement new arguments.
unsigned NumPlacementArgs : 14;
unsigned NumPlacementArgs : 13;
// The number of constructor arguments. This may be 1 even for non-class
// types; use the pseudo copy constructor.
unsigned NumConstructorArgs : 14;
@ -1086,6 +1099,7 @@ class CXXNewExpr : public Expr {
SourceRange TypeIdParens,
Expr *arraySize, CXXConstructorDecl *constructor, bool initializer,
Expr **constructorArgs, unsigned numConsArgs,
bool HadMultipleCandidates,
FunctionDecl *operatorDelete, bool usualArrayDeleteWantsSize,
QualType ty, TypeSourceInfo *AllocatedTypeInfo,
SourceLocation startLoc, SourceLocation endLoc,
@ -1174,6 +1188,11 @@ class CXXNewExpr : public Expr {
return cast<Expr>(SubExprs[Array + NumPlacementArgs + i]);
}
/// \brief Whether the new expression refers a constructor that was
/// resolved from an overloaded set having size greater than 1.
bool hadMultipleCandidates() const { return HadMultipleCandidates; }
void setHadMultipleCandidates(bool V) { HadMultipleCandidates = V; }
typedef ExprIterator arg_iterator;
typedef ConstExprIterator const_arg_iterator;
@ -1842,16 +1861,16 @@ class OverloadExpr : public Expr {
/// template argument list, e.g. f<int>.
bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; }
ExplicitTemplateArgumentList &getExplicitTemplateArgs(); // defined far below
ASTTemplateArgumentListInfo &getExplicitTemplateArgs(); // defined far below
const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const {
return const_cast<OverloadExpr*>(this)->getExplicitTemplateArgs();
}
/// \brief Retrieves the optional explicit template arguments.
/// This points to the same data as getExplicitTemplateArgs(), but
/// returns null if there are no explicit template arguments.
const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() {
if (!hasExplicitTemplateArgs()) return 0;
return &getExplicitTemplateArgs();
}
@ -1969,21 +1988,21 @@ class UnresolvedLookupExpr : public OverloadExpr {
// nodes, users are *forbidden* from calling these methods on objects
// without explicit template arguments.
ExplicitTemplateArgumentList &getExplicitTemplateArgs() {
ASTTemplateArgumentListInfo &getExplicitTemplateArgs() {
assert(hasExplicitTemplateArgs());
return *reinterpret_cast<ExplicitTemplateArgumentList*>(this + 1);
return *reinterpret_cast<ASTTemplateArgumentListInfo*>(this + 1);
}
/// Gets a reference to the explicit template argument list.
const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const {
assert(hasExplicitTemplateArgs());
return *reinterpret_cast<const ExplicitTemplateArgumentList*>(this + 1);
return *reinterpret_cast<const ASTTemplateArgumentListInfo*>(this + 1);
}
/// \brief Retrieves the optional explicit template arguments.
/// This points to the same data as getExplicitTemplateArgs(), but
/// returns null if there are no explicit template arguments.
const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() {
if (!hasExplicitTemplateArgs()) return 0;
return &getExplicitTemplateArgs();
}
@ -2094,21 +2113,21 @@ class DependentScopeDeclRefExpr : public Expr {
// nodes, users are *forbidden* from calling these methods on objects
// without explicit template arguments.
ExplicitTemplateArgumentList &getExplicitTemplateArgs() {
ASTTemplateArgumentListInfo &getExplicitTemplateArgs() {
assert(hasExplicitTemplateArgs());
return *reinterpret_cast<ExplicitTemplateArgumentList*>(this + 1);
return *reinterpret_cast<ASTTemplateArgumentListInfo*>(this + 1);
}
/// Gets a reference to the explicit template argument list.
const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const {
assert(hasExplicitTemplateArgs());
return *reinterpret_cast<const ExplicitTemplateArgumentList*>(this + 1);
return *reinterpret_cast<const ASTTemplateArgumentListInfo*>(this + 1);
}
/// \brief Retrieves the optional explicit template arguments.
/// This points to the same data as getExplicitTemplateArgs(), but
/// returns null if there are no explicit template arguments.
const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() {
if (!hasExplicitTemplateArgs()) return 0;
return &getExplicitTemplateArgs();
}
@ -2470,14 +2489,14 @@ class CXXDependentScopeMemberExpr : public Expr {
/// \brief Retrieve the explicit template argument list that followed the
/// member template name, if any.
ExplicitTemplateArgumentList &getExplicitTemplateArgs() {
ASTTemplateArgumentListInfo &getExplicitTemplateArgs() {
assert(HasExplicitTemplateArgs);
return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
return *reinterpret_cast<ASTTemplateArgumentListInfo *>(this + 1);
}
/// \brief Retrieve the explicit template argument list that followed the
/// member template name, if any.
const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const {
return const_cast<CXXDependentScopeMemberExpr *>(this)
->getExplicitTemplateArgs();
}
@ -2485,7 +2504,7 @@ class CXXDependentScopeMemberExpr : public Expr {
/// \brief Retrieves the optional explicit template arguments.
/// This points to the same data as getExplicitTemplateArgs(), but
/// returns null if there are no explicit template arguments.
const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() {
if (!hasExplicitTemplateArgs()) return 0;
return &getExplicitTemplateArgs();
}
@ -2663,22 +2682,22 @@ class UnresolvedMemberExpr : public OverloadExpr {
/// \brief Retrieve the explicit template argument list that followed the
/// member template name.
ExplicitTemplateArgumentList &getExplicitTemplateArgs() {
ASTTemplateArgumentListInfo &getExplicitTemplateArgs() {
assert(hasExplicitTemplateArgs());
return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
return *reinterpret_cast<ASTTemplateArgumentListInfo *>(this + 1);
}
/// \brief Retrieve the explicit template argument list that followed the
/// member template name, if any.
const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const {
assert(hasExplicitTemplateArgs());
return *reinterpret_cast<const ExplicitTemplateArgumentList *>(this + 1);
return *reinterpret_cast<const ASTTemplateArgumentListInfo *>(this + 1);
}
/// \brief Retrieves the optional explicit template arguments.
/// This points to the same data as getExplicitTemplateArgs(), but
/// returns null if there are no explicit template arguments.
const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() {
if (!hasExplicitTemplateArgs()) return 0;
return &getExplicitTemplateArgs();
}
@ -2856,7 +2875,7 @@ class PackExpansionExpr : public Expr {
}
};
inline ExplicitTemplateArgumentList &OverloadExpr::getExplicitTemplateArgs() {
inline ASTTemplateArgumentListInfo &OverloadExpr::getExplicitTemplateArgs() {
if (isa<UnresolvedLookupExpr>(this))
return cast<UnresolvedLookupExpr>(this)->getExplicitTemplateArgs();
else

View File

@ -16,6 +16,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/SelectorLocationsKind.h"
#include "clang/Basic/IdentifierTable.h"
namespace clang {
@ -359,12 +360,12 @@ class ObjCPropertyRefExpr : public Expr {
QualType ArgType;
if (isImplicitProperty()) {
const ObjCMethodDecl *Setter = getImplicitPropertySetter();
ObjCMethodDecl::param_iterator P = Setter->param_begin();
ObjCMethodDecl::param_const_iterator P = Setter->param_begin();
ArgType = (*P)->getType();
} else {
if (ObjCPropertyDecl *PDecl = getExplicitProperty())
if (const ObjCMethodDecl *Setter = PDecl->getSetterMethodDecl()) {
ObjCMethodDecl::param_iterator P = Setter->param_begin();
ObjCMethodDecl::param_const_iterator P = Setter->param_begin();
ArgType = (*P)->getType();
}
if (ArgType.isNull())
@ -444,9 +445,21 @@ class ObjCPropertyRefExpr : public Expr {
/// class, and can be distinguished via \c getReceiverKind(). Example:
///
class ObjCMessageExpr : public Expr {
/// \brief Stores either the selector that this message is sending
/// to (when \c HasMethod is zero) or an \c ObjCMethodDecl pointer
/// referring to the method that we type-checked against.
uintptr_t SelectorOrMethod;
enum { NumArgsBitWidth = 16 };
/// \brief The number of arguments in the message send, not
/// including the receiver.
unsigned NumArgs : 16;
unsigned NumArgs : NumArgsBitWidth;
void setNumArgs(unsigned Num) {
assert((Num >> NumArgsBitWidth) == 0 && "Num of args is out of range!");
NumArgs = Num;
}
/// \brief The kind of message send this is, which is one of the
/// ReceiverKind values.
@ -464,26 +477,24 @@ class ObjCMessageExpr : public Expr {
/// \brief Whether this message send is a "delegate init call",
/// i.e. a call of an init method on self from within an init method.
unsigned IsDelegateInitCall : 1;
/// \brief Whether the locations of the selector identifiers are in a
/// "standard" position, a enum SelectorLocationsKind.
unsigned SelLocsKind : 2;
/// \brief When the message expression is a send to 'super', this is
/// the location of the 'super' keyword.
SourceLocation SuperLoc;
/// \brief Stores either the selector that this message is sending
/// to (when \c HasMethod is zero) or an \c ObjCMethodDecl pointer
/// referring to the method that we type-checked against.
uintptr_t SelectorOrMethod;
/// \brief Location of the selector.
SourceLocation SelectorLoc;
/// \brief The source locations of the open and close square
/// brackets ('[' and ']', respectively).
SourceLocation LBracLoc, RBracLoc;
ObjCMessageExpr(EmptyShell Empty, unsigned NumArgs)
: Expr(ObjCMessageExprClass, Empty), NumArgs(NumArgs), Kind(0),
HasMethod(0), IsDelegateInitCall(0), SelectorOrMethod(0) { }
: Expr(ObjCMessageExprClass, Empty), SelectorOrMethod(0), Kind(0),
HasMethod(0), IsDelegateInitCall(0) {
setNumArgs(NumArgs);
}
ObjCMessageExpr(QualType T, ExprValueKind VK,
SourceLocation LBracLoc,
@ -491,27 +502,34 @@ class ObjCMessageExpr : public Expr {
bool IsInstanceSuper,
QualType SuperType,
Selector Sel,
SourceLocation SelLoc,
ArrayRef<SourceLocation> SelLocs,
SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method,
Expr **Args, unsigned NumArgs,
ArrayRef<Expr *> Args,
SourceLocation RBracLoc);
ObjCMessageExpr(QualType T, ExprValueKind VK,
SourceLocation LBracLoc,
TypeSourceInfo *Receiver,
Selector Sel,
SourceLocation SelLoc,
ArrayRef<SourceLocation> SelLocs,
SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method,
Expr **Args, unsigned NumArgs,
ArrayRef<Expr *> Args,
SourceLocation RBracLoc);
ObjCMessageExpr(QualType T, ExprValueKind VK,
SourceLocation LBracLoc,
Expr *Receiver,
Selector Sel,
SourceLocation SelLoc,
ArrayRef<SourceLocation> SelLocs,
SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method,
Expr **Args, unsigned NumArgs,
ArrayRef<Expr *> Args,
SourceLocation RBracLoc);
void initArgsAndSelLocs(ArrayRef<Expr *> Args,
ArrayRef<SourceLocation> SelLocs,
SelectorLocationsKind SelLocsK);
/// \brief Retrieve the pointer value of the message receiver.
void *getReceiverPointer() const {
return *const_cast<void **>(
@ -523,6 +541,40 @@ class ObjCMessageExpr : public Expr {
*reinterpret_cast<void **>(this + 1) = Value;
}
SelectorLocationsKind getSelLocsKind() const {
return (SelectorLocationsKind)SelLocsKind;
}
bool hasStandardSelLocs() const {
return getSelLocsKind() != SelLoc_NonStandard;
}
/// \brief Get a pointer to the stored selector identifiers locations array.
/// No locations will be stored if HasStandardSelLocs is true.
SourceLocation *getStoredSelLocs() {
return reinterpret_cast<SourceLocation*>(getArgs() + getNumArgs());
}
const SourceLocation *getStoredSelLocs() const {
return reinterpret_cast<const SourceLocation*>(getArgs() + getNumArgs());
}
/// \brief Get the number of stored selector identifiers locations.
/// No locations will be stored if HasStandardSelLocs is true.
unsigned getNumStoredSelLocs() const {
if (hasStandardSelLocs())
return 0;
return getNumSelectorLocs();
}
static ObjCMessageExpr *alloc(ASTContext &C,
ArrayRef<Expr *> Args,
SourceLocation RBraceLoc,
ArrayRef<SourceLocation> SelLocs,
Selector Sel,
SelectorLocationsKind &SelLocsK);
static ObjCMessageExpr *alloc(ASTContext &C,
unsigned NumArgs,
unsigned NumStoredSelLocs);
public:
/// \brief The kind of receiver this message is sending to.
enum ReceiverKind {
@ -570,9 +622,9 @@ class ObjCMessageExpr : public Expr {
bool IsInstanceSuper,
QualType SuperType,
Selector Sel,
SourceLocation SelLoc,
ArrayRef<SourceLocation> SelLocs,
ObjCMethodDecl *Method,
Expr **Args, unsigned NumArgs,
ArrayRef<Expr *> Args,
SourceLocation RBracLoc);
/// \brief Create a class message send.
@ -605,9 +657,9 @@ class ObjCMessageExpr : public Expr {
SourceLocation LBracLoc,
TypeSourceInfo *Receiver,
Selector Sel,
SourceLocation SelLoc,
ArrayRef<SourceLocation> SelLocs,
ObjCMethodDecl *Method,
Expr **Args, unsigned NumArgs,
ArrayRef<Expr *> Args,
SourceLocation RBracLoc);
/// \brief Create an instance message send.
@ -640,9 +692,9 @@ class ObjCMessageExpr : public Expr {
SourceLocation LBracLoc,
Expr *Receiver,
Selector Sel,
SourceLocation SelLoc,
ArrayRef<SourceLocation> SeLocs,
ObjCMethodDecl *Method,
Expr **Args, unsigned NumArgs,
ArrayRef<Expr *> Args,
SourceLocation RBracLoc);
/// \brief Create an empty Objective-C message expression, to be
@ -652,7 +704,9 @@ class ObjCMessageExpr : public Expr {
///
/// \param NumArgs The number of message arguments, not including
/// the receiver.
static ObjCMessageExpr *CreateEmpty(ASTContext &Context, unsigned NumArgs);
static ObjCMessageExpr *CreateEmpty(ASTContext &Context,
unsigned NumArgs,
unsigned NumStoredSelLocs);
/// \brief Determine the kind of receiver that this message is being
/// sent to.
@ -822,7 +876,27 @@ class ObjCMessageExpr : public Expr {
SourceLocation getLeftLoc() const { return LBracLoc; }
SourceLocation getRightLoc() const { return RBracLoc; }
SourceLocation getSelectorLoc() const { return SelectorLoc; }
SourceLocation getSelectorStartLoc() const { return getSelectorLoc(0); }
SourceLocation getSelectorLoc(unsigned Index) const {
assert(Index < getNumSelectorLocs() && "Index out of range!");
if (hasStandardSelLocs())
return getStandardSelectorLoc(Index, getSelector(),
getSelLocsKind() == SelLoc_StandardWithSpace,
llvm::makeArrayRef(const_cast<Expr**>(getArgs()),
getNumArgs()),
RBracLoc);
return getStoredSelLocs()[Index];
}
void getSelectorLocs(SmallVectorImpl<SourceLocation> &SelLocs) const;
unsigned getNumSelectorLocs() const {
Selector Sel = getSelector();
if (Sel.isUnarySelector())
return 1;
return Sel.getNumArgs();
}
void setSourceRange(SourceRange R) {
LBracLoc = R.getBegin();
@ -989,10 +1063,10 @@ class ObjCBridgedCastExpr : public ExplicitCastExpr {
public:
ObjCBridgedCastExpr(SourceLocation LParenLoc, ObjCBridgeCastKind Kind,
SourceLocation BridgeKeywordLoc, TypeSourceInfo *TSInfo,
Expr *Operand)
CastKind CK, SourceLocation BridgeKeywordLoc,
TypeSourceInfo *TSInfo, Expr *Operand)
: ExplicitCastExpr(ObjCBridgedCastExprClass, TSInfo->getType(), VK_RValue,
CK_BitCast, Operand, 0, TSInfo),
CK, Operand, 0, TSInfo),
LParenLoc(LParenLoc), BridgeKeywordLoc(BridgeKeywordLoc), Kind(Kind) { }
/// \brief Construct an empty Objective-C bridged cast.
@ -1007,7 +1081,7 @@ class ObjCBridgedCastExpr : public ExplicitCastExpr {
}
/// \brief Retrieve the kind of bridge being performed as a string.
llvm::StringRef getBridgeKindName() const;
StringRef getBridgeKindName() const;
/// \brief The location of the bridge keyword.
SourceLocation getBridgeKeywordLoc() const { return BridgeKeywordLoc; }

View File

@ -15,11 +15,6 @@
#define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
#include "clang/AST/DeclBase.h"
#include <cassert>
namespace llvm {
template <class T> class SmallVectorImpl;
}
namespace clang {
@ -129,16 +124,6 @@ class ExternalASTSource {
virtual DeclContextLookupResult
FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name);
/// \brief Deserialize all the visible declarations from external storage.
///
/// Name lookup deserializes visible declarations lazily, thus a DeclContext
/// may not have a complete name lookup table. This function deserializes
/// the rest of visible declarations from the external storage and completes
/// the name lookup table of the DeclContext.
///
/// The default implementation of this method is a no-op.
virtual void MaterializeVisibleDecls(const DeclContext *DC);
/// \brief Finds all declarations lexically contained within the given
/// DeclContext, after applying an optional filter predicate.
///
@ -151,20 +136,20 @@ class ExternalASTSource {
/// The default implementation of this method is a no-op.
virtual ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
bool (*isKindWeWant)(Decl::Kind),
llvm::SmallVectorImpl<Decl*> &Result);
SmallVectorImpl<Decl*> &Result);
/// \brief Finds all declarations lexically contained within the given
/// DeclContext.
///
/// \return true if an error occurred
ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
llvm::SmallVectorImpl<Decl*> &Result) {
SmallVectorImpl<Decl*> &Result) {
return FindExternalLexicalDecls(DC, 0, Result);
}
template <typename DeclTy>
ExternalLoadResult FindExternalLexicalDeclsBy(const DeclContext *DC,
llvm::SmallVectorImpl<Decl*> &Result) {
SmallVectorImpl<Decl*> &Result) {
return FindExternalLexicalDecls(DC, DeclTy::classofKind, Result);
}
@ -231,15 +216,11 @@ class ExternalASTSource {
static DeclContextLookupResult
SetExternalVisibleDeclsForName(const DeclContext *DC,
DeclarationName Name,
llvm::SmallVectorImpl<NamedDecl*> &Decls);
ArrayRef<NamedDecl*> Decls);
static DeclContextLookupResult
SetNoExternalVisibleDeclsForName(const DeclContext *DC,
DeclarationName Name);
void MaterializeVisibleDeclsForName(const DeclContext *DC,
DeclarationName Name,
llvm::SmallVectorImpl<NamedDecl*> &Decls);
};
/// \brief A lazy pointer to an AST node (of base type T) that resides
@ -305,6 +286,178 @@ struct LazyOffsetPtr {
}
};
/// \brief Represents a lazily-loaded vector of data.
///
/// The lazily-loaded vector of data contains data that is partially loaded
/// from an external source and partially added by local translation. The
/// items loaded from the external source are loaded lazily, when needed for
/// iteration over the complete vector.
template<typename T, typename Source,
void (Source::*Loader)(SmallVectorImpl<T>&),
unsigned LoadedStorage = 2, unsigned LocalStorage = 4>
class LazyVector {
SmallVector<T, LoadedStorage> Loaded;
SmallVector<T, LocalStorage> Local;
public:
// Iteration over the elements in the vector.
class iterator {
LazyVector *Self;
/// \brief Position within the vector..
///
/// In a complete iteration, the Position field walks the range [-M, N),
/// where negative values are used to indicate elements
/// loaded from the external source while non-negative values are used to
/// indicate elements added via \c push_back().
/// However, to provide iteration in source order (for, e.g., chained
/// precompiled headers), dereferencing the iterator flips the negative
/// values (corresponding to loaded entities), so that position -M
/// corresponds to element 0 in the loaded entities vector, position -M+1
/// corresponds to element 1 in the loaded entities vector, etc. This
/// gives us a reasonably efficient, source-order walk.
int Position;
friend class LazyVector;
public:
typedef T value_type;
typedef value_type& reference;
typedef value_type* pointer;
typedef std::random_access_iterator_tag iterator_category;
typedef int difference_type;
iterator() : Self(0), Position(0) { }
iterator(LazyVector *Self, int Position)
: Self(Self), Position(Position) { }
reference operator*() const {
if (Position < 0)
return Self->Loaded.end()[Position];
return Self->Local[Position];
}
pointer operator->() const {
if (Position < 0)
return &Self->Loaded.end()[Position];
return &Self->Local[Position];
}
reference operator[](difference_type D) {
return *(*this + D);
}
iterator &operator++() {
++Position;
return *this;
}
iterator operator++(int) {
iterator Prev(*this);
++Position;
return Prev;
}
iterator &operator--() {
--Position;
return *this;
}
iterator operator--(int) {
iterator Prev(*this);
--Position;
return Prev;
}
friend bool operator==(const iterator &X, const iterator &Y) {
return X.Position == Y.Position;
}
friend bool operator!=(const iterator &X, const iterator &Y) {
return X.Position != Y.Position;
}
friend bool operator<(const iterator &X, const iterator &Y) {
return X.Position < Y.Position;
}
friend bool operator>(const iterator &X, const iterator &Y) {
return X.Position > Y.Position;
}
friend bool operator<=(const iterator &X, const iterator &Y) {
return X.Position < Y.Position;
}
friend bool operator>=(const iterator &X, const iterator &Y) {
return X.Position > Y.Position;
}
friend iterator& operator+=(iterator &X, difference_type D) {
X.Position += D;
return X;
}
friend iterator& operator-=(iterator &X, difference_type D) {
X.Position -= D;
return X;
}
friend iterator operator+(iterator X, difference_type D) {
X.Position += D;
return X;
}
friend iterator operator+(difference_type D, iterator X) {
X.Position += D;
return X;
}
friend difference_type operator-(const iterator &X, const iterator &Y) {
return X.Position - Y.Position;
}
friend iterator operator-(iterator X, difference_type D) {
X.Position -= D;
return X;
}
};
friend class iterator;
iterator begin(Source *source, bool LocalOnly = false) {
if (LocalOnly)
return iterator(this, 0);
if (source)
(source->*Loader)(Loaded);
return iterator(this, -(int)Loaded.size());
}
iterator end() {
return iterator(this, Local.size());
}
void push_back(const T& LocalValue) {
Local.push_back(LocalValue);
}
void erase(iterator From, iterator To) {
if (From.Position < 0 && To.Position < 0) {
Loaded.erase(Loaded.end() + From.Position, Loaded.end() + To.Position);
return;
}
if (From.Position < 0) {
Loaded.erase(Loaded.end() + From.Position, Loaded.end());
From = begin(0, true);
}
Local.erase(Local.begin() + From.Position, Local.begin() + To.Position);
}
};
/// \brief A lazy pointer to a statement.
typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt>
LazyDeclStmtPtr;

View File

@ -6,24 +6,24 @@ TABLEGEN_INC_FILES_COMMON = 1
include $(CLANG_LEVEL)/Makefile
$(ObjDir)/Attrs.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \
$(ObjDir)/Attrs.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \
$(ObjDir)/.dir
$(Echo) "Building Clang attribute classes with tblgen"
$(Verb) $(TableGen) -gen-clang-attr-classes -o $(call SYSPATH, $@) \
$(Verb) $(ClangTableGen) -gen-clang-attr-classes -o $(call SYSPATH, $@) \
-I $(PROJ_SRC_DIR)/../../ $<
$(ObjDir)/AttrImpl.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \
$(ObjDir)/AttrImpl.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \
$(ObjDir)/.dir
$(Echo) "Building Clang attribute implementations with tblgen"
$(Verb) $(TableGen) -gen-clang-attr-impl -o $(call SYSPATH, $@) \
$(Verb) $(ClangTableGen) -gen-clang-attr-impl -o $(call SYSPATH, $@) \
-I $(PROJ_SRC_DIR)/../../ $<
$(ObjDir)/StmtNodes.inc.tmp : $(TD_SRC_DIR)/StmtNodes.td $(TBLGEN) \
$(ObjDir)/StmtNodes.inc.tmp : $(TD_SRC_DIR)/StmtNodes.td $(CLANG_TBLGEN) \
$(ObjDir)/.dir
$(Echo) "Building Clang statement node tables with tblgen"
$(Verb) $(TableGen) -gen-clang-stmt-nodes -o $(call SYSPATH, $@) $<
$(Verb) $(ClangTableGen) -gen-clang-stmt-nodes -o $(call SYSPATH, $@) $<
$(ObjDir)/DeclNodes.inc.tmp : $(TD_SRC_DIR)/DeclNodes.td $(TBLGEN) \
$(ObjDir)/DeclNodes.inc.tmp : $(TD_SRC_DIR)/DeclNodes.td $(CLANG_TBLGEN) \
$(ObjDir)/.dir
$(Echo) "Building Clang declaration node tables with tblgen"
$(Verb) $(TableGen) -gen-clang-decl-nodes -o $(call SYSPATH, $@) $<
$(Verb) $(ClangTableGen) -gen-clang-decl-nodes -o $(call SYSPATH, $@) $<

View File

@ -39,25 +39,25 @@ namespace clang {
/// external memory ownership.
class MangleBuffer {
public:
void setString(llvm::StringRef Ref) {
void setString(StringRef Ref) {
String = Ref;
}
llvm::SmallVectorImpl<char> &getBuffer() {
SmallVectorImpl<char> &getBuffer() {
return Buffer;
}
llvm::StringRef getString() const {
StringRef getString() const {
if (!String.empty()) return String;
return Buffer.str();
}
operator llvm::StringRef() const {
operator StringRef() const {
return getString();
}
private:
llvm::StringRef String;
StringRef String;
llvm::SmallString<256> Buffer;
};
@ -65,21 +65,21 @@ class MangleBuffer {
/// calls to the C++ name mangler.
class MangleContext {
ASTContext &Context;
Diagnostic &Diags;
DiagnosticsEngine &Diags;
llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds;
llvm::DenseMap<const BlockDecl*, unsigned> LocalBlockIds;
public:
explicit MangleContext(ASTContext &Context,
Diagnostic &Diags)
DiagnosticsEngine &Diags)
: Context(Context), Diags(Diags) { }
virtual ~MangleContext() { }
ASTContext &getASTContext() const { return Context; }
Diagnostic &getDiags() const { return Diags; }
DiagnosticsEngine &getDiags() const { return Diags; }
virtual void startNewFunction() { LocalBlockIds.clear(); }
@ -95,55 +95,55 @@ class MangleContext {
/// @{
virtual bool shouldMangleDeclName(const NamedDecl *D) = 0;
virtual void mangleName(const NamedDecl *D, llvm::raw_ostream &)=0;
virtual void mangleName(const NamedDecl *D, raw_ostream &)=0;
virtual void mangleThunk(const CXXMethodDecl *MD,
const ThunkInfo &Thunk,
llvm::raw_ostream &) = 0;
raw_ostream &) = 0;
virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
const ThisAdjustment &ThisAdjustment,
llvm::raw_ostream &) = 0;
raw_ostream &) = 0;
virtual void mangleReferenceTemporary(const VarDecl *D,
llvm::raw_ostream &) = 0;
raw_ostream &) = 0;
virtual void mangleCXXVTable(const CXXRecordDecl *RD,
llvm::raw_ostream &) = 0;
raw_ostream &) = 0;
virtual void mangleCXXVTT(const CXXRecordDecl *RD,
llvm::raw_ostream &) = 0;
raw_ostream &) = 0;
virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
const CXXRecordDecl *Type,
llvm::raw_ostream &) = 0;
virtual void mangleCXXRTTI(QualType T, llvm::raw_ostream &) = 0;
virtual void mangleCXXRTTIName(QualType T, llvm::raw_ostream &) = 0;
raw_ostream &) = 0;
virtual void mangleCXXRTTI(QualType T, raw_ostream &) = 0;
virtual void mangleCXXRTTIName(QualType T, raw_ostream &) = 0;
virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
llvm::raw_ostream &) = 0;
raw_ostream &) = 0;
virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
llvm::raw_ostream &) = 0;
raw_ostream &) = 0;
void mangleGlobalBlock(const BlockDecl *BD,
llvm::raw_ostream &Out);
raw_ostream &Out);
void mangleCtorBlock(const CXXConstructorDecl *CD, CXXCtorType CT,
const BlockDecl *BD, llvm::raw_ostream &Out);
const BlockDecl *BD, raw_ostream &Out);
void mangleDtorBlock(const CXXDestructorDecl *CD, CXXDtorType DT,
const BlockDecl *BD, llvm::raw_ostream &Out);
const BlockDecl *BD, raw_ostream &Out);
void mangleBlock(const DeclContext *DC, const BlockDecl *BD,
llvm::raw_ostream &Out);
raw_ostream &Out);
// Do the right thing.
void mangleBlock(const BlockDecl *BD, llvm::raw_ostream &Out);
void mangleBlock(const BlockDecl *BD, raw_ostream &Out);
void mangleObjCMethodName(const ObjCMethodDecl *MD,
llvm::raw_ostream &);
raw_ostream &);
// This is pretty lame.
virtual void mangleItaniumGuardVariable(const VarDecl *D,
llvm::raw_ostream &) {
assert(0 && "Target does not support mangling guard variables");
raw_ostream &) {
llvm_unreachable("Target does not support mangling guard variables");
}
/// @}
};
MangleContext *createItaniumMangleContext(ASTContext &Context,
Diagnostic &Diags);
DiagnosticsEngine &Diags);
MangleContext *createMicrosoftMangleContext(ASTContext &Context,
Diagnostic &Diags);
DiagnosticsEngine &Diags);
}

View File

@ -18,10 +18,6 @@
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerIntPair.h"
namespace llvm {
class raw_ostream;
}
namespace clang {
class ASTContext;
@ -196,7 +192,7 @@ class NestedNameSpecifier : public llvm::FoldingSetNode {
/// \brief Print this nested name specifier to the given output
/// stream.
void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const;
void print(raw_ostream &OS, const PrintingPolicy &Policy) const;
void Profile(llvm::FoldingSetNodeID &ID) const {
ID.AddPointer(Prefix.getOpaqueValue());
@ -469,7 +465,7 @@ class NestedNameSpecifierLocBuilder {
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
NestedNameSpecifier *NNS) {
DB.AddTaggedVal(reinterpret_cast<intptr_t>(NNS),
Diagnostic::ak_nestednamespec);
DiagnosticsEngine::ak_nestednamespec);
return DB;
}

View File

@ -31,9 +31,12 @@ enum CastKind {
/// to be reinterpreted as a bit pattern of another type. Generally
/// the operands must have equivalent size and unrelated types.
///
/// The pointer conversion char* -> int* is a bitcast. Many other
/// pointer conversions which are "physically" bitcasts are given
/// special cast kinds.
/// The pointer conversion char* -> int* is a bitcast. A conversion
/// from any pointer type to a C pointer type is a bitcast unless
/// it's actually BaseToDerived or DerivedToBase. A conversion to a
/// block pointer or ObjC pointer type is a bitcast only if the
/// operand has the same type kind; otherwise, it's one of the
/// specialized casts below.
///
/// Vector coercions are bitcasts.
CK_BitCast,
@ -186,12 +189,16 @@ enum CastKind {
/// (float) ld
CK_FloatingCast,
/// CK_AnyPointerToObjCPointerCast - Casting any other pointer kind
/// to an Objective-C pointer.
CK_AnyPointerToObjCPointerCast,
/// CK_CPointerToObjCPointerCast - Casting a C pointer kind to an
/// Objective-C pointer.
CK_CPointerToObjCPointerCast,
/// CK_AnyPointerToBlockPointerCast - Casting any other pointer kind
/// to a block pointer.
/// CK_BlockPointerToObjCPointerCast - Casting a block pointer to an
/// ObjC pointer.
CK_BlockPointerToObjCPointerCast,
/// CK_AnyPointerToBlockPointerCast - Casting any non-block pointer
/// to a block pointer. Block-to-block casts are bitcasts.
CK_AnyPointerToBlockPointerCast,
/// \brief Converting between two Objective-C object types, which
@ -247,20 +254,27 @@ enum CastKind {
/// _Complex unsigned -> _Complex float
CK_IntegralComplexToFloatingComplex,
/// \brief Produces a retainable object pointer so that it may be
/// consumed, e.g. by being passed to a consuming parameter. Calls
/// objc_retain.
CK_ObjCProduceObject,
/// \brief [ARC] Produces a retainable object pointer so that it may
/// be consumed, e.g. by being passed to a consuming parameter.
/// Calls objc_retain.
CK_ARCProduceObject,
/// \brief Consumes a retainable object pointer that has just been
/// produced, e.g. as the return value of a retaining call. Enters
/// a cleanup to call objc_release at some indefinite time.
CK_ObjCConsumeObject,
/// \brief [ARC] Consumes a retainable object pointer that has just
/// been produced, e.g. as the return value of a retaining call.
/// Enters a cleanup to call objc_release at some indefinite time.
CK_ARCConsumeObject,
/// \brief Reclaim a retainable object pointer object that may have
/// been produced and autoreleased as part of a function return
/// \brief [ARC] Reclaim a retainable object pointer object that may
/// have been produced and autoreleased as part of a function return
/// sequence.
CK_ObjCReclaimReturnedObject
CK_ARCReclaimReturnedObject,
/// \brief [ARC] Causes a value of block type to be copied to the
/// heap, if it is not already there. A number of other operations
/// in ARC cause blocks to be copied; this is for cases where that
/// would not otherwise be guaranteed, such as when casting to a
/// non-block pointer type.
CK_ARCExtendBlockObject
};
#define CK_Invalid ((CastKind) -1)

View File

@ -32,6 +32,7 @@ class ParentMap {
Stmt *getParent(Stmt*) const;
Stmt *getParentIgnoreParens(Stmt *) const;
Stmt *getParentIgnoreParenCasts(Stmt *) const;
Stmt *getParentIgnoreParenImpCasts(Stmt *) const;
Stmt *getOuterParenParent(Stmt *) const;
const Stmt *getParent(const Stmt* S) const {

View File

@ -15,10 +15,7 @@
#define LLVM_CLANG_AST_PRETTY_PRINTER_H
#include "clang/Basic/LangOptions.h"
namespace llvm {
class raw_ostream;
}
#include "clang/Basic/LLVM.h"
namespace clang {
@ -29,7 +26,7 @@ class LangOptions;
class PrinterHelper {
public:
virtual ~PrinterHelper();
virtual bool handledStmt(Stmt* E, llvm::raw_ostream& OS) = 0;
virtual bool handledStmt(Stmt* E, raw_ostream& OS) = 0;
};
/// \brief Describes how types, statements, expressions, and
@ -41,13 +38,14 @@ struct PrintingPolicy {
SuppressTagKeyword(false), SuppressTag(false), SuppressScope(false),
SuppressInitializers(false),
Dump(false), ConstantArraySizeAsWritten(false),
AnonymousTagLocations(true), SuppressStrongLifetime(false) { }
AnonymousTagLocations(true), SuppressStrongLifetime(false),
Bool(LO.Bool) { }
/// \brief The number of spaces to use to indent each line.
unsigned Indentation : 8;
/// \brief What language we're printing.
const LangOptions LangOpts;
LangOptions LangOpts;
/// \brief Whether we should suppress printing of the actual specifiers for
/// the given type or declaration.
@ -133,6 +131,10 @@ struct PrintingPolicy {
/// \brief When true, suppress printing of the __strong lifetime qualifier in
/// ARC.
unsigned SuppressStrongLifetime : 1;
/// \brief Whether we can use 'bool' rather than '_Bool', even if the language
/// doesn't actually have 'bool' (because, e.g., it is defined as a macro).
unsigned Bool : 1;
};
} // end namespace clang

View File

@ -63,6 +63,9 @@ class ASTRecordLayout {
/// any empty subobjects.
CharUnits SizeOfLargestEmptySubobject;
/// VBPtrOffset - Virtual base table offset.
CharUnits VBPtrOffset;
/// PrimaryBase - The primary base info for this record.
llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> PrimaryBase;
@ -89,7 +92,8 @@ class ASTRecordLayout {
// Constructor for C++ records.
typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy;
ASTRecordLayout(const ASTContext &Ctx,
CharUnits size, CharUnits alignment, CharUnits datasize,
CharUnits size, CharUnits alignment, CharUnits vbptroffset,
CharUnits datasize,
const uint64_t *fieldoffsets, unsigned fieldcount,
CharUnits nonvirtualsize, CharUnits nonvirtualalign,
CharUnits SizeOfLargestEmptySubobject,
@ -199,6 +203,10 @@ class ASTRecordLayout {
assert(CXXInfo && "Record layout does not have C++ specific info!");
return CXXInfo->SizeOfLargestEmptySubobject;
}
CharUnits getVBPtrOffset() const {
return CXXInfo->VBPtrOffset;
}
};
} // end namespace clang

View File

@ -813,6 +813,10 @@ DEF_TRAVERSE_TYPE(ObjCObjectPointerType, {
TRY_TO(TraverseType(T->getPointeeType()));
})
DEF_TRAVERSE_TYPE(AtomicType, {
TRY_TO(TraverseType(T->getValueType()));
})
#undef DEF_TRAVERSE_TYPE
// ----------------- TypeLoc traversal -----------------
@ -1041,6 +1045,10 @@ DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType, {
TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
})
DEF_TRAVERSE_TYPELOC(AtomicType, {
TRY_TO(TraverseTypeLoc(TL.getValueLoc()));
})
#undef DEF_TRAVERSE_TYPELOC
// ----------------- Decl traversal -----------------
@ -1114,6 +1122,10 @@ DEF_TRAVERSE_DECL(FriendTemplateDecl, {
}
})
DEF_TRAVERSE_DECL(ClassScopeFunctionSpecializationDecl, {
TRY_TO(TraverseDecl(D->getSpecialization()));
})
DEF_TRAVERSE_DECL(LinkageSpecDecl, { })
DEF_TRAVERSE_DECL(ObjCClassDecl, {
@ -1252,7 +1264,7 @@ bool RecursiveASTVisitor<Derived>::TraverseClassInstantiations(
= (U.get<ClassTemplatePartialSpecializationDecl*>() == Pattern);
if (ShouldVisit)
TRY_TO(TraverseClassTemplateSpecializationDecl(SD));
TRY_TO(TraverseDecl(SD));
break;
}
@ -1280,7 +1292,7 @@ DEF_TRAVERSE_DECL(ClassTemplateDecl, {
TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
// By default, we do not traverse the instantiations of
// class templates since they do not apprear in the user code. The
// class templates since they do not appear in the user code. The
// following code optionally traverses them.
if (getDerived().shouldVisitTemplateInstantiations()) {
// If this is the definition of the primary template, visit
@ -1318,7 +1330,7 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations(
case TSK_ExplicitSpecialization:
break;
default:
assert(false && "Unknown specialization kind.");
llvm_unreachable("Unknown specialization kind.");
}
}
@ -1548,10 +1560,10 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
FTSI->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) {
// A specialization might not have explicit template arguments if it has
// a templated return type and concrete arguments.
if (const TemplateArgumentListInfo *TALI =
if (const ASTTemplateArgumentListInfo *TALI =
FTSI->TemplateArgumentsAsWritten) {
TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getArgumentArray(),
TALI->size()));
TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getTemplateArgs(),
TALI->NumTemplateArgs));
}
}
}
@ -1980,6 +1992,7 @@ DEF_TRAVERSE_STMT(SizeOfPackExpr, { })
DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, { })
DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, { })
DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, { })
DEF_TRAVERSE_STMT(AtomicExpr, { })
// These literals (all of them) do not need any action.
DEF_TRAVERSE_STMT(IntegerLiteral, { })

View File

@ -0,0 +1,83 @@
//===--- SelectorLocationsKind.h - Kind of selector locations ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Describes whether the identifier locations for a selector are "standard"
// or not.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_SELECTORLOCATIONSKIND_H
#define LLVM_CLANG_AST_SELECTORLOCATIONSKIND_H
#include "clang/Basic/LLVM.h"
namespace clang {
class Selector;
class SourceLocation;
class Expr;
class ParmVarDecl;
/// \brief Whether all locations of the selector identifiers are in a
/// "standard" position.
enum SelectorLocationsKind {
/// \brief Non-standard.
SelLoc_NonStandard = 0,
/// \brief For nullary selectors, immediately before the end:
/// "[foo release]" / "-(void)release;"
/// Or immediately before the arguments:
/// "[foo first:1 second:2]" / "-(id)first:(int)x second:(int)y;
SelLoc_StandardNoSpace = 1,
/// \brief For nullary selectors, immediately before the end:
/// "[foo release]" / "-(void)release;"
/// Or with a space between the arguments:
/// "[foo first: 1 second: 2]" / "-(id)first: (int)x second: (int)y;
SelLoc_StandardWithSpace = 2
};
/// \brief Returns true if all \arg SelLocs are in a "standard" location.
SelectorLocationsKind hasStandardSelectorLocs(Selector Sel,
ArrayRef<SourceLocation> SelLocs,
ArrayRef<Expr *> Args,
SourceLocation EndLoc);
/// \brief Get the "standard" location of a selector identifier, e.g:
/// For nullary selectors, immediately before ']': "[foo release]"
///
/// \param WithArgSpace if true the standard location is with a space apart
/// before arguments: "[foo first: 1 second: 2]"
/// If false: "[foo first:1 second:2]"
SourceLocation getStandardSelectorLoc(unsigned Index,
Selector Sel,
bool WithArgSpace,
ArrayRef<Expr *> Args,
SourceLocation EndLoc);
/// \brief Returns true if all \arg SelLocs are in a "standard" location.
SelectorLocationsKind hasStandardSelectorLocs(Selector Sel,
ArrayRef<SourceLocation> SelLocs,
ArrayRef<ParmVarDecl *> Args,
SourceLocation EndLoc);
/// \brief Get the "standard" location of a selector identifier, e.g:
/// For nullary selectors, immediately before ']': "[foo release]"
///
/// \param WithArgSpace if true the standard location is with a space apart
/// before arguments: "-(id)first: (int)x second: (int)y;"
/// If false: "-(id)first:(int)x second:(int)y;"
SourceLocation getStandardSelectorLoc(unsigned Index,
Selector Sel,
bool WithArgSpace,
ArrayRef<ParmVarDecl *> Args,
SourceLocation EndLoc);
} // end namespace clang
#endif

View File

@ -14,16 +14,15 @@
#ifndef LLVM_CLANG_AST_STMT_H
#define LLVM_CLANG_AST_STMT_H
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/StmtIterator.h"
#include "clang/AST/DeclGroup.h"
#include "llvm/ADT/SmallVector.h"
#include "clang/AST/ASTContext.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/SmallVector.h"
#include <string>
using llvm::dyn_cast_or_null;
namespace llvm {
class FoldingSetNodeID;
@ -108,11 +107,10 @@ class Stmt {
// Make vanilla 'new' and 'delete' illegal for Stmts.
protected:
void* operator new(size_t bytes) throw() {
assert(0 && "Stmts cannot be allocated with regular 'new'.");
return 0;
llvm_unreachable("Stmts cannot be allocated with regular 'new'.");
}
void operator delete(void* data) throw() {
assert(0 && "Stmts cannot be released with regular 'delete'.");
llvm_unreachable("Stmts cannot be released with regular 'delete'.");
}
class StmtBitfields {
@ -148,6 +146,7 @@ class Stmt {
friend class CXXUnresolvedConstructExpr; // ctor
friend class CXXDependentScopeMemberExpr; // ctor
friend class OverloadExpr; // ctor
friend class AtomicExpr; // ctor
unsigned : NumStmtBits;
unsigned ValueKind : 2;
@ -167,6 +166,7 @@ class Stmt {
unsigned HasQualifier : 1;
unsigned HasExplicitTemplateArgs : 1;
unsigned HasFoundDecl : 1;
unsigned HadMultipleCandidates : 1;
};
class CastExprBitfields {
@ -270,7 +270,7 @@ class Stmt {
/// This is useful in a debugger.
void dump() const;
void dump(SourceManager &SM) const;
void dump(llvm::raw_ostream &OS, SourceManager &SM) const;
void dump(raw_ostream &OS, SourceManager &SM) const;
/// dumpAll - This does a dump of the specified AST fragment and all subtrees.
void dumpAll() const;
@ -279,12 +279,12 @@ class Stmt {
/// dumpPretty/printPretty - These two methods do a "pretty print" of the AST
/// back to its original source language syntax.
void dumpPretty(ASTContext& Context) const;
void printPretty(llvm::raw_ostream &OS, PrinterHelper *Helper,
void printPretty(raw_ostream &OS, PrinterHelper *Helper,
const PrintingPolicy &Policy,
unsigned Indentation = 0) const {
printPretty(OS, *(ASTContext*)0, Helper, Policy, Indentation);
}
void printPretty(llvm::raw_ostream &OS, ASTContext &Context,
void printPretty(raw_ostream &OS, ASTContext &Context,
PrinterHelper *Helper,
const PrintingPolicy &Policy,
unsigned Indentation = 0) const;
@ -297,6 +297,12 @@ class Stmt {
/// statement, such as ExprWithCleanups or ImplicitCastExpr nodes.
Stmt *IgnoreImplicit();
const Stmt *stripLabelLikeStatements() const;
Stmt *stripLabelLikeStatements() {
return const_cast<Stmt*>(
const_cast<const Stmt*>(this)->stripLabelLikeStatements());
}
// Implement isa<T> support.
static bool classof(const Stmt *) { return true; }
@ -407,25 +413,25 @@ class DeclStmt : public Stmt {
class NullStmt : public Stmt {
SourceLocation SemiLoc;
/// \brief If the null statement was preceded by an empty macro this is
/// its instantiation source location, e.g:
/// \brief True if the null statement was preceded by an empty macro, e.g:
/// @code
/// #define CALL(x)
/// CALL(0);
/// @endcode
SourceLocation LeadingEmptyMacro;
bool HasLeadingEmptyMacro;
public:
NullStmt(SourceLocation L, SourceLocation LeadingEmptyMacro =SourceLocation())
: Stmt(NullStmtClass), SemiLoc(L), LeadingEmptyMacro(LeadingEmptyMacro) {}
NullStmt(SourceLocation L, bool hasLeadingEmptyMacro = false)
: Stmt(NullStmtClass), SemiLoc(L),
HasLeadingEmptyMacro(hasLeadingEmptyMacro) {}
/// \brief Build an empty null statement.
explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty) { }
explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty),
HasLeadingEmptyMacro(false) { }
SourceLocation getSemiLoc() const { return SemiLoc; }
void setSemiLoc(SourceLocation L) { SemiLoc = L; }
bool hasLeadingEmptyMacro() const { return LeadingEmptyMacro.isValid(); }
SourceLocation getLeadingEmptyMacroLoc() const { return LeadingEmptyMacro; }
bool hasLeadingEmptyMacro() const { return HasLeadingEmptyMacro; }
SourceRange getSourceRange() const { return SourceRange(SemiLoc); }
@ -525,6 +531,10 @@ class CompoundStmt : public Stmt {
child_range children() {
return child_range(&Body[0], &Body[0]+CompoundStmtBits.NumStmts);
}
const_child_range children() const {
return child_range(&Body[0], &Body[0]+CompoundStmtBits.NumStmts);
}
};
// SwitchCase is the base class for CaseStmt and DefaultStmt,
@ -1308,7 +1318,7 @@ class AsmStmt : public Stmt {
/// true, otherwise return false. This handles canonicalization and
/// translation of strings from GCC syntax to LLVM IR syntax, and handles
//// flattening of named references like %[foo] to Operand AsmStringPiece's.
unsigned AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece> &Pieces,
unsigned AnalyzeAsmString(SmallVectorImpl<AsmStringPiece> &Pieces,
ASTContext &C, unsigned &DiagOffs) const;
@ -1320,17 +1330,17 @@ class AsmStmt : public Stmt {
return Names[i];
}
llvm::StringRef getOutputName(unsigned i) const {
StringRef getOutputName(unsigned i) const {
if (IdentifierInfo *II = getOutputIdentifier(i))
return II->getName();
return llvm::StringRef();
return StringRef();
}
/// getOutputConstraint - Return the constraint string for the specified
/// output operand. All output constraints are known to be non-empty (either
/// '=' or '+').
llvm::StringRef getOutputConstraint(unsigned i) const;
StringRef getOutputConstraint(unsigned i) const;
const StringLiteral *getOutputConstraintLiteral(unsigned i) const {
return Constraints[i];
@ -1364,16 +1374,16 @@ class AsmStmt : public Stmt {
return Names[i + NumOutputs];
}
llvm::StringRef getInputName(unsigned i) const {
StringRef getInputName(unsigned i) const {
if (IdentifierInfo *II = getInputIdentifier(i))
return II->getName();
return llvm::StringRef();
return StringRef();
}
/// getInputConstraint - Return the specified input constraint. Unlike output
/// constraints, these can be empty.
llvm::StringRef getInputConstraint(unsigned i) const;
StringRef getInputConstraint(unsigned i) const;
const StringLiteral *getInputConstraintLiteral(unsigned i) const {
return Constraints[i + NumOutputs];
@ -1403,7 +1413,7 @@ class AsmStmt : public Stmt {
/// getNamedOperand - Given a symbolic operand reference like %[foo],
/// translate this into a numeric value needed to reference the same operand.
/// This returns -1 if the operand name is invalid.
int getNamedOperand(llvm::StringRef SymbolicName) const;
int getNamedOperand(StringRef SymbolicName) const;
unsigned getNumClobbers() const { return NumClobbers; }
StringLiteral *getClobber(unsigned i) { return Clobbers[i]; }

View File

@ -42,7 +42,7 @@ class StmtVisitorBase {
// below.
if (PTR(BinaryOperator) BinOp = dyn_cast<BinaryOperator>(S)) {
switch (BinOp->getOpcode()) {
default: assert(0 && "Unknown binary operator!");
default: llvm_unreachable("Unknown binary operator!");
case BO_PtrMemD: DISPATCH(BinPtrMemD, BinaryOperator);
case BO_PtrMemI: DISPATCH(BinPtrMemI, BinaryOperator);
case BO_Mul: DISPATCH(BinMul, BinaryOperator);
@ -80,7 +80,7 @@ class StmtVisitorBase {
}
} else if (PTR(UnaryOperator) UnOp = dyn_cast<UnaryOperator>(S)) {
switch (UnOp->getOpcode()) {
default: assert(0 && "Unknown unary operator!");
default: llvm_unreachable("Unknown unary operator!");
case UO_PostInc: DISPATCH(UnaryPostInc, UnaryOperator);
case UO_PostDec: DISPATCH(UnaryPostDec, UnaryOperator);
case UO_PreInc: DISPATCH(UnaryPreInc, UnaryOperator);
@ -99,7 +99,7 @@ class StmtVisitorBase {
// Top switch stmt: dispatch to VisitFooStmt for each FooStmt.
switch (S->getStmtClass()) {
default: assert(0 && "Unknown stmt kind!");
default: llvm_unreachable("Unknown stmt kind!");
#define ABSTRACT_STMT(STMT)
#define STMT(CLASS, PARENT) \
case Stmt::CLASS ## Class: DISPATCH(CLASS, CLASS);

View File

@ -23,7 +23,6 @@
namespace llvm {
class FoldingSetNodeID;
class raw_ostream;
}
namespace clang {
@ -354,7 +353,7 @@ class TemplateArgument {
TemplateArgument getPackExpansionPattern() const;
/// \brief Print this template argument to the given output stream.
void print(const PrintingPolicy &Policy, llvm::raw_ostream &Out) const;
void print(const PrintingPolicy &Policy, raw_ostream &Out) const;
/// \brief Used to insert TemplateArguments into FoldingSets.
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const;
@ -515,10 +514,14 @@ class TemplateArgumentLoc {
/// A convenient class for passing around template argument
/// information. Designed to be passed by reference.
class TemplateArgumentListInfo {
llvm::SmallVector<TemplateArgumentLoc, 8> Arguments;
SmallVector<TemplateArgumentLoc, 8> Arguments;
SourceLocation LAngleLoc;
SourceLocation RAngleLoc;
// This can leak if used in an AST node, use ASTTemplateArgumentListInfo
// instead.
void* operator new(size_t bytes, ASTContext& C);
public:
TemplateArgumentListInfo() {}
@ -547,6 +550,48 @@ class TemplateArgumentListInfo {
}
};
/// \brief Represents an explicit template argument list in C++, e.g.,
/// the "<int>" in "sort<int>".
/// This is safe to be used inside an AST node, in contrast with
/// TemplateArgumentListInfo.
struct ASTTemplateArgumentListInfo {
/// \brief The source location of the left angle bracket ('<');
SourceLocation LAngleLoc;
/// \brief The source location of the right angle bracket ('>');
SourceLocation RAngleLoc;
/// \brief The number of template arguments in TemplateArgs.
/// The actual template arguments (if any) are stored after the
/// ExplicitTemplateArgumentList structure.
unsigned NumTemplateArgs;
/// \brief Retrieve the template arguments
TemplateArgumentLoc *getTemplateArgs() {
return reinterpret_cast<TemplateArgumentLoc *> (this + 1);
}
/// \brief Retrieve the template arguments
const TemplateArgumentLoc *getTemplateArgs() const {
return reinterpret_cast<const TemplateArgumentLoc *> (this + 1);
}
const TemplateArgumentLoc &operator[](unsigned I) const {
return getTemplateArgs()[I];
}
static const ASTTemplateArgumentListInfo *Create(ASTContext &C,
const TemplateArgumentListInfo &List);
void initializeFrom(const TemplateArgumentListInfo &List);
void initializeFrom(const TemplateArgumentListInfo &List,
bool &Dependent, bool &InstantiationDependent,
bool &ContainsUnexpandedParameterPack);
void copyInto(TemplateArgumentListInfo &List) const;
static std::size_t sizeFor(unsigned NumTemplateArgs);
static std::size_t sizeFor(const TemplateArgumentListInfo &List);
};
const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
const TemplateArgument &Arg);

View File

@ -14,14 +14,11 @@
#ifndef LLVM_CLANG_AST_TEMPLATENAME_H
#define LLVM_CLANG_AST_TEMPLATENAME_H
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerUnion.h"
#include "clang/Basic/OperatorKinds.h"
namespace llvm {
class raw_ostream;
}
namespace clang {
class ASTContext;
@ -308,7 +305,7 @@ class TemplateName {
/// \param SuppressNNS if true, don't print the
/// nested-name-specifier that precedes the template name (if it has
/// one).
void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy,
void print(raw_ostream &OS, const PrintingPolicy &Policy,
bool SuppressNNS = false) const;
/// \brief Debugging aid that dumps the template name to standard

View File

@ -22,19 +22,15 @@
#include "clang/Basic/Visibility.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TemplateName.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/type_traits.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include "clang/Basic/LLVM.h"
using llvm::isa;
using llvm::cast;
using llvm::cast_or_null;
using llvm::dyn_cast;
using llvm::dyn_cast_or_null;
namespace clang {
enum {
TypeAlignmentInBits = 4,
@ -508,6 +504,9 @@ class QualType {
const Type *getTypePtrOrNull() const;
/// Retrieves a pointer to the name of the base type.
const IdentifierInfo *getBaseTypeIdentifier() const;
/// Divides a QualType into its unqualified type and a set of local
/// qualifiers.
SplitQualType split() const;
@ -868,8 +867,9 @@ class QualType {
/// type other than void.
bool isCForbiddenLValueType() const;
/// \brief Determine whether this type has trivial copy-assignment semantics.
bool hasTrivialCopyAssignment(ASTContext &Context) const;
/// \brief Determine whether this type has trivial copy/move-assignment
/// semantics.
bool hasTrivialAssignment(ASTContext &Context, bool Copying) const;
private:
// These methods are implemented in a separate translation unit;
@ -1362,6 +1362,7 @@ class Type : public ExtQualsTypeCommonBase {
/// various convenient purposes within Clang. All such types are
/// BuiltinTypes.
bool isPlaceholderType() const;
const BuiltinType *getAsPlaceholderType() const;
/// isSpecificPlaceholderType - Test for a specific placeholder type.
bool isSpecificPlaceholderType(unsigned K) const;
@ -1373,6 +1374,8 @@ class Type : public ExtQualsTypeCommonBase {
bool isBooleanType() const;
bool isCharType() const;
bool isWideCharType() const;
bool isChar16Type() const;
bool isChar32Type() const;
bool isAnyCharacterType() const;
bool isIntegralType(ASTContext &Ctx) const;
@ -1389,6 +1392,7 @@ class Type : public ExtQualsTypeCommonBase {
bool isComplexType() const; // C99 6.2.5p11 (complex)
bool isAnyComplexType() const; // C99 6.2.5p11 (complex) + Complex Int.
bool isFloatingType() const; // C99 6.2.5p11 (real floating + complex)
bool isHalfType() const; // OpenCL 6.1.1.1, NEON (IEEE 754-2008 half)
bool isRealType() const; // C99 6.2.5p17 (real floating + integer)
bool isArithmeticType() const; // C99 6.2.5p18 (integer + floating)
bool isVoidType() const; // C99 6.2.5p19
@ -1447,6 +1451,7 @@ class Type : public ExtQualsTypeCommonBase {
bool isCARCBridgableType() const;
bool isTemplateTypeParmType() const; // C++ template type parameter
bool isNullPtrType() const; // C++0x nullptr_t
bool isAtomicType() const; // C1X _Atomic()
/// Determines if this type, which must satisfy
/// isObjCLifetimeType(), is implicitly __unsafe_unretained rather
@ -1457,7 +1462,9 @@ class Type : public ExtQualsTypeCommonBase {
Qualifiers::ObjCLifetime getObjCARCImplicitLifetime() const;
enum ScalarTypeKind {
STK_Pointer,
STK_CPointer,
STK_BlockPointer,
STK_ObjCObjectPointer,
STK_MemberPointer,
STK_Bool,
STK_Integral,
@ -1693,6 +1700,8 @@ class BuiltinType : public Type {
LongLong,
Int128, // __int128_t
Half, // This is the 'half' type in OpenCL,
// __fp16 in case of ARM NEON.
Float, Double, LongDouble,
NullPtr, // This is the type of C++0x 'nullptr'.
@ -1755,7 +1764,7 @@ class BuiltinType : public Type {
}
Kind getKind() const { return static_cast<Kind>(BuiltinTypeBits.Kind); }
const char *getName(const LangOptions &LO) const;
const char *getName(const PrintingPolicy &Policy) const;
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@ -1773,7 +1782,7 @@ class BuiltinType : public Type {
}
bool isFloatingPoint() const {
return getKind() >= Float && getKind() <= LongDouble;
return getKind() >= Half && getKind() <= LongDouble;
}
/// Determines whether this type is a placeholder type, i.e. a type
@ -2249,7 +2258,7 @@ class VariableArrayType : public ArrayType {
friend class StmtIteratorBase;
void Profile(llvm::FoldingSetNodeID &ID) {
assert(0 && "Cannot unique VariableArrayTypes.");
llvm_unreachable("Cannot unique VariableArrayTypes.");
}
};
@ -2635,7 +2644,7 @@ class FunctionType : public Type {
return getResultType().getNonLValueExprType(Context);
}
static llvm::StringRef getNameForCallConv(CallingConv CC);
static StringRef getNameForCallConv(CallingConv CC);
static bool classof(const Type *T) {
return T->getTypeClass() == FunctionNoProto ||
@ -2696,8 +2705,17 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
unsigned char TypeQuals;
RefQualifierKind RefQualifier;
unsigned NumExceptions;
/// Exceptions - A variable size array after that holds the exception types.
const QualType *Exceptions;
/// NoexceptExpr - Instead of Exceptions, there may be a single Expr*
/// pointing to the expression in the noexcept() specifier.
Expr *NoexceptExpr;
/// ConsumedArgs - A variable size array, following Exceptions
/// and of length NumArgs, holding flags indicating which arguments
/// are consumed. This only appears if HasAnyConsumedArgs is true.
const bool *ConsumedArguments;
};
@ -2728,19 +2746,6 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
/// HasAnyConsumedArgs - Whether this function has any consumed arguments.
unsigned HasAnyConsumedArgs : 1;
/// ArgInfo - There is an variable size array after the class in memory that
/// holds the argument types.
/// Exceptions - There is another variable size array after ArgInfo that
/// holds the exception types.
/// NoexceptExpr - Instead of Exceptions, there may be a single Expr* pointing
/// to the expression in the noexcept() specifier.
/// ConsumedArgs - A variable size array, following Exceptions
/// and of length NumArgs, holding flags indicating which arguments
/// are consumed. This only appears if HasAnyConsumedArgs is true.
friend class ASTContext; // ASTContext creates these.
const bool *getConsumedArgsBuffer() const {
@ -4348,6 +4353,37 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
static bool classof(const ObjCObjectPointerType *) { return true; }
};
class AtomicType : public Type, public llvm::FoldingSetNode {
QualType ValueType;
AtomicType(QualType ValTy, QualType Canonical)
: Type(Atomic, Canonical, ValTy->isDependentType(),
ValTy->isInstantiationDependentType(),
ValTy->isVariablyModifiedType(),
ValTy->containsUnexpandedParameterPack()),
ValueType(ValTy) {}
friend class ASTContext; // ASTContext creates these.
public:
/// getValueType - Gets the type contained by this atomic type, i.e.
/// the type returned by performing an atomic load of this atomic type.
QualType getValueType() const { return ValueType; }
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getValueType());
}
static void Profile(llvm::FoldingSetNodeID &ID, QualType T) {
ID.AddPointer(T.getAsOpaquePtr());
}
static bool classof(const Type *T) {
return T->getTypeClass() == Atomic;
}
static bool classof(const AtomicType *) { return true; }
};
/// A qualifier set is used to build a set of qualifiers.
class QualifierCollector : public Qualifiers {
public:
@ -4673,6 +4709,9 @@ inline bool Type::isObjCObjectOrInterfaceType() const {
return isa<ObjCInterfaceType>(CanonicalType) ||
isa<ObjCObjectType>(CanonicalType);
}
inline bool Type::isAtomicType() const {
return isa<AtomicType>(CanonicalType);
}
inline bool Type::isObjCQualifiedIdType() const {
if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
@ -4714,11 +4753,18 @@ inline bool Type::isSpecificBuiltinType(unsigned K) const {
}
inline bool Type::isPlaceholderType() const {
if (const BuiltinType *BT = getAs<BuiltinType>())
if (const BuiltinType *BT = dyn_cast<BuiltinType>(this))
return BT->isPlaceholderType();
return false;
}
inline const BuiltinType *Type::getAsPlaceholderType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(this))
if (BT->isPlaceholderType())
return BT;
return 0;
}
inline bool Type::isSpecificPlaceholderType(unsigned K) const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(this))
return (BT->getKind() == (BuiltinType::Kind) K);
@ -4757,7 +4803,7 @@ inline const Type *Type::getBaseElementTypeUnsafe() const {
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
QualType T) {
DB.AddTaggedVal(reinterpret_cast<intptr_t>(T.getAsOpaquePtr()),
Diagnostic::ak_qualtype);
DiagnosticsEngine::ak_qualtype);
return DB;
}
@ -4766,7 +4812,7 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
QualType T) {
PD.AddTaggedVal(reinterpret_cast<intptr_t>(T.getAsOpaquePtr()),
Diagnostic::ak_qualtype);
DiagnosticsEngine::ak_qualtype);
return PD;
}

View File

@ -538,6 +538,10 @@ class InjectedClassNameTypeLoc :
public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
InjectedClassNameTypeLoc,
InjectedClassNameType> {
public:
CXXRecordDecl *getDecl() const {
return getTypePtr()->getDecl();
}
};
/// \brief Wrapper for source info for unresolved typename using decls.
@ -561,6 +565,12 @@ class TagTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
TagType> {
public:
TagDecl *getDecl() const { return getTypePtr()->getDecl(); }
/// \brief True if the tag was defined in this type specifier.
bool isDefinition() const {
return getDecl()->isCompleteDefinition() &&
(getNameLoc().isInvalid() || getNameLoc() == getDecl()->getLocation());
}
};
/// \brief Wrapper for source info for record types.
@ -1408,6 +1418,8 @@ class TypeOfTypeLoc
class DecltypeTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
DecltypeTypeLoc,
DecltypeType> {
public:
Expr *getUnderlyingExpr() const { return getTypePtr()->getUnderlyingExpr(); }
};
struct UnaryTransformTypeLocInfo {
@ -1718,6 +1730,62 @@ class PackExpansionTypeLoc
}
};
struct AtomicTypeLocInfo {
SourceLocation KWLoc, LParenLoc, RParenLoc;
};
class AtomicTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, AtomicTypeLoc,
AtomicType, AtomicTypeLocInfo> {
public:
TypeLoc getValueLoc() const {
return this->getInnerTypeLoc();
}
SourceRange getLocalSourceRange() const {
return SourceRange(getKWLoc(), getRParenLoc());
}
SourceLocation getKWLoc() const {
return this->getLocalData()->KWLoc;
}
void setKWLoc(SourceLocation Loc) {
this->getLocalData()->KWLoc = Loc;
}
SourceLocation getLParenLoc() const {
return this->getLocalData()->LParenLoc;
}
void setLParenLoc(SourceLocation Loc) {
this->getLocalData()->LParenLoc = Loc;
}
SourceLocation getRParenLoc() const {
return this->getLocalData()->RParenLoc;
}
void setRParenLoc(SourceLocation Loc) {
this->getLocalData()->RParenLoc = Loc;
}
SourceRange getParensRange() const {
return SourceRange(getLParenLoc(), getRParenLoc());
}
void setParensRange(SourceRange Range) {
setLParenLoc(Range.getBegin());
setRParenLoc(Range.getEnd());
}
void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setKWLoc(Loc);
setLParenLoc(Loc);
setRParenLoc(Loc);
}
QualType getInnerType() const {
return this->getTypePtr()->getValueType();
}
};
}
#endif

View File

@ -102,9 +102,10 @@ DEPENDENT_TYPE(PackExpansion, Type)
TYPE(ObjCObject, Type)
TYPE(ObjCInterface, ObjCObjectType)
TYPE(ObjCObjectPointer, Type)
TYPE(Atomic, Type)
#ifdef LAST_TYPE
LAST_TYPE(ObjCObjectPointer)
LAST_TYPE(Atomic)
#undef LAST_TYPE
#endif

View File

@ -28,7 +28,7 @@ class TypeVisitor {
RetTy Visit(const Type *T) {
// Top switch stmt: dispatch to VisitFooType for each FooType.
switch (T->getTypeClass()) {
default: assert(0 && "Unknown type class!");
default: llvm_unreachable("Unknown type class!");
#define ABSTRACT_TYPE(CLASS, PARENT)
#define TYPE(CLASS, PARENT) case Type::CLASS: DISPATCH(CLASS##Type);
#include "clang/AST/TypeNodes.def"

View File

@ -25,7 +25,7 @@ namespace clang {
/// non-const iterator.
class UnresolvedSetIterator {
private:
typedef llvm::SmallVectorImpl<DeclAccessPair> DeclsTy;
typedef SmallVectorImpl<DeclAccessPair> DeclsTy;
typedef DeclsTy::iterator IteratorTy;
IteratorTy ir;
@ -177,7 +177,7 @@ class UnresolvedSetImpl {
/// A set of unresolved declarations
template <unsigned InlineCapacity> class UnresolvedSet :
public UnresolvedSetImpl {
llvm::SmallVector<DeclAccessPair, InlineCapacity> Decls;
SmallVector<DeclAccessPair, InlineCapacity> Decls;
};

View File

@ -0,0 +1,176 @@
//===--- VTTBuilder.h - C++ VTT layout builder --------------------*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This contains code dealing with generation of the layout of virtual table
// tables (VTT).
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_VTTBUILDER_H
#define LLVM_CLANG_AST_VTTBUILDER_H
#include "clang/AST/BaseSubobject.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/GlobalDecl.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/ABI.h"
#include "llvm/ADT/SetVector.h"
#include <utility>
namespace clang {
class VTTVTable {
llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> BaseAndIsVirtual;
CharUnits BaseOffset;
public:
VTTVTable() {}
VTTVTable(const CXXRecordDecl *Base, CharUnits BaseOffset, bool BaseIsVirtual)
: BaseAndIsVirtual(Base, BaseIsVirtual), BaseOffset(BaseOffset) {}
VTTVTable(BaseSubobject Base, bool BaseIsVirtual)
: BaseAndIsVirtual(Base.getBase(), BaseIsVirtual),
BaseOffset(Base.getBaseOffset()) {}
const CXXRecordDecl *getBase() const {
return BaseAndIsVirtual.getPointer();
}
CharUnits getBaseOffset() const {
return BaseOffset;
}
bool isVirtual() const {
return BaseAndIsVirtual.getInt();
}
BaseSubobject getBaseSubobject() const {
return BaseSubobject(getBase(), getBaseOffset());
}
};
struct VTTComponent {
uint64_t VTableIndex;
BaseSubobject VTableBase;
VTTComponent() {}
VTTComponent(uint64_t VTableIndex, BaseSubobject VTableBase)
: VTableIndex(VTableIndex), VTableBase(VTableBase) {}
};
/// VTT builder - Class for building VTT layout information.
class VTTBuilder {
ASTContext &Ctx;
/// MostDerivedClass - The most derived class for which we're building this
/// vtable.
const CXXRecordDecl *MostDerivedClass;
typedef SmallVector<VTTVTable, 64> VTTVTablesVectorTy;
/// VTTVTables - The VTT vtables.
VTTVTablesVectorTy VTTVTables;
typedef SmallVector<VTTComponent, 64> VTTComponentsVectorTy;
/// VTTComponents - The VTT components.
VTTComponentsVectorTy VTTComponents;
/// MostDerivedClassLayout - the AST record layout of the most derived class.
const ASTRecordLayout &MostDerivedClassLayout;
typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy;
/// SubVTTIndicies - The sub-VTT indices for the bases of the most derived
/// class.
llvm::DenseMap<BaseSubobject, uint64_t> SubVTTIndicies;
/// SecondaryVirtualPointerIndices - The secondary virtual pointer indices of
/// all subobjects of the most derived class.
llvm::DenseMap<BaseSubobject, uint64_t> SecondaryVirtualPointerIndices;
/// GenerateDefinition - Whether the VTT builder should generate LLVM IR for
/// the VTT.
bool GenerateDefinition;
/// AddVTablePointer - Add a vtable pointer to the VTT currently being built.
///
/// \param AddressPoints - If the vtable is a construction vtable, this has
/// the address points for it.
void AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex,
const CXXRecordDecl *VTableClass);
/// LayoutSecondaryVTTs - Lay out the secondary VTTs of the given base
/// subobject.
void LayoutSecondaryVTTs(BaseSubobject Base);
/// LayoutSecondaryVirtualPointers - Lay out the secondary virtual pointers
/// for the given base subobject.
///
/// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
/// or a direct or indirect base of a virtual base.
///
/// \param AddressPoints - If the vtable is a construction vtable, this has
/// the address points for it.
void LayoutSecondaryVirtualPointers(BaseSubobject Base,
bool BaseIsMorallyVirtual,
uint64_t VTableIndex,
const CXXRecordDecl *VTableClass,
VisitedVirtualBasesSetTy &VBases);
/// LayoutSecondaryVirtualPointers - Lay out the secondary virtual pointers
/// for the given base subobject.
///
/// \param AddressPoints - If the vtable is a construction vtable, this has
/// the address points for it.
void LayoutSecondaryVirtualPointers(BaseSubobject Base,
uint64_t VTableIndex);
/// LayoutVirtualVTTs - Lay out the VTTs for the virtual base classes of the
/// given record decl.
void LayoutVirtualVTTs(const CXXRecordDecl *RD,
VisitedVirtualBasesSetTy &VBases);
/// LayoutVTT - Will lay out the VTT for the given subobject, including any
/// secondary VTTs, secondary virtual pointers and virtual VTTs.
void LayoutVTT(BaseSubobject Base, bool BaseIsVirtual);
public:
VTTBuilder(ASTContext &Ctx, const CXXRecordDecl *MostDerivedClass,
bool GenerateDefinition);
// getVTTComponents - Returns a reference to the VTT components.
const VTTComponentsVectorTy &getVTTComponents() const {
return VTTComponents;
}
// getVTTVTables - Returns a reference to the VTT vtables.
const VTTVTablesVectorTy &getVTTVTables() const {
return VTTVTables;
}
/// getSubVTTIndicies - Returns a reference to the sub-VTT indices.
const llvm::DenseMap<BaseSubobject, uint64_t> &getSubVTTIndicies() const {
return SubVTTIndicies;
}
/// getSecondaryVirtualPointerIndices - Returns a reference to the secondary
/// virtual pointer indices.
const llvm::DenseMap<BaseSubobject, uint64_t> &
getSecondaryVirtualPointerIndices() const {
return SecondaryVirtualPointerIndices;
}
};
}
#endif

View File

@ -0,0 +1,357 @@
//===--- VTableBuilder.h - C++ vtable layout builder --------------*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This contains code dealing with generation of the layout of virtual tables.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_VTABLEBUILDER_H
#define LLVM_CLANG_AST_VTABLEBUILDER_H
#include "clang/AST/BaseSubobject.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/GlobalDecl.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/ABI.h"
#include "llvm/ADT/SetVector.h"
#include <utility>
namespace clang {
class CXXRecordDecl;
/// VTableComponent - Represents a single component in a vtable.
class VTableComponent {
public:
enum Kind {
CK_VCallOffset,
CK_VBaseOffset,
CK_OffsetToTop,
CK_RTTI,
CK_FunctionPointer,
/// CK_CompleteDtorPointer - A pointer to the complete destructor.
CK_CompleteDtorPointer,
/// CK_DeletingDtorPointer - A pointer to the deleting destructor.
CK_DeletingDtorPointer,
/// CK_UnusedFunctionPointer - In some cases, a vtable function pointer
/// will end up never being called. Such vtable function pointers are
/// represented as a CK_UnusedFunctionPointer.
CK_UnusedFunctionPointer
};
VTableComponent() { }
static VTableComponent MakeVCallOffset(CharUnits Offset) {
return VTableComponent(CK_VCallOffset, Offset);
}
static VTableComponent MakeVBaseOffset(CharUnits Offset) {
return VTableComponent(CK_VBaseOffset, Offset);
}
static VTableComponent MakeOffsetToTop(CharUnits Offset) {
return VTableComponent(CK_OffsetToTop, Offset);
}
static VTableComponent MakeRTTI(const CXXRecordDecl *RD) {
return VTableComponent(CK_RTTI, reinterpret_cast<uintptr_t>(RD));
}
static VTableComponent MakeFunction(const CXXMethodDecl *MD) {
assert(!isa<CXXDestructorDecl>(MD) &&
"Don't use MakeFunction with destructors!");
return VTableComponent(CK_FunctionPointer,
reinterpret_cast<uintptr_t>(MD));
}
static VTableComponent MakeCompleteDtor(const CXXDestructorDecl *DD) {
return VTableComponent(CK_CompleteDtorPointer,
reinterpret_cast<uintptr_t>(DD));
}
static VTableComponent MakeDeletingDtor(const CXXDestructorDecl *DD) {
return VTableComponent(CK_DeletingDtorPointer,
reinterpret_cast<uintptr_t>(DD));
}
static VTableComponent MakeUnusedFunction(const CXXMethodDecl *MD) {
assert(!isa<CXXDestructorDecl>(MD) &&
"Don't use MakeUnusedFunction with destructors!");
return VTableComponent(CK_UnusedFunctionPointer,
reinterpret_cast<uintptr_t>(MD));
}
static VTableComponent getFromOpaqueInteger(uint64_t I) {
return VTableComponent(I);
}
/// getKind - Get the kind of this vtable component.
Kind getKind() const {
return (Kind)(Value & 0x7);
}
CharUnits getVCallOffset() const {
assert(getKind() == CK_VCallOffset && "Invalid component kind!");
return getOffset();
}
CharUnits getVBaseOffset() const {
assert(getKind() == CK_VBaseOffset && "Invalid component kind!");
return getOffset();
}
CharUnits getOffsetToTop() const {
assert(getKind() == CK_OffsetToTop && "Invalid component kind!");
return getOffset();
}
const CXXRecordDecl *getRTTIDecl() const {
assert(getKind() == CK_RTTI && "Invalid component kind!");
return reinterpret_cast<CXXRecordDecl *>(getPointer());
}
const CXXMethodDecl *getFunctionDecl() const {
assert(getKind() == CK_FunctionPointer);
return reinterpret_cast<CXXMethodDecl *>(getPointer());
}
const CXXDestructorDecl *getDestructorDecl() const {
assert((getKind() == CK_CompleteDtorPointer ||
getKind() == CK_DeletingDtorPointer) && "Invalid component kind!");
return reinterpret_cast<CXXDestructorDecl *>(getPointer());
}
const CXXMethodDecl *getUnusedFunctionDecl() const {
assert(getKind() == CK_UnusedFunctionPointer);
return reinterpret_cast<CXXMethodDecl *>(getPointer());
}
private:
VTableComponent(Kind ComponentKind, CharUnits Offset) {
assert((ComponentKind == CK_VCallOffset ||
ComponentKind == CK_VBaseOffset ||
ComponentKind == CK_OffsetToTop) && "Invalid component kind!");
assert(Offset.getQuantity() <= ((1LL << 56) - 1) && "Offset is too big!");
Value = ((Offset.getQuantity() << 3) | ComponentKind);
}
VTableComponent(Kind ComponentKind, uintptr_t Ptr) {
assert((ComponentKind == CK_RTTI ||
ComponentKind == CK_FunctionPointer ||
ComponentKind == CK_CompleteDtorPointer ||
ComponentKind == CK_DeletingDtorPointer ||
ComponentKind == CK_UnusedFunctionPointer) &&
"Invalid component kind!");
assert((Ptr & 7) == 0 && "Pointer not sufficiently aligned!");
Value = Ptr | ComponentKind;
}
CharUnits getOffset() const {
assert((getKind() == CK_VCallOffset || getKind() == CK_VBaseOffset ||
getKind() == CK_OffsetToTop) && "Invalid component kind!");
return CharUnits::fromQuantity(Value >> 3);
}
uintptr_t getPointer() const {
assert((getKind() == CK_RTTI ||
getKind() == CK_FunctionPointer ||
getKind() == CK_CompleteDtorPointer ||
getKind() == CK_DeletingDtorPointer ||
getKind() == CK_UnusedFunctionPointer) &&
"Invalid component kind!");
return static_cast<uintptr_t>(Value & ~7ULL);
}
explicit VTableComponent(uint64_t Value)
: Value(Value) { }
/// The kind is stored in the lower 3 bits of the value. For offsets, we
/// make use of the facts that classes can't be larger than 2^55 bytes,
/// so we store the offset in the lower part of the 61 bytes that remain.
/// (The reason that we're not simply using a PointerIntPair here is that we
/// need the offsets to be 64-bit, even when on a 32-bit machine).
int64_t Value;
};
class VTableLayout {
public:
typedef std::pair<uint64_t, ThunkInfo> VTableThunkTy;
typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
typedef const VTableComponent *vtable_component_iterator;
typedef const VTableThunkTy *vtable_thunk_iterator;
typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy;
private:
uint64_t NumVTableComponents;
VTableComponent *VTableComponents;
/// VTableThunks - Contains thunks needed by vtables.
uint64_t NumVTableThunks;
VTableThunkTy *VTableThunks;
/// Address points - Address points for all vtables.
AddressPointsMapTy AddressPoints;
public:
VTableLayout(uint64_t NumVTableComponents,
const VTableComponent *VTableComponents,
uint64_t NumVTableThunks,
const VTableThunkTy *VTableThunks,
const AddressPointsMapTy &AddressPoints);
~VTableLayout();
uint64_t getNumVTableComponents() const {
return NumVTableComponents;
}
vtable_component_iterator vtable_component_begin() const {
return VTableComponents;
}
vtable_component_iterator vtable_component_end() const {
return VTableComponents+NumVTableComponents;
}
uint64_t getNumVTableThunks() const {
return NumVTableThunks;
}
vtable_thunk_iterator vtable_thunk_begin() const {
return VTableThunks;
}
vtable_thunk_iterator vtable_thunk_end() const {
return VTableThunks+NumVTableThunks;
}
uint64_t getAddressPoint(BaseSubobject Base) const {
assert(AddressPoints.count(Base) &&
"Did not find address point!");
uint64_t AddressPoint = AddressPoints.lookup(Base);
assert(AddressPoint && "Address point must not be zero!");
return AddressPoint;
}
const AddressPointsMapTy &getAddressPoints() const {
return AddressPoints;
}
};
class VTableContext {
ASTContext &Context;
public:
typedef SmallVector<std::pair<uint64_t, ThunkInfo>, 1>
VTableThunksTy;
typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
private:
/// MethodVTableIndices - Contains the index (relative to the vtable address
/// point) where the function pointer for a virtual function is stored.
typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy;
MethodVTableIndicesTy MethodVTableIndices;
typedef llvm::DenseMap<const CXXRecordDecl *, const VTableLayout *>
VTableLayoutMapTy;
VTableLayoutMapTy VTableLayouts;
/// NumVirtualFunctionPointers - Contains the number of virtual function
/// pointers in the vtable for a given record decl.
llvm::DenseMap<const CXXRecordDecl *, uint64_t> NumVirtualFunctionPointers;
typedef std::pair<const CXXRecordDecl *,
const CXXRecordDecl *> ClassPairTy;
/// VirtualBaseClassOffsetOffsets - Contains the vtable offset (relative to
/// the address point) in chars where the offsets for virtual bases of a class
/// are stored.
typedef llvm::DenseMap<ClassPairTy, CharUnits>
VirtualBaseClassOffsetOffsetsMapTy;
VirtualBaseClassOffsetOffsetsMapTy VirtualBaseClassOffsetOffsets;
typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
/// Thunks - Contains all thunks that a given method decl will need.
ThunksMapTy Thunks;
void ComputeMethodVTableIndices(const CXXRecordDecl *RD);
/// ComputeVTableRelatedInformation - Compute and store all vtable related
/// information (vtable layout, vbase offset offsets, thunks etc) for the
/// given record decl.
void ComputeVTableRelatedInformation(const CXXRecordDecl *RD);
public:
VTableContext(ASTContext &Context) : Context(Context) {}
~VTableContext();
const VTableLayout &getVTableLayout(const CXXRecordDecl *RD) {
ComputeVTableRelatedInformation(RD);
assert(VTableLayouts.count(RD) && "No layout for this record decl!");
return *VTableLayouts[RD];
}
VTableLayout *
createConstructionVTableLayout(const CXXRecordDecl *MostDerivedClass,
CharUnits MostDerivedClassOffset,
bool MostDerivedClassIsVirtual,
const CXXRecordDecl *LayoutClass);
const ThunkInfoVectorTy *getThunkInfo(const CXXMethodDecl *MD) {
ComputeVTableRelatedInformation(MD->getParent());
ThunksMapTy::const_iterator I = Thunks.find(MD);
if (I == Thunks.end()) {
// We did not find a thunk for this method.
return 0;
}
return &I->second;
}
/// getNumVirtualFunctionPointers - Return the number of virtual function
/// pointers in the vtable for a given record decl.
uint64_t getNumVirtualFunctionPointers(const CXXRecordDecl *RD);
/// getMethodVTableIndex - Return the index (relative to the vtable address
/// point) where the function pointer for the given virtual function is
/// stored.
uint64_t getMethodVTableIndex(GlobalDecl GD);
/// getVirtualBaseOffsetOffset - Return the offset in chars (relative to the
/// vtable address point) where the offset of the virtual base that contains
/// the given base is stored, otherwise, if no virtual base contains the given
/// class, return 0. Base must be a virtual base class or an unambigious
/// base.
CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
const CXXRecordDecl *VBase);
};
}
#endif

View File

@ -164,8 +164,8 @@ class ConversionSpecifier {
return Position;
}
llvm::StringRef getCharacters() const {
return llvm::StringRef(getStart(), getLength());
StringRef getCharacters() const {
return StringRef(getStart(), getLength());
}
bool consumesDataArgument() const {
@ -271,7 +271,7 @@ class OptionalAmount {
ArgTypeResult getArgType(ASTContext &Ctx) const;
void toString(llvm::raw_ostream &os) const;
void toString(raw_ostream &os) const;
bool usesPositionalArg() const { return (bool) UsesPositionalArg; }
unsigned getPositionalArgIndex() const {
@ -465,7 +465,7 @@ class PrintfSpecifier : public analyze_format_string::FormatSpecifier {
/// was not successful.
bool fixType(QualType QT);
void toString(llvm::raw_ostream &os) const;
void toString(raw_ostream &os) const;
// Validation methods - to check if any element results in undefined behavior
bool hasValidPlusPrefix() const;

View File

@ -1,4 +1,4 @@
//===- LiveVariables.h - Live Variable Analysis for Source CFGs -*- C++ --*-===//
//===- LiveVariables.h - Live Variable Analysis for Source CFGs -*- C++ --*-//
//
// The LLVM Compiler Infrastructure
//
@ -14,110 +14,105 @@
#ifndef LLVM_CLANG_LIVEVARIABLES_H
#define LLVM_CLANG_LIVEVARIABLES_H
#include "clang/Analysis/AnalysisContext.h"
#include "clang/AST/Decl.h"
#include "clang/Analysis/Support/BlkExprDeclBitVector.h"
#include "clang/Analysis/FlowSensitive/DataflowValues.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/ImmutableSet.h"
namespace clang {
class CFG;
class CFGBlock;
class Stmt;
class DeclRefExpr;
class SourceManager;
class AnalysisContext;
struct LiveVariables_ValueTypes {
struct ObserverTy;
// We keep dataflow state for declarations and block-level expressions;
typedef StmtDeclBitVector_Types::ValTy ValTy;
// We need to keep track of both declarations and CFGBlock-level expressions,
// (so that we don't explore such expressions twice). We also want
// to compute liveness information for block-level expressions, since these
// act as "temporary" values.
struct AnalysisDataTy : public StmtDeclBitVector_Types::AnalysisDataTy {
ObserverTy* Observer;
ValTy AlwaysLive;
AnalysisContext *AC;
bool killAtAssign;
AnalysisDataTy() : Observer(NULL), AC(NULL), killAtAssign(true) {}
};
//===-----------------------------------------------------===//
// ObserverTy - Observer for uninitialized values queries.
//===-----------------------------------------------------===//
struct ObserverTy {
virtual ~ObserverTy() {}
/// ObserveStmt - A callback invoked right before invoking the
/// liveness transfer function on the given statement.
virtual void ObserveStmt(Stmt* S, const CFGBlock *currentBlock,
const AnalysisDataTy& AD,
const ValTy& V) {}
virtual void ObserverKill(DeclRefExpr* DR) {}
};
};
class LiveVariables : public DataflowValues<LiveVariables_ValueTypes,
dataflow::backward_analysis_tag> {
class LiveVariables : public ManagedAnalysis {
public:
typedef LiveVariables_ValueTypes::ObserverTy ObserverTy;
class LivenessValues {
public:
LiveVariables(AnalysisContext &AC, bool killAtAssign = true);
llvm::ImmutableSet<const Stmt *> liveStmts;
llvm::ImmutableSet<const VarDecl *> liveDecls;
bool equals(const LivenessValues &V) const;
/// IsLive - Return true if a variable is live at the end of a
LivenessValues()
: liveStmts(0), liveDecls(0) {}
LivenessValues(llvm::ImmutableSet<const Stmt *> LiveStmts,
llvm::ImmutableSet<const VarDecl *> LiveDecls)
: liveStmts(LiveStmts), liveDecls(LiveDecls) {}
~LivenessValues() {}
bool isLive(const Stmt *S) const;
bool isLive(const VarDecl *D) const;
friend class LiveVariables;
};
struct Observer {
virtual ~Observer() {}
/// A callback invoked right before invoking the
/// liveness transfer function on the given statement.
virtual void observeStmt(const Stmt *S,
const CFGBlock *currentBlock,
const LivenessValues& V) {}
/// Called when the live variables analysis registers
/// that a variable is killed.
virtual void observerKill(const DeclRefExpr *DR) {}
};
virtual ~LiveVariables();
/// Compute the liveness information for a given CFG.
static LiveVariables *computeLiveness(AnalysisContext &analysisContext,
bool killAtAssign);
/// Return true if a variable is live at the end of a
/// specified block.
bool isLive(const CFGBlock* B, const VarDecl* D) const;
/// IsLive - Returns true if a variable is live at the beginning of the
bool isLive(const CFGBlock *B, const VarDecl *D);
/// Returns true if a variable is live at the beginning of the
/// the statement. This query only works if liveness information
/// has been recorded at the statement level (see runOnAllBlocks), and
/// only returns liveness information for block-level expressions.
bool isLive(const Stmt* S, const VarDecl* D) const;
/// IsLive - Returns true the block-level expression "value" is live
bool isLive(const Stmt *S, const VarDecl *D);
/// Returns true the block-level expression "value" is live
/// before the given block-level expression (see runOnAllBlocks).
bool isLive(const Stmt* Loc, const Stmt* StmtVal) const;
bool isLive(const Stmt *Loc, const Stmt *StmtVal);
/// Print to stderr the liveness information associated with
/// each basic block.
void dumpBlockLiveness(const SourceManager& M);
/// IsLive - Return true if a variable is live according to the
/// provided livness bitvector.
bool isLive(const ValTy& V, const VarDecl* D) const;
/// dumpLiveness - Print to stderr the liveness information encoded
/// by a specified bitvector.
void dumpLiveness(const ValTy& V, const SourceManager& M) const;
/// dumpBlockLiveness - Print to stderr the liveness information
/// associated with each basic block.
void dumpBlockLiveness(const SourceManager& M) const;
/// getNumDecls - Return the number of variables (declarations) that
/// whose liveness status is being tracked by the dataflow
/// analysis.
unsigned getNumDecls() const { return getAnalysisData().getNumDecls(); }
/// IntializeValues - This routine can perform extra initialization, but
/// for LiveVariables this does nothing since all that logic is in
/// the constructor.
void InitializeValues(const CFG& cfg) {}
void runOnCFG(CFG& cfg);
/// runOnAllBlocks - Propagate the dataflow values once for each block,
/// starting from the current dataflow values. 'recordStmtValues' indicates
/// whether the method should store dataflow values per each individual
/// block-level expression.
void runOnAllBlocks(const CFG& cfg, ObserverTy* Obs,
bool recordStmtValues=false);
void runOnAllBlocks(Observer &obs);
static LiveVariables *create(AnalysisContext &analysisContext) {
return computeLiveness(analysisContext, true);
}
static const void *getTag();
private:
LiveVariables(void *impl);
void *impl;
};
class RelaxedLiveVariables : public LiveVariables {
public:
static LiveVariables *create(AnalysisContext &analysisContext) {
return computeLiveness(analysisContext, false);
}
static const void *getTag();
};
} // end namespace clang
#endif

View File

@ -45,7 +45,7 @@ class Callback {
/// ScanReachableFromBlock - Mark all blocks reachable from Start.
/// Returns the total number of blocks that were marked reachable.
unsigned ScanReachableFromBlock(const CFGBlock &Start,
unsigned ScanReachableFromBlock(const CFGBlock *Start,
llvm::BitVector &Reachable);
void FindUnreachableCode(AnalysisContext &AC, Callback &CB);

View File

@ -0,0 +1,153 @@
//===- ThreadSafety.h ------------------------------------------*- C++ --*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//
// A intra-procedural analysis for thread safety (e.g. deadlocks and race
// conditions), based off of an annotation system.
//
// See http://clang.llvm.org/docs/LanguageExtensions.html#threadsafety for more
// information.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_THREADSAFETY_H
#define LLVM_CLANG_THREADSAFETY_H
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/StringRef.h"
namespace clang {
namespace thread_safety {
/// This enum distinguishes between different kinds of operations that may
/// need to be protected by locks. We use this enum in error handling.
enum ProtectedOperationKind {
POK_VarDereference, /// Dereferencing a variable (e.g. p in *p = 5;)
POK_VarAccess, /// Reading or writing a variable (e.g. x in x = 5;)
POK_FunctionCall /// Making a function call (e.g. fool())
};
/// This enum distinguishes between different kinds of lock actions. For
/// example, it is an error to write a variable protected by shared version of a
/// mutex.
enum LockKind {
LK_Shared, /// Shared/reader lock of a mutex
LK_Exclusive /// Exclusive/writer lock of a mutex
};
/// This enum distinguishes between different ways to access (read or write) a
/// variable.
enum AccessKind {
AK_Read, /// Reading a variable
AK_Written /// Writing a variable
};
/// This enum distinguishes between different situations where we warn due to
/// inconsistent locking.
/// \enum SK_LockedSomeLoopIterations -- a mutex is locked for some but not all
/// loop iterations.
/// \enum SK_LockedSomePredecessors -- a mutex is locked in some but not all
/// predecessors of a CFGBlock.
/// \enum SK_LockedAtEndOfFunction -- a mutex is still locked at the end of a
/// function.
enum LockErrorKind {
LEK_LockedSomeLoopIterations,
LEK_LockedSomePredecessors,
LEK_LockedAtEndOfFunction
};
/// Handler class for thread safety warnings.
class ThreadSafetyHandler {
public:
typedef llvm::StringRef Name;
virtual ~ThreadSafetyHandler() = 0;
/// Warn about lock expressions which fail to resolve to lockable objects.
/// \param Loc -- the SourceLocation of the unresolved expression.
virtual void handleInvalidLockExp(SourceLocation Loc) {}
/// Warn about unlock function calls that do not have a prior matching lock
/// expression.
/// \param LockName -- A StringRef name for the lock expression, to be printed
/// in the error message.
/// \param Loc -- The SourceLocation of the Unlock
virtual void handleUnmatchedUnlock(Name LockName, SourceLocation Loc) {}
/// Warn about lock function calls for locks which are already held.
/// \param LockName -- A StringRef name for the lock expression, to be printed
/// in the error message.
/// \param Loc -- The location of the second lock expression.
virtual void handleDoubleLock(Name LockName, SourceLocation Loc) {}
/// Warn about situations where a mutex is sometimes held and sometimes not.
/// The three situations are:
/// 1. a mutex is locked on an "if" branch but not the "else" branch,
/// 2, or a mutex is only held at the start of some loop iterations,
/// 3. or when a mutex is locked but not unlocked inside a function.
/// \param LockName -- A StringRef name for the lock expression, to be printed
/// in the error message.
/// \param Loc -- The location of the lock expression where the mutex is locked
/// \param LEK -- which of the three above cases we should warn for
virtual void handleMutexHeldEndOfScope(Name LockName, SourceLocation Loc,
LockErrorKind LEK){}
/// Warn when a mutex is held exclusively and shared at the same point. For
/// example, if a mutex is locked exclusively during an if branch and shared
/// during the else branch.
/// \param LockName -- A StringRef name for the lock expression, to be printed
/// in the error message.
/// \param Loc1 -- The location of the first lock expression.
/// \param Loc2 -- The location of the second lock expression.
virtual void handleExclusiveAndShared(Name LockName, SourceLocation Loc1,
SourceLocation Loc2) {}
/// Warn when a protected operation occurs while no locks are held.
/// \param D -- The decl for the protected variable or function
/// \param POK -- The kind of protected operation (e.g. variable access)
/// \param AK -- The kind of access (i.e. read or write) that occurred
/// \param Loc -- The location of the protected operation.
virtual void handleNoMutexHeld(const NamedDecl *D, ProtectedOperationKind POK,
AccessKind AK, SourceLocation Loc) {}
/// Warn when a protected operation occurs while the specific mutex protecting
/// the operation is not locked.
/// \param LockName -- A StringRef name for the lock expression, to be printed
/// in the error message.
/// \param D -- The decl for the protected variable or function
/// \param POK -- The kind of protected operation (e.g. variable access)
/// \param AK -- The kind of access (i.e. read or write) that occurred
/// \param Loc -- The location of the protected operation.
virtual void handleMutexNotHeld(const NamedDecl *D,
ProtectedOperationKind POK, Name LockName,
LockKind LK, SourceLocation Loc) {}
/// Warn when a function is called while an excluded mutex is locked. For
/// example, the mutex may be locked inside the function.
/// \param FunName -- The name of the function
/// \param LockName -- A StringRef name for the lock expression, to be printed
/// in the error message.
/// \param Loc -- The location of the function call.
virtual void handleFunExcludesLock(Name FunName, Name LockName,
SourceLocation Loc) {}
};
/// \brief Check a function's CFG for thread-safety violations.
///
/// We traverse the blocks in the CFG, compute the set of mutexes that are held
/// at the end of each block, and issue warnings for thread safety violations.
/// Each block in the CFG is traversed exactly once.
void runThreadSafetyAnalysis(AnalysisContext &AC, ThreadSafetyHandler &Handler);
/// \brief Helper function that returns a LockKind required for the given level
/// of access.
LockKind getLockKindFromAccessKind(AccessKind AK);
}} // end namespace clang::thread_safety
#endif

View File

@ -27,10 +27,16 @@ class UninitVariablesHandler {
public:
UninitVariablesHandler() {}
virtual ~UninitVariablesHandler();
/// Called when the uninitialized variable is used at the given expression.
virtual void handleUseOfUninitVariable(const Expr *ex,
const VarDecl *vd,
bool isAlwaysUninit) {}
/// Called when the uninitialized variable analysis detects the
/// idiom 'int x = x'. All other uses of 'x' within the initializer
/// are handled by handleUseOfUninitVariable.
virtual void handleSelfInit(const VarDecl *vd) {}
};
struct UninitVariablesAnalysisStats {

View File

@ -19,6 +19,7 @@
#include "clang/AST/Expr.h"
#include "clang/Analysis/CFG.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/DenseMap.h"
@ -31,14 +32,35 @@ class Stmt;
class CFGReverseBlockReachabilityAnalysis;
class CFGStmtMap;
class LiveVariables;
class ManagedAnalysis;
class ParentMap;
class PseudoConstantAnalysis;
class ImplicitParamDecl;
class LocationContextManager;
class StackFrameContext;
namespace idx { class TranslationUnit; }
/// The base class of a hierarchy of objects representing analyses tied
/// to AnalysisContext.
class ManagedAnalysis {
protected:
ManagedAnalysis() {}
public:
virtual ~ManagedAnalysis();
// Subclasses need to implement:
//
// static const void *getTag();
//
// Which returns a fixed pointer address to distinguish classes of
// analysis objects. They also need to implement:
//
// static [Derived*] create(AnalysisContext &Ctx);
//
// which creates the analysis object given an AnalysisContext.
};
/// AnalysisContext contains the context data for the function or method under
/// analysis.
class AnalysisContext {
@ -54,7 +76,6 @@ class AnalysisContext {
CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs;
bool builtCFG, builtCompleteCFG;
const bool useUnoptimizedCFG;
llvm::OwningPtr<LiveVariables> liveness;
llvm::OwningPtr<LiveVariables> relaxedLiveness;
@ -67,12 +88,13 @@ class AnalysisContext {
// FIXME: remove.
llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
void *ManagedAnalyses;
public:
AnalysisContext(const Decl *d, idx::TranslationUnit *tu);
AnalysisContext(const Decl *d, idx::TranslationUnit *tu,
bool useUnoptimizedCFG = false,
bool addehedges = false,
bool addImplicitDtors = false,
bool addInitializers = false);
const CFG::BuildOptions &buildOptions);
~AnalysisContext();
@ -81,13 +103,22 @@ class AnalysisContext {
idx::TranslationUnit *getTranslationUnit() const { return TU; }
/// Return the build options used to construct the CFG.
CFG::BuildOptions &getCFGBuildOptions() {
return cfgBuildOptions;
}
const CFG::BuildOptions &getCFGBuildOptions() const {
return cfgBuildOptions;
}
/// getAddEHEdges - Return true iff we are adding exceptional edges from
/// callExprs. If this is false, then try/catch statements and blocks
/// reachable from them can appear to be dead in the CFG, analysis passes must
/// cope with that.
bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; }
bool getUseUnoptimizedCFG() const {
return cfgBuildOptions.PruneTriviallyFalseEdges;
return !cfgBuildOptions.PruneTriviallyFalseEdges;
}
bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; }
bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; }
@ -95,7 +126,7 @@ class AnalysisContext {
void registerForcedBlockExpression(const Stmt *stmt);
const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt);
Stmt *getBody();
Stmt *getBody() const;
CFG *getCFG();
CFGStmtMap *getCFGStmtMap();
@ -114,8 +145,6 @@ class AnalysisContext {
ParentMap &getParentMap();
PseudoConstantAnalysis *getPseudoConstantAnalysis();
LiveVariables *getLiveVariables();
LiveVariables *getRelaxedLiveVariables();
typedef const VarDecl * const * referenced_decls_iterator;
@ -125,29 +154,44 @@ class AnalysisContext {
/// Return the ImplicitParamDecl* associated with 'self' if this
/// AnalysisContext wraps an ObjCMethodDecl. Returns NULL otherwise.
const ImplicitParamDecl *getSelfDecl() const;
/// Return the specified analysis object, lazily running the analysis if
/// necessary. Return NULL if the analysis could not run.
template <typename T>
T *getAnalysis() {
const void *tag = T::getTag();
ManagedAnalysis *&data = getAnalysisImpl(tag);
if (!data) {
data = T::create(*this);
}
return static_cast<T*>(data);
}
private:
ManagedAnalysis *&getAnalysisImpl(const void* tag);
};
class AnalysisContextManager {
typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
ContextMap Contexts;
bool UseUnoptimizedCFG;
bool AddImplicitDtors;
bool AddInitializers;
CFG::BuildOptions cfgBuildOptions;
public:
AnalysisContextManager(bool useUnoptimizedCFG = false,
bool addImplicitDtors = false, bool addInitializers = false)
: UseUnoptimizedCFG(useUnoptimizedCFG), AddImplicitDtors(addImplicitDtors),
AddInitializers(addInitializers) {}
bool addImplicitDtors = false,
bool addInitializers = false);
~AnalysisContextManager();
AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0);
bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
bool getAddImplicitDtors() const { return AddImplicitDtors; }
bool getAddInitializers() const { return AddInitializers; }
bool getUseUnoptimizedCFG() const {
return !cfgBuildOptions.PruneTriviallyFalseEdges;
}
CFG::BuildOptions &getCFGBuildOptions() {
return cfgBuildOptions;
}
// Discard all previously created AnalysisContexts.
/// Discard all previously created AnalysisContexts.
void clear();
};
@ -187,8 +231,9 @@ class LocationContext : public llvm::FoldingSetNode {
CFG *getCFG() const { return getAnalysisContext()->getCFG(); }
LiveVariables *getLiveVariables() const {
return getAnalysisContext()->getLiveVariables();
template <typename T>
T *getAnalysis() const {
return getAnalysisContext()->getAnalysis<T>();
}
ParentMap &getParentMap() const {
@ -212,7 +257,7 @@ class LocationContext : public llvm::FoldingSetNode {
ContextKind ck,
AnalysisContext *ctx,
const LocationContext *parent,
const void* data);
const void *data);
};
class StackFrameContext : public LocationContext {
@ -251,7 +296,7 @@ class StackFrameContext : public LocationContext {
ID.AddInteger(idx);
}
static bool classof(const LocationContext* Ctx) {
static bool classof(const LocationContext *Ctx) {
return Ctx->getKind() == StackFrame;
}
};
@ -274,7 +319,7 @@ class ScopeContext : public LocationContext {
ProfileCommon(ID, Scope, ctx, parent, s);
}
static bool classof(const LocationContext* Ctx) {
static bool classof(const LocationContext *Ctx) {
return Ctx->getKind() == Scope;
}
};
@ -302,7 +347,7 @@ class BlockInvocationContext : public LocationContext {
ProfileCommon(ID, Block, ctx, parent, bd);
}
static bool classof(const LocationContext* Ctx) {
static bool classof(const LocationContext *Ctx) {
return Ctx->getKind() == Block;
}
};

View File

@ -16,7 +16,7 @@ namespace clang {
namespace diag {
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
SFINAE,ACCESS,CATEGORY,BRIEF,FULL) ENUM,
SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY,BRIEF,FULL) ENUM,
#define ANALYSISSTART
#include "clang/Basic/DiagnosticAnalysisKinds.inc"
#undef DIAG

View File

@ -21,15 +21,13 @@
#include "llvm/Support/Casting.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/BitVector.h"
#include "clang/AST/Stmt.h"
#include "clang/Analysis/Support/BumpVector.h"
#include "clang/Basic/SourceLocation.h"
#include <cassert>
#include <iterator>
namespace llvm {
class raw_ostream;
}
namespace clang {
class CXXDestructorDecl;
class Decl;
@ -98,7 +96,9 @@ class CFGStmt : public CFGElement {
public:
CFGStmt(Stmt *S) : CFGElement(Statement, S) {}
Stmt *getStmt() const { return static_cast<Stmt *>(Data1.getPointer()); }
const Stmt *getStmt() const {
return static_cast<const Stmt *>(Data1.getPointer());
}
static bool classof(const CFGElement *E) {
return E->getKind() == Statement;
@ -280,7 +280,7 @@ class CFGBlock {
void push_back(CFGElement e, BumpVectorContext &C) { Impl.push_back(e, C); }
reverse_iterator insert(reverse_iterator I, size_t Cnt, CFGElement E,
BumpVectorContext& C) {
BumpVectorContext &C) {
return Impl.insert(I, Cnt, E, C);
}
@ -333,10 +333,21 @@ class CFGBlock {
AdjacentBlocks Preds;
AdjacentBlocks Succs;
/// NoReturn - This bit is set when the basic block contains a function call
/// or implicit destructor that is attributed as 'noreturn'. In that case,
/// control cannot technically ever proceed past this block. All such blocks
/// will have a single immediate successor: the exit block. This allows them
/// to be easily reached from the exit block and using this bit quickly
/// recognized without scanning the contents of the block.
///
/// Optimization Note: This bit could be profitably folded with Terminator's
/// storage if the memory usage of CFGBlock becomes an issue.
unsigned HasNoReturnElement : 1;
public:
explicit CFGBlock(unsigned blockid, BumpVectorContext &C)
: Elements(C), Label(NULL), Terminator(NULL), LoopTarget(NULL),
BlockID(blockid), Preds(C, 1), Succs(C, 1) {}
BlockID(blockid), Preds(C, 1), Succs(C, 1), HasNoReturnElement(false) {}
~CFGBlock() {}
// Statement iterators
@ -455,42 +466,45 @@ class CFGBlock {
// Manipulation of block contents
void setTerminator(Stmt* Statement) { Terminator = Statement; }
void setLabel(Stmt* Statement) { Label = Statement; }
void setTerminator(Stmt *Statement) { Terminator = Statement; }
void setLabel(Stmt *Statement) { Label = Statement; }
void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; }
void setHasNoReturnElement() { HasNoReturnElement = true; }
CFGTerminator getTerminator() { return Terminator; }
const CFGTerminator getTerminator() const { return Terminator; }
Stmt* getTerminatorCondition();
Stmt *getTerminatorCondition();
const Stmt* getTerminatorCondition() const {
const Stmt *getTerminatorCondition() const {
return const_cast<CFGBlock*>(this)->getTerminatorCondition();
}
const Stmt *getLoopTarget() const { return LoopTarget; }
Stmt* getLabel() { return Label; }
const Stmt* getLabel() const { return Label; }
Stmt *getLabel() { return Label; }
const Stmt *getLabel() const { return Label; }
bool hasNoReturnElement() const { return HasNoReturnElement; }
unsigned getBlockID() const { return BlockID; }
void dump(const CFG *cfg, const LangOptions &LO) const;
void print(llvm::raw_ostream &OS, const CFG* cfg, const LangOptions &LO) const;
void printTerminator(llvm::raw_ostream &OS, const LangOptions &LO) const;
void print(raw_ostream &OS, const CFG* cfg, const LangOptions &LO) const;
void printTerminator(raw_ostream &OS, const LangOptions &LO) const;
void addSuccessor(CFGBlock* Block, BumpVectorContext &C) {
void addSuccessor(CFGBlock *Block, BumpVectorContext &C) {
if (Block)
Block->Preds.push_back(this, C);
Succs.push_back(Block, C);
}
void appendStmt(Stmt* statement, BumpVectorContext &C) {
void appendStmt(Stmt *statement, BumpVectorContext &C) {
Elements.push_back(CFGStmt(statement), C);
}
void appendInitializer(CXXCtorInitializer *initializer,
BumpVectorContext& C) {
BumpVectorContext &C) {
Elements.push_back(CFGInitializer(initializer), C);
}
@ -506,14 +520,18 @@ class CFGBlock {
Elements.push_back(CFGTemporaryDtor(E), C);
}
void appendAutomaticObjDtor(VarDecl *VD, Stmt *S, BumpVectorContext &C) {
Elements.push_back(CFGAutomaticObjDtor(VD, S), C);
}
// Destructors must be inserted 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 beginAutomaticObjDtorsInsert(iterator I, size_t Cnt,
BumpVectorContext& C) {
BumpVectorContext &C) {
return iterator(Elements.insert(I.base(), Cnt, CFGElement(), C));
}
iterator insertAutomaticObjDtor(iterator I, VarDecl* VD, Stmt* S) {
iterator insertAutomaticObjDtor(iterator I, VarDecl *VD, Stmt *S) {
*I = CFGAutomaticObjDtor(VD, S);
return ++I;
}
@ -533,30 +551,46 @@ class CFG {
//===--------------------------------------------------------------------===//
class BuildOptions {
llvm::BitVector alwaysAddMask;
public:
typedef llvm::DenseMap<const Stmt *, const CFGBlock*> ForcedBlkExprs;
ForcedBlkExprs **forcedBlkExprs;
bool PruneTriviallyFalseEdges:1;
bool AddEHEdges:1;
bool AddInitializers:1;
bool AddImplicitDtors:1;
bool PruneTriviallyFalseEdges;
bool AddEHEdges;
bool AddInitializers;
bool AddImplicitDtors;
bool alwaysAdd(const Stmt *stmt) const {
return alwaysAddMask[stmt->getStmtClass()];
}
BuildOptions &setAlwaysAdd(Stmt::StmtClass stmtClass, bool val = true) {
alwaysAddMask[stmtClass] = val;
return *this;
}
BuildOptions &setAllAlwaysAdd() {
alwaysAddMask.set();
return *this;
}
BuildOptions()
: forcedBlkExprs(0), PruneTriviallyFalseEdges(true)
, AddEHEdges(false)
, AddInitializers(false)
, AddImplicitDtors(false) {}
: alwaysAddMask(Stmt::lastStmtConstant, false)
,forcedBlkExprs(0), PruneTriviallyFalseEdges(true)
,AddEHEdges(false)
,AddInitializers(false)
,AddImplicitDtors(false) {}
};
/// buildCFG - Builds a CFG from an AST. The responsibility to free the
/// constructed CFG belongs to the caller.
static CFG* buildCFG(const Decl *D, Stmt* AST, ASTContext *C,
static CFG* buildCFG(const Decl *D, Stmt *AST, ASTContext *C,
const BuildOptions &BO);
/// createBlock - Create a new block in the CFG. The CFG owns the block;
/// the caller should not directly free it.
CFGBlock* createBlock();
CFGBlock *createBlock();
/// setEntry - Set the entry block of the CFG. This is typically used
/// only during CFG construction. Most CFG clients expect that the
@ -565,7 +599,7 @@ class CFG {
/// setIndirectGotoBlock - Set the block used for indirect goto jumps.
/// This is typically used only during CFG construction.
void setIndirectGotoBlock(CFGBlock* B) { IndirectGotoBlock = B; }
void setIndirectGotoBlock(CFGBlock *B) { IndirectGotoBlock = B; }
//===--------------------------------------------------------------------===//
// Block Iterators
@ -577,8 +611,8 @@ class CFG {
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
CFGBlock& front() { return *Blocks.front(); }
CFGBlock& back() { return *Blocks.back(); }
CFGBlock & front() { return *Blocks.front(); }
CFGBlock & back() { return *Blocks.back(); }
iterator begin() { return Blocks.begin(); }
iterator end() { return Blocks.end(); }
@ -590,13 +624,25 @@ class CFG {
const_reverse_iterator rbegin() const { return Blocks.rbegin(); }
const_reverse_iterator rend() const { return Blocks.rend(); }
CFGBlock& getEntry() { return *Entry; }
const CFGBlock& getEntry() const { return *Entry; }
CFGBlock& getExit() { return *Exit; }
const CFGBlock& getExit() const { return *Exit; }
CFGBlock & getEntry() { return *Entry; }
const CFGBlock & getEntry() const { return *Entry; }
CFGBlock & getExit() { return *Exit; }
const CFGBlock & getExit() const { return *Exit; }
CFGBlock* getIndirectGotoBlock() { return IndirectGotoBlock; }
const CFGBlock* getIndirectGotoBlock() const { return IndirectGotoBlock; }
CFGBlock * getIndirectGotoBlock() { return IndirectGotoBlock; }
const CFGBlock * getIndirectGotoBlock() const { return IndirectGotoBlock; }
typedef std::vector<const CFGBlock*>::const_iterator try_block_iterator;
try_block_iterator try_blocks_begin() const {
return TryDispatchBlocks.begin();
}
try_block_iterator try_blocks_end() const {
return TryDispatchBlocks.end();
}
void addTryDispatchBlock(const CFGBlock *block) {
TryDispatchBlocks.push_back(block);
}
//===--------------------------------------------------------------------===//
// Member templates useful for various batch operations over CFGs.
@ -608,7 +654,7 @@ class CFG {
for (CFGBlock::const_iterator BI=(*I)->begin(), BE=(*I)->end();
BI != BE; ++BI) {
if (const CFGStmt *stmt = BI->getAs<CFGStmt>())
O(stmt->getStmt());
O(const_cast<Stmt*>(stmt->getStmt()));
}
}
@ -624,11 +670,11 @@ class CFG {
operator unsigned() const { assert(Idx >=0); return (unsigned) Idx; }
};
bool isBlkExpr(const Stmt* S) { return getBlkExprNum(S); }
bool isBlkExpr(const Stmt *S) { return getBlkExprNum(S); }
bool isBlkExpr(const Stmt *S) const {
return const_cast<CFG*>(this)->isBlkExpr(S);
}
BlkExprNumTy getBlkExprNum(const Stmt* S);
BlkExprNumTy getBlkExprNum(const Stmt *S);
unsigned getNumBlkExprs();
/// getNumBlockIDs - Returns the total number of BlockIDs allocated (which
@ -640,7 +686,7 @@ class CFG {
//===--------------------------------------------------------------------===//
void viewCFG(const LangOptions &LO) const;
void print(llvm::raw_ostream& OS, const LangOptions &LO) const;
void print(raw_ostream &OS, const LangOptions &LO) const;
void dump(const LangOptions &LO) const;
//===--------------------------------------------------------------------===//
@ -661,8 +707,8 @@ class CFG {
}
private:
CFGBlock* Entry;
CFGBlock* Exit;
CFGBlock *Entry;
CFGBlock *Exit;
CFGBlock* IndirectGotoBlock; // Special block to contain collective dispatch
// for indirect gotos
unsigned NumBlockIDs;
@ -670,11 +716,15 @@ class CFG {
// BlkExprMap - An opaque pointer to prevent inclusion of DenseMap.h.
// It represents a map from Expr* to integers to record the set of
// block-level expressions and their "statement number" in the CFG.
void* BlkExprMap;
void * BlkExprMap;
BumpVectorContext BlkBVC;
CFGBlockListTy Blocks;
/// C++ 'try' statements are modeled with an indirect dispatch block.
/// This is the collection of such blocks present in the CFG.
std::vector<const CFGBlock *> TryDispatchBlocks;
};
} // end namespace clang
@ -703,11 +753,11 @@ template <> struct simplify_type< ::clang::CFGTerminator> {
// Traits for: CFGBlock
template <> struct GraphTraits< ::clang::CFGBlock* > {
template <> struct GraphTraits< ::clang::CFGBlock *> {
typedef ::clang::CFGBlock NodeType;
typedef ::clang::CFGBlock::succ_iterator ChildIteratorType;
static NodeType* getEntryNode(::clang::CFGBlock* BB)
static NodeType* getEntryNode(::clang::CFGBlock *BB)
{ return BB; }
static inline ChildIteratorType child_begin(NodeType* N)
@ -717,11 +767,11 @@ template <> struct GraphTraits< ::clang::CFGBlock* > {
{ return N->succ_end(); }
};
template <> struct GraphTraits< const ::clang::CFGBlock* > {
template <> struct GraphTraits< const ::clang::CFGBlock *> {
typedef const ::clang::CFGBlock NodeType;
typedef ::clang::CFGBlock::const_succ_iterator ChildIteratorType;
static NodeType* getEntryNode(const clang::CFGBlock* BB)
static NodeType* getEntryNode(const clang::CFGBlock *BB)
{ return BB; }
static inline ChildIteratorType child_begin(NodeType* N)
@ -748,7 +798,7 @@ template <> struct GraphTraits<Inverse<const ::clang::CFGBlock*> > {
// Traits for: CFG
template <> struct GraphTraits< ::clang::CFG* >
: public GraphTraits< ::clang::CFGBlock* > {
: public GraphTraits< ::clang::CFGBlock *> {
typedef ::clang::CFG::iterator nodes_iterator;
@ -758,7 +808,7 @@ template <> struct GraphTraits< ::clang::CFG* >
};
template <> struct GraphTraits<const ::clang::CFG* >
: public GraphTraits<const ::clang::CFGBlock* > {
: public GraphTraits<const ::clang::CFGBlock *> {
typedef ::clang::CFG::const_iterator nodes_iterator;

View File

@ -14,12 +14,13 @@
#ifndef LLVM_CLANG_ANALYSIS_DS_COCOA
#define LLVM_CLANG_ANALYSIS_DS_COCOA
#include "clang/Basic/IdentifierTable.h"
#include "llvm/ADT/StringRef.h"
#include "clang/AST/Type.h"
namespace clang {
class FunctionDecl;
class ObjCMethodDecl;
class QualType;
namespace ento {
namespace cocoa {
@ -33,8 +34,8 @@ namespace cocoa {
return deriveNamingConvention(S, MD) == CreateRule;
}
bool isRefType(QualType RetTy, llvm::StringRef Prefix,
llvm::StringRef Name = llvm::StringRef());
bool isRefType(QualType RetTy, StringRef Prefix,
StringRef Name = StringRef());
bool isCocoaObjectRef(QualType T);
@ -43,7 +44,7 @@ namespace cocoa {
namespace coreFoundation {
bool isCFObjectRef(QualType T);
bool followsCreateRule(llvm::StringRef functionName);
bool followsCreateRule(const FunctionDecl *FD);
}
}} // end: "clang:ento"

View File

@ -30,11 +30,11 @@ namespace clang {
class DataflowWorkListTy {
llvm::DenseMap<const CFGBlock*, unsigned char> BlockSet;
llvm::SmallVector<const CFGBlock *, 10> BlockQueue;
SmallVector<const CFGBlock *, 10> BlockQueue;
public:
/// enqueue - Add a block to the worklist. Blocks already on the
/// worklist are not added a second time.
void enqueue(const CFGBlock* B) {
void enqueue(const CFGBlock *B) {
unsigned char &x = BlockSet[B];
if (x == 1)
return;
@ -43,7 +43,7 @@ class DataflowWorkListTy {
}
/// dequeue - Remove a block from the worklist.
const CFGBlock* dequeue() {
const CFGBlock *dequeue() {
assert(!BlockQueue.empty());
const CFGBlock *B = BlockQueue.back();
BlockQueue.pop_back();
@ -69,20 +69,20 @@ template <> struct ItrTraits<forward_analysis_tag> {
typedef CFGBlock::const_succ_iterator NextBItr;
typedef CFGBlock::const_iterator StmtItr;
static PrevBItr PrevBegin(const CFGBlock* B) { return B->pred_begin(); }
static PrevBItr PrevEnd(const CFGBlock* B) { return B->pred_end(); }
static PrevBItr PrevBegin(const CFGBlock *B) { return B->pred_begin(); }
static PrevBItr PrevEnd(const CFGBlock *B) { return B->pred_end(); }
static NextBItr NextBegin(const CFGBlock* B) { return B->succ_begin(); }
static NextBItr NextEnd(const CFGBlock* B) { return B->succ_end(); }
static NextBItr NextBegin(const CFGBlock *B) { return B->succ_begin(); }
static NextBItr NextEnd(const CFGBlock *B) { return B->succ_end(); }
static StmtItr StmtBegin(const CFGBlock* B) { return B->begin(); }
static StmtItr StmtEnd(const CFGBlock* B) { return B->end(); }
static StmtItr StmtBegin(const CFGBlock *B) { return B->begin(); }
static StmtItr StmtEnd(const CFGBlock *B) { return B->end(); }
static BlockEdge PrevEdge(const CFGBlock* B, const CFGBlock* Prev) {
static BlockEdge PrevEdge(const CFGBlock *B, const CFGBlock *Prev) {
return BlockEdge(Prev, B, 0);
}
static BlockEdge NextEdge(const CFGBlock* B, const CFGBlock* Next) {
static BlockEdge NextEdge(const CFGBlock *B, const CFGBlock *Next) {
return BlockEdge(B, Next, 0);
}
};
@ -92,20 +92,20 @@ template <> struct ItrTraits<backward_analysis_tag> {
typedef CFGBlock::const_pred_iterator NextBItr;
typedef CFGBlock::const_reverse_iterator StmtItr;
static PrevBItr PrevBegin(const CFGBlock* B) { return B->succ_begin(); }
static PrevBItr PrevEnd(const CFGBlock* B) { return B->succ_end(); }
static PrevBItr PrevBegin(const CFGBlock *B) { return B->succ_begin(); }
static PrevBItr PrevEnd(const CFGBlock *B) { return B->succ_end(); }
static NextBItr NextBegin(const CFGBlock* B) { return B->pred_begin(); }
static NextBItr NextEnd(const CFGBlock* B) { return B->pred_end(); }
static NextBItr NextBegin(const CFGBlock *B) { return B->pred_begin(); }
static NextBItr NextEnd(const CFGBlock *B) { return B->pred_end(); }
static StmtItr StmtBegin(const CFGBlock* B) { return B->rbegin(); }
static StmtItr StmtEnd(const CFGBlock* B) { return B->rend(); }
static StmtItr StmtBegin(const CFGBlock *B) { return B->rbegin(); }
static StmtItr StmtEnd(const CFGBlock *B) { return B->rend(); }
static BlockEdge PrevEdge(const CFGBlock* B, const CFGBlock* Prev) {
static BlockEdge PrevEdge(const CFGBlock *B, const CFGBlock *Prev) {
return BlockEdge(B, Prev, 0);
}
static BlockEdge NextEdge(const CFGBlock* B, const CFGBlock* Next) {
static BlockEdge NextEdge(const CFGBlock *B, const CFGBlock *Next) {
return BlockEdge(Next, B, 0);
}
};
@ -162,7 +162,7 @@ class DataflowSolver {
/// dataflow values using runOnCFG, as runOnBlock is intended to
/// only be used for querying the dataflow values within a block
/// with and Observer object.
void runOnBlock(const CFGBlock* B, bool recordStmtValues) {
void runOnBlock(const CFGBlock *B, bool recordStmtValues) {
BlockDataMapTy& M = D.getBlockDataMap();
typename BlockDataMapTy::iterator I = M.find(B);
@ -172,13 +172,13 @@ class DataflowSolver {
}
}
void runOnBlock(const CFGBlock& B, bool recordStmtValues) {
void runOnBlock(const CFGBlock &B, bool recordStmtValues) {
runOnBlock(&B, recordStmtValues);
}
void runOnBlock(CFG::iterator& I, bool recordStmtValues) {
void runOnBlock(CFG::iterator &I, bool recordStmtValues) {
runOnBlock(*I, recordStmtValues);
}
void runOnBlock(CFG::const_iterator& I, bool recordStmtValues) {
void runOnBlock(CFG::const_iterator &I, bool recordStmtValues) {
runOnBlock(*I, recordStmtValues);
}
@ -199,7 +199,7 @@ class DataflowSolver {
EnqueueBlocksOnWorklist(cfg, AnalysisDirTag());
while (!WorkList.isEmpty()) {
const CFGBlock* B = WorkList.dequeue();
const CFGBlock *B = WorkList.dequeue();
ProcessMerge(cfg, B);
ProcessBlock(B, recordStmtValues, AnalysisDirTag());
UpdateEdges(cfg, B, TF.getVal());
@ -222,7 +222,7 @@ class DataflowSolver {
WorkList.enqueue(&**I);
}
void ProcessMerge(CFG& cfg, const CFGBlock* B) {
void ProcessMerge(CFG& cfg, const CFGBlock *B) {
ValTy& V = TF.getVal();
TF.SetTopValue(V);
@ -270,7 +270,7 @@ class DataflowSolver {
}
/// ProcessBlock - Process the transfer functions for a given block.
void ProcessBlock(const CFGBlock* B, bool recordStmtValues,
void ProcessBlock(const CFGBlock *B, bool recordStmtValues,
dataflow::forward_analysis_tag) {
TF.setCurrentBlock(B);
@ -284,7 +284,7 @@ class DataflowSolver {
TF.VisitTerminator(const_cast<CFGBlock*>(B));
}
void ProcessBlock(const CFGBlock* B, bool recordStmtValues,
void ProcessBlock(const CFGBlock *B, bool recordStmtValues,
dataflow::backward_analysis_tag) {
TF.setCurrentBlock(B);
@ -298,12 +298,12 @@ class DataflowSolver {
}
}
void ProcessStmt(const Stmt* S, bool record, dataflow::forward_analysis_tag) {
void ProcessStmt(const Stmt *S, bool record, dataflow::forward_analysis_tag) {
if (record) D.getStmtDataMap()[S] = TF.getVal();
TF.BlockStmt_Visit(const_cast<Stmt*>(S));
}
void ProcessStmt(const Stmt* S, bool record, dataflow::backward_analysis_tag){
void ProcessStmt(const Stmt *S, bool record, dataflow::backward_analysis_tag){
TF.BlockStmt_Visit(const_cast<Stmt*>(S));
if (record) D.getStmtDataMap()[S] = TF.getVal();
}
@ -312,14 +312,14 @@ class DataflowSolver {
/// block, update the dataflow value associated with the block's
/// outgoing/incoming edges (depending on whether we do a
// forward/backward analysis respectively)
void UpdateEdges(CFG& cfg, const CFGBlock* B, ValTy& V) {
void UpdateEdges(CFG& cfg, const CFGBlock *B, ValTy& V) {
for (NextBItr I=ItrTraits::NextBegin(B), E=ItrTraits::NextEnd(B); I!=E; ++I)
if (CFGBlock *NextBlk = *I)
UpdateEdgeValue(ItrTraits::NextEdge(B, NextBlk),V, NextBlk);
}
/// UpdateEdgeValue - Update the value associated with a given edge.
void UpdateEdgeValue(BlockEdge E, ValTy& V, const CFGBlock* TargetBlock) {
void UpdateEdgeValue(BlockEdge E, ValTy& V, const CFGBlock *TargetBlock) {
EdgeDataMapTy& M = D.getEdgeDataMap();
typename EdgeDataMapTy::iterator I = M.find(E);

View File

@ -84,13 +84,13 @@ class DataflowValues {
/// getEdgeData - Retrieves the dataflow values associated with a
/// CFG edge.
ValTy& getEdgeData(const BlockEdge& E) {
ValTy& getEdgeData(const BlockEdge &E) {
typename EdgeDataMapTy::iterator I = EdgeDataMap.find(E);
assert (I != EdgeDataMap.end() && "No data associated with Edge.");
return I->second;
}
const ValTy& getEdgeData(const BlockEdge& E) const {
const ValTy& getEdgeData(const BlockEdge &E) const {
return reinterpret_cast<DataflowValues*>(this)->getEdgeData(E);
}
@ -98,13 +98,13 @@ class DataflowValues {
/// specified CFGBlock. If the dataflow analysis is a forward analysis,
/// this data is associated with the END of the block. If the analysis
/// is a backwards analysis, it is associated with the ENTRY of the block.
ValTy& getBlockData(const CFGBlock* B) {
ValTy& getBlockData(const CFGBlock *B) {
typename BlockDataMapTy::iterator I = BlockDataMap.find(B);
assert (I != BlockDataMap.end() && "No data associated with block.");
return I->second;
}
const ValTy& getBlockData(const CFGBlock* B) const {
const ValTy& getBlockData(const CFGBlock *B) const {
return const_cast<DataflowValues*>(this)->getBlockData(B);
}
@ -114,14 +114,14 @@ class DataflowValues {
/// If the analysis is a backwards analysis, it is associated with
/// the point after a Stmt. This data is only computed for block-level
/// expressions, and only when requested when the analysis is executed.
ValTy& getStmtData(const Stmt* S) {
ValTy& getStmtData(const Stmt *S) {
assert (StmtDataMap && "Dataflow values were not computed for statements.");
typename StmtDataMapTy::iterator I = StmtDataMap->find(S);
assert (I != StmtDataMap->end() && "No data associated with statement.");
return I->second;
}
const ValTy& getStmtData(const Stmt* S) const {
const ValTy& getStmtData(const Stmt *S) const {
return const_cast<DataflowValues*>(this)->getStmtData(S);
}

View File

@ -21,15 +21,18 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/Support/Casting.h"
#include "llvm/ADT/StringRef.h"
#include <cassert>
#include <utility>
#include <string>
namespace clang {
class LocationContext;
class AnalysisContext;
class FunctionDecl;
class LocationContext;
class ProgramPointTag;
class ProgramPoint {
public:
enum Kind { BlockEdgeKind,
@ -42,7 +45,6 @@ class ProgramPoint {
PreStoreKind,
PostStoreKind,
PostPurgeDeadSymbolsKind,
PostStmtCustomKind,
PostConditionKind,
PostLValueKind,
PostInitializerKind,
@ -58,25 +60,33 @@ class ProgramPoint {
// The LocationContext could be NULL to allow ProgramPoint to be used in
// context insensitive analysis.
const LocationContext *L;
const void *Tag;
const ProgramPointTag *Tag;
ProgramPoint();
protected:
ProgramPoint(const void* P, Kind k, const LocationContext *l,
const void *tag = 0)
ProgramPoint(const void *P, Kind k, const LocationContext *l,
const ProgramPointTag *tag = 0)
: Data(P, static_cast<const void*>(NULL)), K(k), L(l), Tag(tag) {}
ProgramPoint(const void* P1, const void* P2, Kind k, const LocationContext *l,
const void *tag = 0)
ProgramPoint(const void *P1, const void *P2, Kind k, const LocationContext *l,
const ProgramPointTag *tag = 0)
: Data(P1, P2), K(k), L(l), Tag(tag) {}
protected:
const void* getData1() const { return Data.first; }
const void* getData2() const { return Data.second; }
const void *getData1() const { return Data.first; }
const void *getData2() const { return Data.second; }
public:
/// Create a new ProgramPoint object that is the same as the original
/// except for using the specified tag value.
ProgramPoint withTag(const ProgramPointTag *tag) const {
return ProgramPoint(Data.first, Data.second, K, L, tag);
}
Kind getKind() const { return K; }
const void *getTag() const { return Tag; }
const ProgramPointTag *getTag() const { return Tag; }
const LocationContext *getLocationContext() const { return L; }
@ -93,7 +103,7 @@ class ProgramPoint {
return K == RHS.K && Data == RHS.Data && L == RHS.L && Tag == RHS.Tag;
}
bool operator!=(const ProgramPoint& RHS) const {
bool operator!=(const ProgramPoint &RHS) const {
return K != RHS.K || Data != RHS.Data || L != RHS.L || Tag != RHS.Tag;
}
@ -104,29 +114,30 @@ class ProgramPoint {
ID.AddPointer(L);
ID.AddPointer(Tag);
}
static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K,
const LocationContext *LC,
const ProgramPointTag *tag);
};
class BlockEntrance : public ProgramPoint {
public:
BlockEntrance(const CFGBlock* B, const LocationContext *L,
const void *tag = 0)
: ProgramPoint(B, BlockEntranceKind, L, tag) {}
BlockEntrance(const CFGBlock *B, const LocationContext *L,
const ProgramPointTag *tag = 0)
: ProgramPoint(B, BlockEntranceKind, L, tag) {
assert(B && "BlockEntrance requires non-null block");
}
const CFGBlock* getBlock() const {
const CFGBlock *getBlock() const {
return reinterpret_cast<const CFGBlock*>(getData1());
}
const CFGElement getFirstElement() const {
const CFGBlock* B = getBlock();
const CFGBlock *B = getBlock();
return B->empty() ? CFGElement() : B->front();
}
/// Create a new BlockEntrance object that is the same as the original
/// except for using the specified tag value.
BlockEntrance withTag(const void *tag) {
return BlockEntrance(getBlock(), getLocationContext(), tag);
}
static bool classof(const ProgramPoint* Location) {
return Location->getKind() == BlockEntranceKind;
}
@ -134,14 +145,14 @@ class BlockEntrance : public ProgramPoint {
class BlockExit : public ProgramPoint {
public:
BlockExit(const CFGBlock* B, const LocationContext *L)
BlockExit(const CFGBlock *B, const LocationContext *L)
: ProgramPoint(B, BlockExitKind, L) {}
const CFGBlock* getBlock() const {
const CFGBlock *getBlock() const {
return reinterpret_cast<const CFGBlock*>(getData1());
}
const Stmt* getTerminator() const {
const Stmt *getTerminator() const {
return getBlock()->getTerminator();
}
@ -153,7 +164,7 @@ class BlockExit : public ProgramPoint {
class StmtPoint : public ProgramPoint {
public:
StmtPoint(const Stmt *S, const void *p2, Kind k, const LocationContext *L,
const void *tag)
const ProgramPointTag *tag)
: ProgramPoint(S, p2, k, L, tag) {}
const Stmt *getStmt() const { return (const Stmt*) getData1(); }
@ -170,7 +181,7 @@ class StmtPoint : public ProgramPoint {
class PreStmt : public StmtPoint {
public:
PreStmt(const Stmt *S, const LocationContext *L, const void *tag,
PreStmt(const Stmt *S, const LocationContext *L, const ProgramPointTag *tag,
const Stmt *SubStmt = 0)
: StmtPoint(S, SubStmt, PreStmtKind, L, tag) {}
@ -183,16 +194,17 @@ class PreStmt : public StmtPoint {
class PostStmt : public StmtPoint {
protected:
PostStmt(const Stmt* S, const void* data, Kind k, const LocationContext *L,
const void *tag =0)
PostStmt(const Stmt *S, const void *data, Kind k, const LocationContext *L,
const ProgramPointTag *tag =0)
: StmtPoint(S, data, k, L, tag) {}
public:
explicit PostStmt(const Stmt* S, Kind k,
const LocationContext *L, const void *tag = 0)
explicit PostStmt(const Stmt *S, Kind k,
const LocationContext *L, const ProgramPointTag *tag = 0)
: StmtPoint(S, NULL, k, L, tag) {}
explicit PostStmt(const Stmt* S, const LocationContext *L,const void *tag = 0)
explicit PostStmt(const Stmt *S, const LocationContext *L,
const ProgramPointTag *tag = 0)
: StmtPoint(S, NULL, PostStmtKind, L, tag) {}
static bool classof(const ProgramPoint* Location) {
@ -201,31 +213,11 @@ class PostStmt : public StmtPoint {
}
};
class PostStmtCustom : public PostStmt {
public:
PostStmtCustom(const Stmt* S,
const std::pair<const void*, const void*>* TaggedData,\
const LocationContext *L)
: PostStmt(S, TaggedData, PostStmtCustomKind, L) {}
const std::pair<const void*, const void*>& getTaggedPair() const {
return
*reinterpret_cast<const std::pair<const void*, const void*>*>(getData2());
}
const void* getTag() const { return getTaggedPair().first; }
const void* getTaggedData() const { return getTaggedPair().second; }
static bool classof(const ProgramPoint* Location) {
return Location->getKind() == PostStmtCustomKind;
}
};
// PostCondition represents the post program point of a branch condition.
class PostCondition : public PostStmt {
public:
PostCondition(const Stmt* S, const LocationContext *L, const void *tag = 0)
PostCondition(const Stmt *S, const LocationContext *L,
const ProgramPointTag *tag = 0)
: PostStmt(S, PostConditionKind, L, tag) {}
static bool classof(const ProgramPoint* Location) {
@ -236,7 +228,7 @@ class PostCondition : public PostStmt {
class LocationCheck : public StmtPoint {
protected:
LocationCheck(const Stmt *S, const LocationContext *L,
ProgramPoint::Kind K, const void *tag)
ProgramPoint::Kind K, const ProgramPointTag *tag)
: StmtPoint(S, NULL, K, L, tag) {}
static bool classof(const ProgramPoint *location) {
@ -247,7 +239,8 @@ class LocationCheck : public StmtPoint {
class PreLoad : public LocationCheck {
public:
PreLoad(const Stmt *S, const LocationContext *L, const void *tag = 0)
PreLoad(const Stmt *S, const LocationContext *L,
const ProgramPointTag *tag = 0)
: LocationCheck(S, L, PreLoadKind, tag) {}
static bool classof(const ProgramPoint *location) {
@ -257,7 +250,8 @@ class PreLoad : public LocationCheck {
class PreStore : public LocationCheck {
public:
PreStore(const Stmt *S, const LocationContext *L, const void *tag = 0)
PreStore(const Stmt *S, const LocationContext *L,
const ProgramPointTag *tag = 0)
: LocationCheck(S, L, PreStoreKind, tag) {}
static bool classof(const ProgramPoint *location) {
@ -267,7 +261,8 @@ class PreStore : public LocationCheck {
class PostLoad : public PostStmt {
public:
PostLoad(const Stmt* S, const LocationContext *L, const void *tag = 0)
PostLoad(const Stmt *S, const LocationContext *L,
const ProgramPointTag *tag = 0)
: PostStmt(S, PostLoadKind, L, tag) {}
static bool classof(const ProgramPoint* Location) {
@ -277,7 +272,8 @@ class PostLoad : public PostStmt {
class PostStore : public PostStmt {
public:
PostStore(const Stmt* S, const LocationContext *L, const void *tag = 0)
PostStore(const Stmt *S, const LocationContext *L,
const ProgramPointTag *tag = 0)
: PostStmt(S, PostStoreKind, L, tag) {}
static bool classof(const ProgramPoint* Location) {
@ -287,7 +283,8 @@ class PostStore : public PostStmt {
class PostLValue : public PostStmt {
public:
PostLValue(const Stmt* S, const LocationContext *L, const void *tag = 0)
PostLValue(const Stmt *S, const LocationContext *L,
const ProgramPointTag *tag = 0)
: PostStmt(S, PostLValueKind, L, tag) {}
static bool classof(const ProgramPoint* Location) {
@ -297,8 +294,8 @@ class PostLValue : public PostStmt {
class PostPurgeDeadSymbols : public PostStmt {
public:
PostPurgeDeadSymbols(const Stmt* S, const LocationContext *L,
const void *tag = 0)
PostPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
const ProgramPointTag *tag = 0)
: PostStmt(S, PostPurgeDeadSymbolsKind, L, tag) {}
static bool classof(const ProgramPoint* Location) {
@ -308,14 +305,17 @@ class PostPurgeDeadSymbols : public PostStmt {
class BlockEdge : public ProgramPoint {
public:
BlockEdge(const CFGBlock* B1, const CFGBlock* B2, const LocationContext *L)
: ProgramPoint(B1, B2, BlockEdgeKind, L) {}
BlockEdge(const CFGBlock *B1, const CFGBlock *B2, const LocationContext *L)
: ProgramPoint(B1, B2, BlockEdgeKind, L) {
assert(B1 && "BlockEdge: source block must be non-null");
assert(B2 && "BlockEdge: destination block must be non-null");
}
const CFGBlock* getSrc() const {
const CFGBlock *getSrc() const {
return static_cast<const CFGBlock*>(getData1());
}
const CFGBlock* getDst() const {
const CFGBlock *getDst() const {
return static_cast<const CFGBlock*>(getData2());
}
@ -365,6 +365,29 @@ class CallExit : public StmtPoint {
}
};
/// ProgramPoints can be "tagged" as representing points specific to a given
/// analysis entity. Tags are abstract annotations, with an associated
/// description and potentially other information.
class ProgramPointTag {
public:
ProgramPointTag(void *tagKind = 0) : TagKind(tagKind) {}
virtual ~ProgramPointTag();
virtual StringRef getTagDescription() const = 0;
protected:
/// Used to implement 'classof' in subclasses.
const void *getTagKind() { return TagKind; }
private:
const void *TagKind;
};
class SimpleProgramPointTag : public ProgramPointTag {
std::string desc;
public:
SimpleProgramPointTag(StringRef description);
StringRef getTagDescription() const;
};
} // end namespace clang
@ -385,12 +408,12 @@ static inline clang::ProgramPoint getTombstoneKey() {
return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0);
}
static unsigned getHashValue(const clang::ProgramPoint& Loc) {
static unsigned getHashValue(const clang::ProgramPoint &Loc) {
return Loc.getHashValue();
}
static bool isEqual(const clang::ProgramPoint& L,
const clang::ProgramPoint& R) {
static bool isEqual(const clang::ProgramPoint &L,
const clang::ProgramPoint &R) {
return L == R;
}

View File

@ -62,16 +62,16 @@ struct DeclBitVector_Types {
AnalysisDataTy() : NDecls(0) {}
virtual ~AnalysisDataTy() {}
bool isTracked(const NamedDecl* SD) { return DMap.find(SD) != DMap.end(); }
bool isTracked(const NamedDecl *SD) { return DMap.find(SD) != DMap.end(); }
Idx getIdx(const NamedDecl* SD) const {
Idx getIdx(const NamedDecl *SD) const {
DMapTy::const_iterator I = DMap.find(SD);
return I == DMap.end() ? Idx() : Idx(I->second);
}
unsigned getNumDecls() const { return NDecls; }
void Register(const NamedDecl* SD) {
void Register(const NamedDecl *SD) {
if (!isTracked(SD)) DMap[SD] = NDecls++;
}
@ -117,11 +117,11 @@ struct DeclBitVector_Types {
}
llvm::BitVector::reference
operator()(const NamedDecl* ND, const AnalysisDataTy& AD) {
operator()(const NamedDecl *ND, const AnalysisDataTy& AD) {
return getBit(AD.getIdx(ND));
}
bool operator()(const NamedDecl* ND, const AnalysisDataTy& AD) const {
bool operator()(const NamedDecl *ND, const AnalysisDataTy& AD) const {
return getBit(AD.getIdx(ND));
}
@ -171,14 +171,14 @@ struct StmtDeclBitVector_Types {
//===--------------------------------------------------------------------===//
class AnalysisDataTy : public DeclBitVector_Types::AnalysisDataTy {
ASTContext* ctx;
ASTContext *ctx;
CFG* cfg;
public:
AnalysisDataTy() : ctx(0), cfg(0) {}
virtual ~AnalysisDataTy() {}
void setContext(ASTContext& c) { ctx = &c; }
ASTContext& getContext() {
void setContext(ASTContext &c) { ctx = &c; }
ASTContext &getContext() {
assert(ctx && "ASTContext should not be NULL.");
return *ctx;
}
@ -186,10 +186,10 @@ struct StmtDeclBitVector_Types {
void setCFG(CFG& c) { cfg = &c; }
CFG& getCFG() { assert(cfg && "CFG should not be NULL."); return *cfg; }
bool isTracked(const Stmt* S) { return cfg->isBlkExpr(S); }
bool isTracked(const Stmt *S) { return cfg->isBlkExpr(S); }
using DeclBitVector_Types::AnalysisDataTy::isTracked;
unsigned getIdx(const Stmt* S) const {
unsigned getIdx(const Stmt *S) const {
CFG::BlkExprNumTy I = cfg->getBlkExprNum(S);
assert(I && "Stmtession not tracked for bitvector.");
return I;
@ -248,11 +248,11 @@ struct StmtDeclBitVector_Types {
}
llvm::BitVector::reference
operator()(const Stmt* S, const AnalysisDataTy& AD) {
operator()(const Stmt *S, const AnalysisDataTy& AD) {
return BlkExprBV[AD.getIdx(S)];
}
const llvm::BitVector::reference
operator()(const Stmt* S, const AnalysisDataTy& AD) const {
operator()(const Stmt *S, const AnalysisDataTy& AD) const {
return const_cast<ValTy&>(*this)(S,AD);
}

View File

@ -28,8 +28,8 @@ static_cast<ImplClass*>(this)->Visit##CLASS##Decl( \
static_cast<CLASS##Decl*>(D)); \
break;
#define DEFAULT_DISPATCH(CLASS) void Visit##CLASS##Decl(CLASS##Decl* D) {}
#define DEFAULT_DISPATCH_VARDECL(CLASS) void Visit##CLASS##Decl(CLASS##Decl* D)\
#define DEFAULT_DISPATCH(CLASS) void Visit##CLASS##Decl(CLASS##Decl *D) {}
#define DEFAULT_DISPATCH_VARDECL(CLASS) void Visit##CLASS##Decl(CLASS##Decl *D)\
{ static_cast<ImplClass*>(this)->VisitVarDecl(D); }
@ -38,23 +38,23 @@ template <typename ImplClass>
class CFGRecStmtDeclVisitor : public CFGRecStmtVisitor<ImplClass> {
public:
void VisitDeclRefExpr(DeclRefExpr* DR) {
void VisitDeclRefExpr(DeclRefExpr *DR) {
static_cast<ImplClass*>(this)->VisitDecl(DR->getDecl());
}
void VisitDeclStmt(DeclStmt* DS) {
void VisitDeclStmt(DeclStmt *DS) {
for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
DI != DE; ++DI) {
Decl* D = *DI;
Decl *D = *DI;
static_cast<ImplClass*>(this)->VisitDecl(D);
// Visit the initializer.
if (VarDecl* VD = dyn_cast<VarDecl>(D))
if (Expr* I = VD->getInit())
if (VarDecl *VD = dyn_cast<VarDecl>(D))
if (Expr *I = VD->getInit())
static_cast<ImplClass*>(this)->Visit(I);
}
}
void VisitDecl(Decl* D) {
void VisitDecl(Decl *D) {
switch (D->getKind()) {
DISPATCH_CASE(Function)
DISPATCH_CASE(CXXMethod)
@ -69,7 +69,7 @@ class CFGRecStmtDeclVisitor : public CFGRecStmtVisitor<ImplClass> {
DISPATCH_CASE(UsingDirective)
DISPATCH_CASE(Using)
default:
assert(false && "Subtype of ScopedDecl not handled.");
llvm_unreachable("Subtype of ScopedDecl not handled.");
}
}

View File

@ -22,7 +22,7 @@ template <typename ImplClass>
class CFGRecStmtVisitor : public CFGStmtVisitor<ImplClass,void> {
public:
void VisitStmt(Stmt* S) {
void VisitStmt(Stmt *S) {
static_cast< ImplClass* >(this)->VisitChildren(S);
}
@ -45,13 +45,13 @@ break;
CONDVAR_CASE(WhileStmt)
#undef CONDVAR_CASE
default:
assert(false && "Infeasible");
llvm_unreachable("Infeasible");
}
static_cast<ImplClass*>(this)->Visit(CondVar->getInit());
}
// Defining operator() allows the visitor to be used as a C++ style functor.
void operator()(Stmt* S) { static_cast<ImplClass*>(this)->BlockStmt_Visit(S);}
void operator()(Stmt *S) { static_cast<ImplClass*>(this)->BlockStmt_Visit(S);}
};
} // end namespace clang

View File

@ -33,7 +33,7 @@ static_cast<ImplClass*>(this)->BlockStmt_Visit ## CLASS(static_cast<CLASS*>(S));
template <typename ImplClass, typename RetTy=void>
class CFGStmtVisitor : public StmtVisitor<ImplClass,RetTy> {
Stmt* CurrentBlkStmt;
Stmt *CurrentBlkStmt;
struct NullifyStmt {
Stmt*& S;
@ -45,9 +45,9 @@ class CFGStmtVisitor : public StmtVisitor<ImplClass,RetTy> {
public:
CFGStmtVisitor() : CurrentBlkStmt(NULL) {}
Stmt* getCurrentBlkStmt() const { return CurrentBlkStmt; }
Stmt *getCurrentBlkStmt() const { return CurrentBlkStmt; }
RetTy Visit(Stmt* S) {
RetTy Visit(Stmt *S) {
if (S == CurrentBlkStmt ||
!static_cast<ImplClass*>(this)->getCFG().isBlkExpr(S))
return StmtVisitor<ImplClass,RetTy>::Visit(S);
@ -67,7 +67,7 @@ class CFGStmtVisitor : public StmtVisitor<ImplClass,RetTy> {
/// the list of statements in a CFGBlock. For substatements, or when there
/// is no implementation provided for a BlockStmt_XXX method, we default
/// to using StmtVisitor's Visit method.
RetTy BlockStmt_Visit(Stmt* S) {
RetTy BlockStmt_Visit(Stmt *S) {
CurrentBlkStmt = S;
NullifyStmt cleanup(CurrentBlkStmt);
@ -106,23 +106,23 @@ class CFGStmtVisitor : public StmtVisitor<ImplClass,RetTy> {
DEFAULT_BLOCKSTMT_VISIT(ConditionalOperator)
DEFAULT_BLOCKSTMT_VISIT(BinaryConditionalOperator)
RetTy BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) {
RetTy BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(S);
}
RetTy BlockStmt_VisitCXXForRangeStmt(CXXForRangeStmt* S) {
RetTy BlockStmt_VisitCXXForRangeStmt(CXXForRangeStmt *S) {
return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(S);
}
RetTy BlockStmt_VisitImplicitControlFlowExpr(Expr* E) {
RetTy BlockStmt_VisitImplicitControlFlowExpr(Expr *E) {
return static_cast<ImplClass*>(this)->BlockStmt_VisitExpr(E);
}
RetTy BlockStmt_VisitExpr(Expr* E) {
RetTy BlockStmt_VisitExpr(Expr *E) {
return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(E);
}
RetTy BlockStmt_VisitStmt(Stmt* S) {
RetTy BlockStmt_VisitStmt(Stmt *S) {
return static_cast<ImplClass*>(this)->Visit(S);
}
@ -141,14 +141,14 @@ class CFGStmtVisitor : public StmtVisitor<ImplClass,RetTy> {
//===--------------------------------------------------------------------===//
/// VisitChildren: Call "Visit" on each child of S.
void VisitChildren(Stmt* S) {
void VisitChildren(Stmt *S) {
switch (S->getStmtClass()) {
default:
break;
case Stmt::StmtExprClass: {
CompoundStmt* CS = cast<StmtExpr>(S)->getSubStmt();
CompoundStmt *CS = cast<StmtExpr>(S)->getSubStmt();
if (CS->body_empty()) return;
static_cast<ImplClass*>(this)->Visit(CS->body_back());
return;

View File

@ -54,7 +54,9 @@ class ExprArgument<string name> : Argument<name>;
class FunctionArgument<string name> : Argument<name>;
class TypeArgument<string name> : Argument<name>;
class UnsignedArgument<string name> : Argument<name>;
class SourceLocArgument<string name> : Argument<name>;
class VariadicUnsignedArgument<string name> : Argument<name>;
class VariadicExprArgument<string name> : Argument<name>;
// A version of the form major.minor[.subminor].
class VersionArgument<string name> : Argument<name>;
@ -89,7 +91,9 @@ class Attr {
// The attribute will not be permitted in C++0x attribute-specifiers if
// this is empty; the empty string can be used as a namespace.
list<string> Namespaces = [];
// Any additional text that should be included verbatim in the class.
// Set to true for attributes with arguments which require delayed parsing.
bit LateParsed = 0;
// Any additional text that should be included verbatim in the class.
code AdditionalMembers = [{}];
}
@ -110,7 +114,7 @@ def Alias : InheritableAttr {
}
def Aligned : InheritableAttr {
let Spellings = ["align", "aligned"];
let Spellings = ["aligned"];
let Subjects = [NonBitField, NormalVar, Tag];
let Args = [AlignedArgument<"Alignment">];
let Namespaces = ["", "std"];
@ -128,7 +132,7 @@ def AnalyzerNoReturn : InheritableAttr {
let Spellings = ["analyzer_noreturn"];
}
def Annotate : InheritableAttr {
def Annotate : InheritableParamAttr {
let Spellings = ["annotate"];
let Args = [StringArgument<"Annotation">];
}
@ -167,6 +171,23 @@ def CDecl : InheritableAttr {
let Spellings = ["cdecl", "__cdecl"];
}
// cf_audited_transfer indicates that the given function has been
// audited and has been marked with the appropriate cf_consumed and
// cf_returns_retained attributes. It is generally applied by
// '#pragma clang arc_cf_code_audited' rather than explicitly.
def CFAuditedTransfer : InheritableAttr {
let Spellings = ["cf_audited_transfer"];
let Subjects = [Function];
}
// cf_unknown_transfer is an explicit opt-out of cf_audited_transfer.
// It indicates that the function has unknown or unautomatable
// transfer semantics.
def CFUnknownTransfer : InheritableAttr {
let Spellings = ["cf_unknown_transfer"];
let Subjects = [Function];
}
def CFReturnsRetained : InheritableAttr {
let Spellings = ["cf_returns_retained"];
let Subjects = [ObjCMethod, Function];
@ -284,7 +305,7 @@ def IBOutlet : InheritableAttr {
def IBOutletCollection : InheritableAttr {
let Spellings = ["iboutletcollection"];
let Args = [TypeArgument<"InterFace">];
let Args = [TypeArgument<"Interface">, SourceLocArgument<"InterfaceLoc">];
}
def Malloc : InheritableAttr {
@ -317,6 +338,10 @@ def Naked : InheritableAttr {
let Spellings = ["naked"];
}
def ReturnsTwice : InheritableAttr {
let Spellings = ["returns_twice"];
}
def NoCommon : InheritableAttr {
let Spellings = ["nocommon"];
}
@ -358,6 +383,12 @@ def NoThrow : InheritableAttr {
let Spellings = ["nothrow"];
}
def NSBridged : InheritableAttr {
let Spellings = ["ns_bridged"];
let Subjects = [Record];
let Args = [IdentifierArgument<"BridgedType">];
}
def NSReturnsRetained : InheritableAttr {
let Spellings = ["ns_returns_retained"];
let Subjects = [ObjCMethod, Function];
@ -405,6 +436,11 @@ def ObjCPreciseLifetime : Attr {
let Subjects = [Var];
}
def ObjCReturnsInnerPointer : Attr {
let Spellings = ["objc_returns_inner_pointer"];
let Subjects = [ObjCMethod];
}
def Overloadable : Attr {
let Spellings = ["overloadable"];
}
@ -533,3 +569,108 @@ def WeakRef : InheritableAttr {
def X86ForceAlignArgPointer : InheritableAttr {
let Spellings = [];
}
// C/C++ Thread safety attributes (e.g. for deadlock, data race checking)
def GuardedVar : InheritableAttr {
let Spellings = ["guarded_var"];
}
def PtGuardedVar : InheritableAttr {
let Spellings = ["pt_guarded_var"];
}
def Lockable : InheritableAttr {
let Spellings = ["lockable"];
}
def ScopedLockable : InheritableAttr {
let Spellings = ["scoped_lockable"];
}
def NoThreadSafetyAnalysis : InheritableAttr {
let Spellings = ["no_thread_safety_analysis"];
}
def GuardedBy : InheritableAttr {
let Spellings = ["guarded_by"];
let Args = [ExprArgument<"Arg">];
let LateParsed = 1;
}
def PtGuardedBy : InheritableAttr {
let Spellings = ["pt_guarded_by"];
let Args = [ExprArgument<"Arg">];
let LateParsed = 1;
}
def AcquiredAfter : InheritableAttr {
let Spellings = ["acquired_after"];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
}
def AcquiredBefore : InheritableAttr {
let Spellings = ["acquired_before"];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
}
def ExclusiveLockFunction : InheritableAttr {
let Spellings = ["exclusive_lock_function"];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
}
def SharedLockFunction : InheritableAttr {
let Spellings = ["shared_lock_function"];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
}
// The first argument is an integer or boolean value specifying the return value
// of a successful lock acquisition.
def ExclusiveTrylockFunction : InheritableAttr {
let Spellings = ["exclusive_trylock_function"];
let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">];
let LateParsed = 1;
}
// The first argument is an integer or boolean value specifying the return value
// of a successful lock acquisition.
def SharedTrylockFunction : InheritableAttr {
let Spellings = ["shared_trylock_function"];
let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">];
let LateParsed = 1;
}
def UnlockFunction : InheritableAttr {
let Spellings = ["unlock_function"];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
}
def LockReturned : InheritableAttr {
let Spellings = ["lock_returned"];
let Args = [ExprArgument<"Arg">];
let LateParsed = 1;
}
def LocksExcluded : InheritableAttr {
let Spellings = ["locks_excluded"];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
}
def ExclusiveLocksRequired : InheritableAttr {
let Spellings = ["exclusive_locks_required"];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
}
def SharedLocksRequired : InheritableAttr {
let Spellings = ["shared_locks_required"];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
}

View File

@ -35,6 +35,7 @@
// A -> "reference" to __builtin_va_list
// V -> Vector, following num elements and a base type.
// X -> _Complex, followed by the base type.
// Y -> ptrdiff_t
// P -> FILE
// J -> jmp_buf
// SJ -> sigjmp_buf
@ -76,6 +77,7 @@
// in that it accepts its arguments as a va_list rather than
// through an ellipsis
// e -> const, but only when -fmath-errno=0
// j -> returns_twice (like setjmp)
// FIXME: gcc has nonnull
#if defined(BUILTIN) && !defined(LIBBUILTIN)
@ -96,9 +98,9 @@ BUILTIN(__builtin_fabsl, "LdLd", "ncF")
BUILTIN(__builtin_fmod , "ddd" , "Fnc")
BUILTIN(__builtin_fmodf, "fff" , "Fnc")
BUILTIN(__builtin_fmodl, "LdLdLd", "Fnc")
BUILTIN(__builtin_frexp , "ddi*" , "Fnc")
BUILTIN(__builtin_frexpf, "ffi*" , "Fnc")
BUILTIN(__builtin_frexpl, "LdLdi*", "Fnc")
BUILTIN(__builtin_frexp , "ddi*" , "Fn")
BUILTIN(__builtin_frexpf, "ffi*" , "Fn")
BUILTIN(__builtin_frexpl, "LdLdi*", "Fn")
BUILTIN(__builtin_huge_val, "d", "nc")
BUILTIN(__builtin_huge_valf, "f", "nc")
BUILTIN(__builtin_huge_vall, "Ld", "nc")
@ -108,9 +110,9 @@ BUILTIN(__builtin_infl , "Ld" , "nc")
BUILTIN(__builtin_ldexp , "ddi" , "Fnc")
BUILTIN(__builtin_ldexpf, "ffi" , "Fnc")
BUILTIN(__builtin_ldexpl, "LdLdi", "Fnc")
BUILTIN(__builtin_modf , "ddd*" , "Fnc")
BUILTIN(__builtin_modff, "fff*" , "Fnc")
BUILTIN(__builtin_modfl, "LdLdLd*", "Fnc")
BUILTIN(__builtin_modf , "ddd*" , "Fn")
BUILTIN(__builtin_modff, "fff*" , "Fn")
BUILTIN(__builtin_modfl, "LdLdLd*", "Fn")
BUILTIN(__builtin_nan, "dcC*" , "ncF")
BUILTIN(__builtin_nanf, "fcC*" , "ncF")
BUILTIN(__builtin_nanl, "LdcC*", "ncF")
@ -233,9 +235,9 @@ BUILTIN(__builtin_nexttowardl, "LdLdLd", "Fnc")
BUILTIN(__builtin_remainder , "ddd", "Fnc")
BUILTIN(__builtin_remainderf, "fff", "Fnc")
BUILTIN(__builtin_remainderl, "LdLdLd", "Fnc")
BUILTIN(__builtin_remquo , "dddi*", "Fnc")
BUILTIN(__builtin_remquof, "fffi*", "Fnc")
BUILTIN(__builtin_remquol, "LdLdLdi*", "Fnc")
BUILTIN(__builtin_remquo , "dddi*", "Fn")
BUILTIN(__builtin_remquof, "fffi*", "Fn")
BUILTIN(__builtin_remquol, "LdLdLdi*", "Fn")
BUILTIN(__builtin_rint , "dd", "Fnc")
BUILTIN(__builtin_rintf, "ff", "Fnc")
BUILTIN(__builtin_rintl, "LdLd", "Fnc")
@ -388,7 +390,7 @@ BUILTIN(__builtin_constant_p, "i.", "nct")
BUILTIN(__builtin_classify_type, "i.", "nct")
BUILTIN(__builtin___CFStringMakeConstantString, "FC*cC*", "nc")
BUILTIN(__builtin___NSStringMakeConstantString, "FC*cC*", "nc")
BUILTIN(__builtin_va_start, "vA.", "n")
BUILTIN(__builtin_va_start, "vA.", "nt")
BUILTIN(__builtin_va_end, "vA", "n")
BUILTIN(__builtin_va_copy, "vAA", "n")
BUILTIN(__builtin_stdarg_start, "vA.", "n")
@ -426,7 +428,7 @@ BUILTIN(__builtin_return_address, "v*IUi", "n")
BUILTIN(__builtin_extract_return_addr, "v*v*", "n")
BUILTIN(__builtin_frame_address, "v*IUi", "n")
BUILTIN(__builtin_flt_rounds, "i", "nc")
BUILTIN(__builtin_setjmp, "iv**", "")
BUILTIN(__builtin_setjmp, "iv**", "j")
BUILTIN(__builtin_longjmp, "vv**i", "r")
BUILTIN(__builtin_unwind_init, "v", "")
BUILTIN(__builtin_eh_return_data_regno, "iIi", "nc")
@ -584,12 +586,21 @@ BUILTIN(__sync_swap_4, "iiD*i.", "n")
BUILTIN(__sync_swap_8, "LLiLLiD*LLi.", "n")
BUILTIN(__sync_swap_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__atomic_load, "v.", "t")
BUILTIN(__atomic_store, "v.", "t")
BUILTIN(__atomic_exchange, "v.", "t")
BUILTIN(__atomic_compare_exchange_strong, "v.", "t")
BUILTIN(__atomic_compare_exchange_weak, "v.", "t")
BUILTIN(__atomic_fetch_add, "v.", "t")
BUILTIN(__atomic_fetch_sub, "v.", "t")
BUILTIN(__atomic_fetch_and, "v.", "t")
BUILTIN(__atomic_fetch_or, "v.", "t")
BUILTIN(__atomic_fetch_xor, "v.", "t")
BUILTIN(__atomic_thread_fence, "vi", "n")
BUILTIN(__atomic_signal_fence, "vi", "n")
// Non-overloaded atomic builtins.
BUILTIN(__sync_synchronize, "v.", "n")
// LLVM instruction builtin [Clang extension].
BUILTIN(__builtin_llvm_memory_barrier,"vbbbbb", "n")
// GCC does not support these, they are a Clang extension.
BUILTIN(__sync_fetch_and_min, "iiD*i", "n")
BUILTIN(__sync_fetch_and_max, "iiD*i", "n")
@ -661,9 +672,26 @@ LIBBUILTIN(rindex, "c*cC*i", "f", "strings.h", ALL_LANGUAGES)
LIBBUILTIN(bzero, "vv*z", "f", "strings.h", ALL_LANGUAGES)
// POSIX unistd.h
LIBBUILTIN(_exit, "vi", "fr", "unistd.h", ALL_LANGUAGES)
LIBBUILTIN(vfork, "iJ", "fj", "unistd.h", ALL_LANGUAGES)
// POSIX setjmp.h
// In some systems setjmp is a macro that expands to _setjmp. We undefine
// it here to avoid having two identical LIBBUILTIN entries.
#undef setjmp
LIBBUILTIN(_setjmp, "iJ", "fj", "setjmp.h", ALL_LANGUAGES)
LIBBUILTIN(__sigsetjmp, "iJ", "fj", "setjmp.h", ALL_LANGUAGES)
LIBBUILTIN(setjmp, "iJ", "fj", "setjmp.h", ALL_LANGUAGES)
LIBBUILTIN(sigsetjmp, "iJ", "fj", "setjmp.h", ALL_LANGUAGES)
LIBBUILTIN(setjmp_syscall, "iJ", "fj", "setjmp.h", ALL_LANGUAGES)
LIBBUILTIN(savectx, "iJ", "fj", "setjmp.h", ALL_LANGUAGES)
LIBBUILTIN(qsetjmp, "iJ", "fj", "setjmp.h", ALL_LANGUAGES)
LIBBUILTIN(getcontext, "iJ", "fj", "setjmp.h", ALL_LANGUAGES)
LIBBUILTIN(_longjmp, "vJi", "fr", "setjmp.h", ALL_LANGUAGES)
LIBBUILTIN(siglongjmp, "vSJi", "fr", "setjmp.h", ALL_LANGUAGES)
// non-standard but very common
LIBBUILTIN(strlcpy, "zc*cC*z", "f", "string.h", ALL_LANGUAGES)
LIBBUILTIN(strlcat, "zc*cC*z", "f", "string.h", ALL_LANGUAGES)
// id objc_msgSend(id, SEL, ...)
LIBBUILTIN(objc_msgSend, "GGH.", "f", "objc/message.h", OBJC_LANG)
@ -687,8 +715,7 @@ LIBBUILTIN(objc_read_weak, "GG*", "f", "/objc/objc-auto.h", OBJC_LANG)
// id objc_assign_weak(id value, id *location)
LIBBUILTIN(objc_assign_weak, "GGG*", "f", "/objc/objc-auto.h", OBJC_LANG)
// id objc_assign_ivar(id value, id dest, ptrdiff_t offset)
// FIXME. Darwin has ptrdiff_t typedef'ed to int.
LIBBUILTIN(objc_assign_ivar, "GGGi", "f", "/objc/objc-auto.h", OBJC_LANG)
LIBBUILTIN(objc_assign_ivar, "GGGY", "f", "/objc/objc-auto.h", OBJC_LANG)
// id objc_assign_global(id val, id *dest)
LIBBUILTIN(objc_assign_global, "GGG*", "f", "/objc/objc-auto.h", OBJC_LANG)
// id objc_assign_strongCast(id val, id *dest
@ -738,5 +765,8 @@ LIBBUILTIN(_Block_object_assign, "vv*vC*iC", "f", "Blocks.h", ALL_LANGUAGES)
LIBBUILTIN(_Block_object_dispose, "vvC*iC", "f", "Blocks.h", ALL_LANGUAGES)
// FIXME: Also declare NSConcreteGlobalBlock and NSConcreteStackBlock.
// Annotation function
BUILTIN(__builtin_annotation, "UiUicC*", "nc")
#undef BUILTIN
#undef LIBBUILTIN

View File

@ -15,16 +15,13 @@
#ifndef LLVM_CLANG_BASIC_BUILTINS_H
#define LLVM_CLANG_BASIC_BUILTINS_H
#include "clang/Basic/LLVM.h"
#include <cstring>
// VC++ defines 'alloca' as an object-like macro, which interferes with our
// builtins.
#undef alloca
namespace llvm {
template <typename T> class SmallVectorImpl;
}
namespace clang {
class TargetInfo;
class IdentifierTable;
@ -65,15 +62,18 @@ class Context {
const Info *TSRecords;
unsigned NumTSRecords;
public:
Context(const TargetInfo &Target);
Context();
/// \brief Perform target-specific initialization
void InitializeTarget(const TargetInfo &Target);
/// InitializeBuiltins - Mark the identifiers for all the builtins with their
/// appropriate builtin ID # and mark any non-portable builtin identifiers as
/// such.
void InitializeBuiltins(IdentifierTable &Table, const LangOptions& LangOpts);
/// \brief Popular the vector with the names of all of the builtins.
void GetBuiltinNames(llvm::SmallVectorImpl<const char *> &Names,
void GetBuiltinNames(SmallVectorImpl<const char *> &Names,
bool NoBuiltins);
/// Builtin::GetName - Return the identifier name for the specified builtin,
@ -103,6 +103,11 @@ class Context {
return strchr(GetRecord(ID).Attributes, 'r') != 0;
}
/// isReturnsTwice - Return true if we know this builtin can return twice.
bool isReturnsTwice(unsigned ID) const {
return strchr(GetRecord(ID).Attributes, 'j') != 0;
}
/// isLibFunction - Return true if this is a builtin for a libc/libm function,
/// with a "__builtin_" prefix (e.g. __builtin_abs).
bool isLibFunction(unsigned ID) const {

View File

@ -74,3 +74,4 @@ def Friend : Decl;
def FriendTemplate : Decl;
def StaticAssert : Decl;
def Block : Decl, DeclContext;
def ClassScopeFunctionSpecialization : Decl;

View File

@ -15,6 +15,7 @@
#ifndef LLVM_CLANG_BASIC_DELAYEDCLEANUPPOOL_H
#define LLVM_CLANG_BASIC_DELAYEDCLEANUPPOOL_H
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
@ -66,7 +67,7 @@ class DelayedCleanupPool {
}
void doCleanup() {
for (llvm::SmallVector<std::pair<void *, CleanupFn>, 8>::reverse_iterator
for (SmallVector<std::pair<void *, CleanupFn>, 8>::reverse_iterator
I = Cleanups.rbegin(), E = Cleanups.rend(); I != E; ++I)
I->second(I->first);
Cleanups.clear();
@ -79,7 +80,7 @@ class DelayedCleanupPool {
private:
llvm::DenseMap<void *, CleanupFn> Ptrs;
llvm::SmallVector<std::pair<void *, CleanupFn>, 8> Cleanups;
SmallVector<std::pair<void *, CleanupFn>, 8> Cleanups;
template <typename T>
static void cleanupWithDelete(void *ptr) {

View File

@ -16,6 +16,7 @@
#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/OwningPtr.h"
@ -25,7 +26,7 @@
#include <list>
namespace clang {
class DiagnosticClient;
class DiagnosticConsumer;
class DiagnosticBuilder;
class IdentifierInfo;
class DeclContext;
@ -64,7 +65,7 @@ class FixItHint {
/// \brief Create a code modification hint that inserts the given
/// code string at a specific location.
static FixItHint CreateInsertion(SourceLocation InsertionLoc,
llvm::StringRef Code) {
StringRef Code) {
FixItHint Hint;
Hint.RemoveRange =
CharSourceRange(SourceRange(InsertionLoc, InsertionLoc), false);
@ -86,7 +87,7 @@ class FixItHint {
/// \brief Create a code modification hint that replaces the given
/// source range with the given code string.
static FixItHint CreateReplacement(CharSourceRange RemoveRange,
llvm::StringRef Code) {
StringRef Code) {
FixItHint Hint;
Hint.RemoveRange = RemoveRange;
Hint.CodeToInsert = Code;
@ -94,17 +95,17 @@ class FixItHint {
}
static FixItHint CreateReplacement(SourceRange RemoveRange,
llvm::StringRef Code) {
StringRef Code) {
return CreateReplacement(CharSourceRange::getTokenRange(RemoveRange), Code);
}
};
/// Diagnostic - This concrete class is used by the front-end to report
/// DiagnosticsEngine - This concrete class is used by the front-end to report
/// problems and issues. It massages the diagnostics (e.g. handling things like
/// "report warnings as errors" and passes them off to the DiagnosticClient for
/// reporting to the user. Diagnostic is tied to one translation unit and
/// one SourceManager.
class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
/// "report warnings as errors" and passes them off to the DiagnosticConsumer
/// for reporting to the user. DiagnosticsEngine is tied to one translation unit
/// and one SourceManager.
class DiagnosticsEngine : public llvm::RefCountedBase<DiagnosticsEngine> {
public:
/// Level - The level of the diagnostic, after it has been through mapping.
enum Level {
@ -148,7 +149,8 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
private:
unsigned char AllExtensionsSilenced; // Used by __extension__
bool IgnoreAllWarnings; // Ignore all warnings: -w
bool WarningsAsErrors; // Treat warnings like errors:
bool WarningsAsErrors; // Treat warnings like errors.
bool EnableAllWarnings; // Enable all warnings.
bool ErrorsAsFatal; // Treat errors like fatal errors.
bool SuppressSystemWarnings; // Suppress warnings in system headers.
bool SuppressAllDiagnostics; // Suppress all diagnostics.
@ -158,7 +160,7 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
// 0 -> no limit.
ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors?
llvm::IntrusiveRefCntPtr<DiagnosticIDs> Diags;
DiagnosticClient *Client;
DiagnosticConsumer *Client;
bool OwnsDiagClient;
SourceManager *SourceMgr;
@ -173,22 +175,22 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
/// the state so that we know what is the diagnostic state at any given
/// source location.
class DiagState {
llvm::DenseMap<unsigned, unsigned> DiagMap;
llvm::DenseMap<unsigned, DiagnosticMappingInfo> DiagMap;
public:
typedef llvm::DenseMap<unsigned, unsigned>::const_iterator iterator;
typedef llvm::DenseMap<unsigned, DiagnosticMappingInfo>::iterator
iterator;
typedef llvm::DenseMap<unsigned, DiagnosticMappingInfo>::const_iterator
const_iterator;
void setMapping(diag::kind Diag, unsigned Map) { DiagMap[Diag] = Map; }
diag::Mapping getMapping(diag::kind Diag) const {
iterator I = DiagMap.find(Diag);
if (I != DiagMap.end())
return (diag::Mapping)I->second;
return diag::Mapping();
void setMappingInfo(diag::kind Diag, DiagnosticMappingInfo Info) {
DiagMap[Diag] = Info;
}
iterator begin() const { return DiagMap.begin(); }
iterator end() const { return DiagMap.end(); }
DiagnosticMappingInfo &getOrAddMappingInfo(diag::kind Diag);
const_iterator begin() const { return DiagMap.begin(); }
const_iterator end() const { return DiagMap.end(); }
};
/// \brief Keeps and automatically disposes all DiagStates that we create.
@ -254,10 +256,10 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
/// \brief Indicates that an unrecoverable error has occurred.
bool UnrecoverableErrorOccurred;
/// \brief Toggles for DiagnosticErrorTrap to check whether an error occurred
/// \brief Counts for DiagnosticErrorTrap to check whether an error occurred
/// during a parsing section, e.g. during parsing a function.
bool TrapErrorOccurred;
bool TrapUnrecoverableErrorOccurred;
unsigned TrapNumErrorsOccurred;
unsigned TrapNumUnrecoverableErrorsOccurred;
/// LastDiagLevel - This is the level of the last diagnostic emitted. This is
/// used to emit continuation diagnostics with the same level as the
@ -283,9 +285,9 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
const char *Argument, unsigned ArgumentLen,
const ArgumentValue *PrevArgs,
unsigned NumPrevArgs,
llvm::SmallVectorImpl<char> &Output,
SmallVectorImpl<char> &Output,
void *Cookie,
llvm::SmallVectorImpl<intptr_t> &QualTypeVals);
SmallVectorImpl<intptr_t> &QualTypeVals);
void *ArgToStringCookie;
ArgToStringFnTy ArgToStringFn;
@ -301,21 +303,25 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
std::string DelayedDiagArg2;
public:
explicit Diagnostic(const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &Diags,
DiagnosticClient *client = 0,
explicit DiagnosticsEngine(
const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &Diags,
DiagnosticConsumer *client = 0,
bool ShouldOwnClient = true);
~Diagnostic();
~DiagnosticsEngine();
const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &getDiagnosticIDs() const {
return Diags;
}
DiagnosticClient *getClient() { return Client; }
const DiagnosticClient *getClient() const { return Client; }
DiagnosticConsumer *getClient() { return Client; }
const DiagnosticConsumer *getClient() const { return Client; }
/// \brief Determine whether this \c DiagnosticsEngine object own its client.
bool ownsClient() const { return OwnsDiagClient; }
/// \brief Return the current diagnostic client along with ownership of that
/// client.
DiagnosticClient *takeClient() {
DiagnosticConsumer *takeClient() {
OwnsDiagClient = false;
return Client;
}
@ -328,8 +334,8 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
void setSourceManager(SourceManager *SrcMgr) { SourceMgr = SrcMgr; }
//===--------------------------------------------------------------------===//
// Diagnostic characterization methods, used by a client to customize how
// diagnostics are emitted.
// DiagnosticsEngine characterization methods, used by a client to customize
// how diagnostics are emitted.
//
/// pushMappings - Copies the current DiagMappings and pushes the new copy
@ -346,7 +352,7 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
///
/// \param ShouldOwnClient true if the diagnostic object should take
/// ownership of \c client.
void setClient(DiagnosticClient *client, bool ShouldOwnClient = true);
void setClient(DiagnosticConsumer *client, bool ShouldOwnClient = true);
/// setErrorLimit - Specify a limit for the number of errors we should
/// emit before giving up. Zero disables the limit.
@ -369,6 +375,12 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
void setIgnoreAllWarnings(bool Val) { IgnoreAllWarnings = Val; }
bool getIgnoreAllWarnings() const { return IgnoreAllWarnings; }
/// setEnableAllWarnings - When set to true, any unmapped ignored warnings
/// are no longer ignored. If this and IgnoreAllWarnings are both set,
/// then that one wins.
void setEnableAllWarnings(bool Val) { EnableAllWarnings = Val; }
bool getEnableAllWarnngs() const { return EnableAllWarnings; }
/// setWarningsAsErrors - When set to true, any warnings reported are issued
/// as errors.
void setWarningsAsErrors(bool Val) { WarningsAsErrors = Val; }
@ -435,10 +447,20 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
///
/// 'Loc' is the source location that this change of diagnostic state should
/// take affect. It can be null if we are setting the state from command-line.
bool setDiagnosticGroupMapping(llvm::StringRef Group, diag::Mapping Map,
SourceLocation Loc = SourceLocation()) {
return Diags->setDiagnosticGroupMapping(Group, Map, Loc, *this);
}
bool setDiagnosticGroupMapping(StringRef Group, diag::Mapping Map,
SourceLocation Loc = SourceLocation());
/// \brief Set the warning-as-error flag for the given diagnostic group. This
/// function always only operates on the current diagnostic state.
///
/// \returns True if the given group is unknown, false otherwise.
bool setDiagnosticGroupWarningAsError(StringRef Group, bool Enabled);
/// \brief Set the error-as-fatal flag for the given diagnostic group. This
/// function always only operates on the current diagnostic state.
///
/// \returns True if the given group is unknown, false otherwise.
bool setDiagnosticGroupErrorAsFatal(StringRef Group, bool Enabled);
bool hasErrorOccurred() const { return ErrorOccurred; }
bool hasFatalErrorOccurred() const { return FatalErrorOccurred; }
@ -457,7 +479,7 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
/// getCustomDiagID - Return an ID for a diagnostic with the specified message
/// and level. If this is the first request for this diagnosic, it is
/// registered and created, otherwise the existing ID is returned.
unsigned getCustomDiagID(Level L, llvm::StringRef Message) {
unsigned getCustomDiagID(Level L, StringRef Message) {
return Diags->getCustomDiagID((DiagnosticIDs::Level)L, Message);
}
@ -467,8 +489,8 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
const char *Modifier, unsigned ModLen,
const char *Argument, unsigned ArgLen,
const ArgumentValue *PrevArgs, unsigned NumPrevArgs,
llvm::SmallVectorImpl<char> &Output,
llvm::SmallVectorImpl<intptr_t> &QualTypeVals) const {
SmallVectorImpl<char> &Output,
SmallVectorImpl<intptr_t> &QualTypeVals) const {
ArgToStringFn(Kind, Val, Modifier, ModLen, Argument, ArgLen,
PrevArgs, NumPrevArgs, Output, ArgToStringCookie,
QualTypeVals);
@ -484,18 +506,17 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
void Reset();
//===--------------------------------------------------------------------===//
// Diagnostic classification and reporting interfaces.
// DiagnosticsEngine classification and reporting interfaces.
//
/// \brief Based on the way the client configured the Diagnostic
/// \brief Based on the way the client configured the DiagnosticsEngine
/// object, classify the specified diagnostic ID into a Level, consumable by
/// the DiagnosticClient.
/// the DiagnosticConsumer.
///
/// \param Loc The source location we are interested in finding out the
/// diagnostic state. Can be null in order to query the latest state.
Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
diag::Mapping *mapping = 0) const {
return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this, mapping);
Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc) const {
return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this);
}
/// Report - Issue the message to the client. @c DiagID is a member of the
@ -527,13 +548,13 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
///
/// \param Arg1 A string argument that will be provided to the
/// diagnostic. A copy of this string will be stored in the
/// Diagnostic object itself.
/// DiagnosticsEngine object itself.
///
/// \param Arg2 A string argument that will be provided to the
/// diagnostic. A copy of this string will be stored in the
/// Diagnostic object itself.
void SetDelayedDiagnostic(unsigned DiagID, llvm::StringRef Arg1 = "",
llvm::StringRef Arg2 = "");
/// DiagnosticsEngine object itself.
void SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1 = "",
StringRef Arg2 = "");
/// \brief Clear out the current diagnostic.
void Clear() { CurDiagID = ~0U; }
@ -542,23 +563,6 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
/// \brief Report the delayed diagnostic.
void ReportDelayed();
/// getDiagnosticMappingInfo - Return the mapping info currently set for the
/// specified builtin diagnostic. This returns the high bit encoding, or zero
/// if the field is completely uninitialized.
diag::Mapping getDiagnosticMappingInfo(diag::kind Diag,
DiagState *State) const {
return State->getMapping(Diag);
}
void setDiagnosticMappingInternal(unsigned DiagId, unsigned Map,
DiagState *State,
bool isUser, bool isPragma) const {
if (isUser) Map |= 8; // Set the high bit for user mappings.
if (isPragma) Map |= 0x10; // Set the bit for diagnostic pragma mappings.
State->setMapping((diag::kind)DiagId, Map);
}
// This is private state used by DiagnosticBuilder. We put it here instead of
// in DiagnosticBuilder in order to keep DiagnosticBuilder a small lightweight
// object. This implementation choice means that we can only have one
@ -567,7 +571,7 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
// diagnostic is in flight at a time.
friend class DiagnosticIDs;
friend class DiagnosticBuilder;
friend class DiagnosticInfo;
friend class Diagnostic;
friend class PartialDiagnostic;
friend class DiagnosticErrorTrap;
@ -614,7 +618,7 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
/// only support 10 ranges, could easily be extended if needed.
CharSourceRange DiagRanges[10];
enum { MaxFixItHints = 3 };
enum { MaxFixItHints = 6 };
/// FixItHints - If valid, provides a hint with some code
/// to insert, remove, or modify at a particular position.
@ -637,28 +641,30 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
/// between the time the instance was created and the time it was
/// queried.
class DiagnosticErrorTrap {
Diagnostic &Diag;
DiagnosticsEngine &Diag;
unsigned NumErrors;
unsigned NumUnrecoverableErrors;
public:
explicit DiagnosticErrorTrap(Diagnostic &Diag)
explicit DiagnosticErrorTrap(DiagnosticsEngine &Diag)
: Diag(Diag) { reset(); }
/// \brief Determine whether any errors have occurred since this
/// object instance was created.
bool hasErrorOccurred() const {
return Diag.TrapErrorOccurred;
return Diag.TrapNumErrorsOccurred > NumErrors;
}
/// \brief Determine whether any unrecoverable errors have occurred since this
/// object instance was created.
bool hasUnrecoverableErrorOccurred() const {
return Diag.TrapUnrecoverableErrorOccurred;
return Diag.TrapNumUnrecoverableErrorsOccurred > NumUnrecoverableErrors;
}
// Set to initial state of "no errors occurred".
void reset() {
Diag.TrapErrorOccurred = false;
Diag.TrapUnrecoverableErrorOccurred = false;
NumErrors = Diag.TrapNumErrorsOccurred;
NumUnrecoverableErrors = Diag.TrapNumUnrecoverableErrorsOccurred;
}
};
@ -667,9 +673,9 @@ class DiagnosticErrorTrap {
//===----------------------------------------------------------------------===//
/// DiagnosticBuilder - This is a little helper class used to produce
/// diagnostics. This is constructed by the Diagnostic::Report method, and
/// allows insertion of extra information (arguments and source ranges) into the
/// currently "in flight" diagnostic. When the temporary for the builder is
/// diagnostics. This is constructed by the DiagnosticsEngine::Report method,
/// and allows insertion of extra information (arguments and source ranges) into
/// the currently "in flight" diagnostic. When the temporary for the builder is
/// destroyed, the diagnostic is issued.
///
/// Note that many of these will be created as temporary objects (many call
@ -678,12 +684,12 @@ class DiagnosticErrorTrap {
/// the common fields to registers, eliminating increments of the NumArgs field,
/// for example.
class DiagnosticBuilder {
mutable Diagnostic *DiagObj;
mutable DiagnosticsEngine *DiagObj;
mutable unsigned NumArgs, NumRanges, NumFixItHints;
void operator=(const DiagnosticBuilder&); // DO NOT IMPLEMENT
friend class Diagnostic;
explicit DiagnosticBuilder(Diagnostic *diagObj)
friend class DiagnosticsEngine;
explicit DiagnosticBuilder(DiagnosticsEngine *diagObj)
: DiagObj(diagObj), NumArgs(0), NumRanges(0), NumFixItHints(0) {}
friend class PartialDiagnostic;
@ -731,7 +737,7 @@ class DiagnosticBuilder {
///
/// \pre \c isActive()
unsigned getDiagID() const {
assert(isActive() && "Diagnostic is inactive");
assert(isActive() && "DiagnosticsEngine is inactive");
return DiagObj->CurDiagID;
}
@ -743,17 +749,17 @@ class DiagnosticBuilder {
/// return Diag(...);
operator bool() const { return true; }
void AddString(llvm::StringRef S) const {
assert(NumArgs < Diagnostic::MaxArguments &&
void AddString(StringRef S) const {
assert(NumArgs < DiagnosticsEngine::MaxArguments &&
"Too many arguments to diagnostic!");
if (DiagObj) {
DiagObj->DiagArgumentsKind[NumArgs] = Diagnostic::ak_std_string;
DiagObj->DiagArgumentsKind[NumArgs] = DiagnosticsEngine::ak_std_string;
DiagObj->DiagArgumentsStr[NumArgs++] = S;
}
}
void AddTaggedVal(intptr_t V, Diagnostic::ArgumentKind Kind) const {
assert(NumArgs < Diagnostic::MaxArguments &&
void AddTaggedVal(intptr_t V, DiagnosticsEngine::ArgumentKind Kind) const {
assert(NumArgs < DiagnosticsEngine::MaxArguments &&
"Too many arguments to diagnostic!");
if (DiagObj) {
DiagObj->DiagArgumentsKind[NumArgs] = Kind;
@ -770,15 +776,17 @@ class DiagnosticBuilder {
}
void AddFixItHint(const FixItHint &Hint) const {
assert(NumFixItHints < Diagnostic::MaxFixItHints &&
assert(NumFixItHints < DiagnosticsEngine::MaxFixItHints &&
"Too many fix-it hints!");
if (NumFixItHints >= DiagnosticsEngine::MaxFixItHints)
return; // Don't crash in release builds
if (DiagObj)
DiagObj->FixItHints[NumFixItHints++] = Hint;
}
};
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
llvm::StringRef S) {
StringRef S) {
DB.AddString(S);
return DB;
}
@ -786,30 +794,30 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
const char *Str) {
DB.AddTaggedVal(reinterpret_cast<intptr_t>(Str),
Diagnostic::ak_c_string);
DiagnosticsEngine::ak_c_string);
return DB;
}
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, int I) {
DB.AddTaggedVal(I, Diagnostic::ak_sint);
DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint);
return DB;
}
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,bool I) {
DB.AddTaggedVal(I, Diagnostic::ak_sint);
DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint);
return DB;
}
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
unsigned I) {
DB.AddTaggedVal(I, Diagnostic::ak_uint);
DB.AddTaggedVal(I, DiagnosticsEngine::ak_uint);
return DB;
}
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
const IdentifierInfo *II) {
DB.AddTaggedVal(reinterpret_cast<intptr_t>(II),
Diagnostic::ak_identifierinfo);
DiagnosticsEngine::ak_identifierinfo);
return DB;
}
@ -823,7 +831,7 @@ typename llvm::enable_if<llvm::is_same<T, DeclContext>,
const DiagnosticBuilder &>::type
operator<<(const DiagnosticBuilder &DB, T *DC) {
DB.AddTaggedVal(reinterpret_cast<intptr_t>(DC),
Diagnostic::ak_declcontext);
DiagnosticsEngine::ak_declcontext);
return DB;
}
@ -848,33 +856,33 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
/// Report - Issue the message to the client. DiagID is a member of the
/// diag::kind enum. This actually returns a new instance of DiagnosticBuilder
/// which emits the diagnostics (through ProcessDiag) when it is destroyed.
inline DiagnosticBuilder Diagnostic::Report(SourceLocation Loc,
inline DiagnosticBuilder DiagnosticsEngine::Report(SourceLocation Loc,
unsigned DiagID){
assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!");
CurDiagLoc = Loc;
CurDiagID = DiagID;
return DiagnosticBuilder(this);
}
inline DiagnosticBuilder Diagnostic::Report(unsigned DiagID) {
inline DiagnosticBuilder DiagnosticsEngine::Report(unsigned DiagID) {
return Report(SourceLocation(), DiagID);
}
//===----------------------------------------------------------------------===//
// DiagnosticInfo
// Diagnostic
//===----------------------------------------------------------------------===//
/// DiagnosticInfo - This is a little helper class (which is basically a smart
/// pointer that forward info from Diagnostic) that allows clients to enquire
/// about the currently in-flight diagnostic.
class DiagnosticInfo {
const Diagnostic *DiagObj;
llvm::StringRef StoredDiagMessage;
/// Diagnostic - This is a little helper class (which is basically a smart
/// pointer that forward info from DiagnosticsEngine) that allows clients to
/// enquire about the currently in-flight diagnostic.
class Diagnostic {
const DiagnosticsEngine *DiagObj;
StringRef StoredDiagMessage;
public:
explicit DiagnosticInfo(const Diagnostic *DO) : DiagObj(DO) {}
DiagnosticInfo(const Diagnostic *DO, llvm::StringRef storedDiagMessage)
explicit Diagnostic(const DiagnosticsEngine *DO) : DiagObj(DO) {}
Diagnostic(const DiagnosticsEngine *DO, StringRef storedDiagMessage)
: DiagObj(DO), StoredDiagMessage(storedDiagMessage) {}
const Diagnostic *getDiags() const { return DiagObj; }
const DiagnosticsEngine *getDiags() const { return DiagObj; }
unsigned getID() const { return DiagObj->CurDiagID; }
const SourceLocation &getLocation() const { return DiagObj->CurDiagLoc; }
bool hasSourceManager() const { return DiagObj->hasSourceManager(); }
@ -884,49 +892,49 @@ class DiagnosticInfo {
/// getArgKind - Return the kind of the specified index. Based on the kind
/// of argument, the accessors below can be used to get the value.
Diagnostic::ArgumentKind getArgKind(unsigned Idx) const {
DiagnosticsEngine::ArgumentKind getArgKind(unsigned Idx) const {
assert(Idx < getNumArgs() && "Argument index out of range!");
return (Diagnostic::ArgumentKind)DiagObj->DiagArgumentsKind[Idx];
return (DiagnosticsEngine::ArgumentKind)DiagObj->DiagArgumentsKind[Idx];
}
/// getArgStdStr - Return the provided argument string specified by Idx.
const std::string &getArgStdStr(unsigned Idx) const {
assert(getArgKind(Idx) == Diagnostic::ak_std_string &&
assert(getArgKind(Idx) == DiagnosticsEngine::ak_std_string &&
"invalid argument accessor!");
return DiagObj->DiagArgumentsStr[Idx];
}
/// getArgCStr - Return the specified C string argument.
const char *getArgCStr(unsigned Idx) const {
assert(getArgKind(Idx) == Diagnostic::ak_c_string &&
assert(getArgKind(Idx) == DiagnosticsEngine::ak_c_string &&
"invalid argument accessor!");
return reinterpret_cast<const char*>(DiagObj->DiagArgumentsVal[Idx]);
}
/// getArgSInt - Return the specified signed integer argument.
int getArgSInt(unsigned Idx) const {
assert(getArgKind(Idx) == Diagnostic::ak_sint &&
assert(getArgKind(Idx) == DiagnosticsEngine::ak_sint &&
"invalid argument accessor!");
return (int)DiagObj->DiagArgumentsVal[Idx];
}
/// getArgUInt - Return the specified unsigned integer argument.
unsigned getArgUInt(unsigned Idx) const {
assert(getArgKind(Idx) == Diagnostic::ak_uint &&
assert(getArgKind(Idx) == DiagnosticsEngine::ak_uint &&
"invalid argument accessor!");
return (unsigned)DiagObj->DiagArgumentsVal[Idx];
}
/// getArgIdentifier - Return the specified IdentifierInfo argument.
const IdentifierInfo *getArgIdentifier(unsigned Idx) const {
assert(getArgKind(Idx) == Diagnostic::ak_identifierinfo &&
assert(getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo &&
"invalid argument accessor!");
return reinterpret_cast<IdentifierInfo*>(DiagObj->DiagArgumentsVal[Idx]);
}
/// getRawArg - Return the specified non-string argument in an opaque form.
intptr_t getRawArg(unsigned Idx) const {
assert(getArgKind(Idx) != Diagnostic::ak_std_string &&
assert(getArgKind(Idx) != DiagnosticsEngine::ak_std_string &&
"invalid argument accessor!");
return DiagObj->DiagArgumentsVal[Idx];
}
@ -959,12 +967,12 @@ class DiagnosticInfo {
/// FormatDiagnostic - Format this diagnostic into a string, substituting the
/// formal arguments into the %0 slots. The result is appended onto the Str
/// array.
void FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const;
void FormatDiagnostic(SmallVectorImpl<char> &OutStr) const;
/// FormatDiagnostic - Format the given format-string into the
/// output buffer using the arguments stored in this diagnostic.
void FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
llvm::SmallVectorImpl<char> &OutStr) const;
SmallVectorImpl<char> &OutStr) const;
};
/**
@ -973,7 +981,7 @@ class DiagnosticInfo {
*/
class StoredDiagnostic {
unsigned ID;
Diagnostic::Level Level;
DiagnosticsEngine::Level Level;
FullSourceLoc Loc;
std::string Message;
std::vector<CharSourceRange> Ranges;
@ -981,18 +989,22 @@ class StoredDiagnostic {
public:
StoredDiagnostic();
StoredDiagnostic(Diagnostic::Level Level, const DiagnosticInfo &Info);
StoredDiagnostic(Diagnostic::Level Level, unsigned ID,
llvm::StringRef Message);
StoredDiagnostic(DiagnosticsEngine::Level Level, const Diagnostic &Info);
StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
StringRef Message);
StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
StringRef Message, FullSourceLoc Loc,
ArrayRef<CharSourceRange> Ranges,
ArrayRef<FixItHint> Fixits);
~StoredDiagnostic();
/// \brief Evaluates true when this object stores a diagnostic.
operator bool() const { return Message.size() > 0; }
unsigned getID() const { return ID; }
Diagnostic::Level getLevel() const { return Level; }
DiagnosticsEngine::Level getLevel() const { return Level; }
const FullSourceLoc &getLocation() const { return Loc; }
llvm::StringRef getMessage() const { return Message; }
StringRef getMessage() const { return Message; }
void setLocation(FullSourceLoc Loc) { this->Loc = Loc; }
@ -1007,20 +1019,20 @@ class StoredDiagnostic {
unsigned fixit_size() const { return FixIts.size(); }
};
/// DiagnosticClient - This is an abstract interface implemented by clients of
/// DiagnosticConsumer - This is an abstract interface implemented by clients of
/// the front-end, which formats and prints fully processed diagnostics.
class DiagnosticClient {
class DiagnosticConsumer {
protected:
unsigned NumWarnings; // Number of warnings reported
unsigned NumErrors; // Number of errors reported
public:
DiagnosticClient() : NumWarnings(0), NumErrors(0) { }
DiagnosticConsumer() : NumWarnings(0), NumErrors(0) { }
unsigned getNumErrors() const { return NumErrors; }
unsigned getNumWarnings() const { return NumWarnings; }
virtual ~DiagnosticClient();
virtual ~DiagnosticConsumer();
/// BeginSourceFile - Callback to inform the diagnostic client that processing
/// of a source file is beginning.
@ -1043,8 +1055,8 @@ class DiagnosticClient {
/// IncludeInDiagnosticCounts - This method (whose default implementation
/// returns true) indicates whether the diagnostics handled by this
/// DiagnosticClient should be included in the number of diagnostics reported
/// by Diagnostic.
/// DiagnosticConsumer should be included in the number of diagnostics
/// reported by DiagnosticsEngine.
virtual bool IncludeInDiagnosticCounts() const;
/// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
@ -1052,8 +1064,24 @@ class DiagnosticClient {
///
/// Default implementation just keeps track of the total number of warnings
/// and errors.
virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
const DiagnosticInfo &Info);
virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
const Diagnostic &Info);
/// \brief Clone the diagnostic consumer, producing an equivalent consumer
/// that can be used in a different context.
virtual DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const = 0;
};
/// IgnoringDiagConsumer - This is a diagnostic client that just ignores all
/// diags.
class IgnoringDiagConsumer : public DiagnosticConsumer {
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
const Diagnostic &Info) {
// Just ignore it.
}
DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const {
return new IgnoringDiagConsumer();
}
};
} // end namespace clang

View File

@ -18,8 +18,6 @@ def MAP_IGNORE : DiagMapping;
def MAP_WARNING : DiagMapping;
def MAP_ERROR : DiagMapping;
def MAP_FATAL : DiagMapping;
def MAP_WARNING_NO_WERROR : DiagMapping;
def MAP_WARNING_SHOW_IN_SYSTEM_HEADER : DiagMapping;
// Define the diagnostic classes.
class DiagClass;
@ -59,6 +57,8 @@ class Diagnostic<string text, DiagClass DC, DiagMapping defaultmapping> {
DiagClass Class = DC;
bit SFINAE = 1;
bit AccessControl = 0;
bit WarningNoWerror = 0;
bit WarningShowInSystemHeader = 0;
DiagMapping DefaultMapping = defaultmapping;
DiagGroup Group;
string CategoryName = "";
@ -77,9 +77,11 @@ class DefaultIgnore { DiagMapping DefaultMapping = MAP_IGNORE; }
class DefaultWarn { DiagMapping DefaultMapping = MAP_WARNING; }
class DefaultError { DiagMapping DefaultMapping = MAP_ERROR; }
class DefaultFatal { DiagMapping DefaultMapping = MAP_FATAL; }
class DefaultWarnNoWerror { DiagMapping DefaultMapping= MAP_WARNING_NO_WERROR; }
class DefaultWarnNoWerror {
bit WarningNoWerror = 1;
}
class DefaultWarnShowInSystemHeader {
DiagMapping DefaultMapping = MAP_WARNING_SHOW_IN_SYSTEM_HEADER;
bit WarningShowInSystemHeader = 1;
}
class NoSFINAE { bit SFINAE = 0; }

View File

@ -57,6 +57,10 @@ def note_odr_number_of_bases : Note<
def note_odr_enumerator : Note<"enumerator %0 with value %1 here">;
def note_odr_missing_enumerator : Note<"no corresponding enumerator here">;
def err_odr_field_type_inconsistent : Error<
"field %0 declared with incompatible types in different "
"translation units (%1 vs. %2)">;
// Importing Objective-C ASTs
def err_odr_ivar_type_inconsistent : Error<
"instance variable %0 declared with incompatible types in different "

View File

@ -52,18 +52,31 @@ def err_invalid_storage_class_in_func_decl : Error<
"invalid storage class specifier in function declarator">;
def err_expected_namespace_name : Error<"expected namespace name">;
def ext_variadic_templates : ExtWarn<
"variadic templates are a C++0x extension">, InGroup<CXX0x>;
"variadic templates are a C++11 extension">, InGroup<CXX11>;
def warn_cxx98_compat_variadic_templates :
Warning<"variadic templates are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
def err_default_special_members : Error<
"only special member functions may be defaulted">;
def err_friends_define_only_namespace_scope : Error<
"cannot define a function with non-namespace scope in a friend declaration">;
def err_deleted_non_function : Error<
"only functions can have deleted definitions">;
def err_module_not_found : Error<"module '%0' not found">, DefaultFatal;
def err_module_not_built : Error<"could not build module '%0'">, DefaultFatal;
def err_module_cycle : Error<"cyclic dependency in module '%0': %1">,
DefaultFatal;
def warn_module_build : Warning<"building module '%0' from source">,
InGroup<ModuleBuild>, DefaultIgnore;
def note_pragma_entered_here : Note<"#pragma entered here">;
// Sema && Lex
def ext_longlong : Extension<
"'long long' is an extension when C99 mode is not enabled">,
InGroup<LongLong>;
def warn_cxx98_compat_longlong : Warning<
"'long long' is incompatible with C++98">,
InGroup<CXX98CompatPedantic>, DefaultIgnore;
def warn_integer_too_large : Warning<
"integer constant is too large for its type">;
def warn_integer_too_large_for_signed : Warning<

View File

@ -65,6 +65,9 @@ def err_drv_command_signalled : Error<
"%0 command failed due to signal %1 (use -v to see invocation)">;
def err_drv_invalid_mfloat_abi : Error<
"invalid float ABI '%0'">;
def err_drv_invalid_libcxx_deployment : Error<
"invalid deployment target for -stdlib=libc++ (requires %0 or later)">;
def err_drv_I_dash_not_supported : Error<
"'%0' not supported, please use -iquote instead">;
def err_drv_unknown_argument : Error<"unknown argument: '%0'">;
@ -123,4 +126,7 @@ def warn_drv_objc_gc_unsupported : Warning<
def warn_drv_pch_not_first_include : Warning<
"precompiled header '%0' was ignored because '%1' is not first '-include'">;
def note_drv_command_failed_diag_msg : Note<
"diagnostic msg: %0">;
}

View File

@ -112,139 +112,11 @@ def err_relocatable_without_isysroot : Error<
def warn_pch_target_triple : Error<
"PCH file was compiled for the target '%0' but the current translation "
"unit is being compiled for target '%1'">;
def warn_pch_c99 : Error<
"C99 support was %select{disabled|enabled}0 in PCH file but is "
"currently %select{disabled|enabled}1">;
def warn_pch_c1x : Error<
"C1X support was %select{disabled|enabled}0 in PCH file but is "
"currently %select{disabled|enabled}1">;
def warn_pch_cplusplus : Error<
"C++ support was %select{disabled|enabled}0 in PCH file but is "
"currently %select{disabled|enabled}1">;
def warn_pch_cplusplus0x : Error<
"C++0x support was %select{disabled|enabled}0 in PCH file but is "
"currently %select{disabled|enabled}1">;
def warn_pch_objective_c : Error<
"Objective-C support was %select{disabled|enabled}0 in PCH file but is "
"currently %select{disabled|enabled}1">;
def warn_pch_objective_c2 : Error<
"Objective-C 2.0 support was %select{disabled|enabled}0 in PCH file but "
"is currently %select{disabled|enabled}1">;
def warn_pch_nonfragile_abi : Error<
"PCH file was compiled with the %select{32-bit|non-fragile}0 Objective-C "
"ABI but the %select{32-bit|non-fragile}1 Objective-C ABI is selected">;
def warn_pch_nonfragile_abi2 : Error<
"PCH file was compiled with the %select{32-bit|enhanced non-fragile}0 "
"Objective-C ABI but the %select{32-bit|enhanced non-fragile}1 "
"Objective-C ABI is selected">;
def warn_pch_auto_ref_count : Error<
"PCH file was compiled %select{without|with} automated reference counting,"
"which is currently %select{disabled|enabled}">;
def warn_pch_apple_kext : Error<
"PCH file was compiled %select{with|without}0 support for Apple's kernel "
"extensions ABI but it is currently %select{disabled|enabled}1">;
def warn_pch_objc_auto_properties : Error<
"PCH file was compiled %select{with|without}0 support for auto-synthesized "
"@properties but it is currently %select{disabled|enabled}1">;
def warn_pch_no_constant_cfstrings : Error<
"Objctive-C NSstring generation support was %select{disabled|enabled}0 "
"in PCH file but currently %select{disabled|enabled}1">;
def warn_pch_extensions : Error<
"extensions were %select{enabled|disabled}0 in PCH file but are "
"currently %select{enabled|disabled}1">;
def warn_pch_gnu_extensions : Error<
"GNU extensions were %select{disabled|enabled}0 in PCH file but are "
"currently %select{disabled|enabled}1">;
def warn_pch_gnu_keywords : Error<
"GNU keywords were %select{disabled|enabled}0 in PCH file but are "
"currently %select{disabled|enabled}1">;
def warn_pch_microsoft_extensions : Error<
"Microsoft extensions were %select{disabled|enabled}0 in PCH file but are "
"currently %select{disabled|enabled}1">;
def warn_pch_ms_bitfields : Error<
"Microsoft-compatible structure layout was %select{disabled|enabled}0 in "
"PCH file but is currently %select{disabled|enabled}1">;
def warn_pch_heinous_extensions : Error<
"heinous extensions were %select{disabled|enabled}0 in PCH file but are "
"currently %select{disabled|enabled}1">;
def warn_pch_lax_vector_conversions : Error<
"lax vector conversions were %select{disabled|enabled}0 in PCH file but "
"are currently %select{disabled|enabled}1">;
def warn_pch_altivec : Error<
"AltiVec initializers were %select{disabled|enabled}0 in PCH file but "
"are currently %select{disabled|enabled}1">;
def warn_pch_opencl : Error<
"OpenCL language extensions were %select{disabled|enabled}0 in PCH file "
"but are currently %select{disabled|enabled}1">;
def warn_pch_cuda : Error<
"CUDA language extensions were %select{disabled|enabled}0 in PCH file "
"but are currently %select{disabled|enabled}1">;
def warn_pch_elide_constructors : Error<
"Elidable copy constructors were %select{disabled|enabled}0 in PCH file "
"but are currently %select{disabled|enabled}1">;
def warn_pch_exceptions : Error<
"exceptions were %select{disabled|enabled}0 in PCH file but "
"are currently %select{disabled|enabled}1">;
def warn_pch_objc_exceptions : Error<
"Objective-C exceptions were %select{disabled|enabled}0 in PCH file but "
"are currently %select{disabled|enabled}1">;
def warn_pch_cxx_exceptions : Error<
"C++ exceptions were %select{disabled|enabled}0 in PCH file but "
"are currently %select{disabled|enabled}1">;
def warn_pch_sjlj_exceptions : Error<
"sjlj-exceptions were %select{disabled|enabled}0 in PCH file but "
"are currently %select{disabled|enabled}1">;
def warn_pch_objc_runtime : Error<
"PCH file was compiled with the %select{NeXT|GNU}0 runtime but the "
"%select{NeXT|GNU}1 runtime is selected">;
def warn_pch_freestanding : Error<
"PCH file was compiled with a %select{hosted|freestanding}0 "
"implementation but a %select{hosted|freestanding}1 implementation "
"is selected">;
def warn_pch_builtins : Error<
"PCH file was compiled with builtins %select{enabled|disabled}0 but "
"builtins are currently %select{enabled|disabled}1">;
def warn_pch_thread_safe_statics : Error<
"PCH file was compiled %select{without|with}0 thread-safe statics but "
"thread-safe statics are currently %select{disabled|enabled}1">;
def warn_pch_posix_threads : Error<
"PCH file was compiled %select{without|with}0 POSIX thread support but "
"POSIX threads are currently %select{disabled|enabled}1">;
def warn_pch_stack_protector : Error<
"stack protector was %select{off|on|required}0 in PCH file but "
"is currently %select{off|on|required}1">;
def warn_pch_blocks : Error<
"blocks were %select{disabled|enabled}0 in PCH file but "
"are currently %select{disabled|enabled}1">;
def warn_pch_math_errno : Error<
"math functions %select{do not respect|respect}0 'errno' in PCH "
"file but they are currently set to %select{not respect|respect}1 "
"'errno'">;
def warn_pch_optimize : Error<
"the macro '__OPTIMIZE__' was %select{not defined|defined}0 in "
"the PCH file but is currently %select{undefined|defined}1">;
def warn_pch_optimize_size : Error<
"the macro '__OPTIMIZE_SIZE__' was %select{not defined|defined}0 in "
"the PCH file but is currently %select{undefined|defined}1">;
def warn_pch_static : Error<
"the PCH file was compiled %select{dynamic|static}0 but the "
"current translation unit is being compiled as %select{dynamic|static}1">;
def warn_pch_pic_level : Error<
"PCH file was compiled with PIC level %0, but the current translation "
"unit will be compiled with PIC level %1">;
def warn_pch_gnu_inline : Error<
"PCH file was compiled with %select{C99|GNU|}0 inline semantics but "
"%select{C99|GNU}1 inline semantics are currently selected">;
def warn_pch_no_inline : Error<
"the macro '__NO_INLINE__' was %select{not defined|defined}0 in "
"the PCH file but is currently %select{undefined|defined}1">;
def warn_pch_deprecated : Error<
"the macro '__DEPRECATED' was %select{not defined|defined}0 in "
"the PCH file but is currently %select{undefined|defined}1">;
def warn_pch_gc_mode : Error<
"the PCH file was built with %select{no||hybrid}0 garbage collection but "
"the current translation unit will compiled with %select{no||hybrid}1 "
"garbage collection">;
def err_pch_langopt_mismatch : Error<"%0 was %select{disabled|enabled}1 in "
"PCH file but is currently %select{disabled|enabled}2">;
def err_pch_langopt_value_mismatch : Error<
"%0 differs in PCH file vs. current file">;
def warn_pch_version_too_old : Error<
"PCH file uses an older PCH format that is no longer supported">;
def warn_pch_version_too_new : Error<
@ -266,18 +138,6 @@ def warn_macro_name_used_in_pch : Error<
def warn_pch_compiler_options_mismatch : Error<
"compiler options used when building the precompiled header differ from "
"the options used when using the precompiled header">;
def warn_pch_access_control : Error<
"C++ access control was %select{disabled|enabled}0 in the PCH file but "
"is currently %select{disabled|enabled}1">;
def warn_pch_char_signed : Error<
"char was %select{unsigned|signed}0 in the PCH file but "
"is currently %select{unsigned|signed}1">;
def warn_pch_short_wchar : Error<
"-fshort-wchar was %select{disabled|enabled}0 in the PCH file but "
"is currently %select{disabled|enabled}1">;
def warn_pch_short_enums : Error<
"-fshort-enums was %select{disabled|enabled}0 in the PCH file but "
"is currently %select{disabled|enabled}1">;
def err_not_a_pch_file : Error<
"'%0' does not appear to be a precompiled header file">, DefaultFatal;
@ -291,6 +151,11 @@ def warn_unknown_warning_specifier : Warning<
"unknown %0 warning specifier: '%1'">,
InGroup<DiagGroup<"unknown-warning-option"> >;
def warn_unkwown_analyzer_checker : Warning<
def warn_unknown_analyzer_checker : Warning<
"no analyzer checkers are associated with '%0'">;
def warn_incompatible_analyzer_plugin_api : Warning<
"checker plugin '%0' is not compatible with this version of the analyzer">,
InGroup<DiagGroup<"analyzer-incompatible-plugin"> >;
def note_incompatible_analyzer_plugin_api : Note<
"current API version is '%0', but plugin was compiled with version '%1'">;
}

View File

@ -54,9 +54,16 @@ def ExtraTokens : DiagGroup<"extra-tokens">;
def FormatExtraArgs : DiagGroup<"format-extra-args">;
def FormatZeroLength : DiagGroup<"format-zero-length">;
def CXXHexFloats : DiagGroup<"c++-hex-floats">;
def CXX98Compat : DiagGroup<"c++98-compat">;
// Warnings for C++11 features which are Extensions in C++98 mode.
def CXX98CompatPedantic : DiagGroup<"c++98-compat-pedantic", [CXX98Compat]>;
def CXX11Narrowing : DiagGroup<"c++11-narrowing">;
def : DiagGroup<"c++0x-narrowing", [CXX11Narrowing]>;
def CXX11Compat : DiagGroup<"c++11-compat", [CXX11Narrowing]>;
def : DiagGroup<"c++0x-compat", [CXX11Compat]>;
def : DiagGroup<"c++0x-compat", [CXXHexFloats]>;
def : DiagGroup<"effc++">;
def ExitTimeDestructors : DiagGroup<"exit-time-destructors">;
def FourByteMultiChar : DiagGroup<"four-char-constants">;
@ -66,13 +73,15 @@ def BitwiseOpParentheses: DiagGroup<"bitwise-op-parentheses">;
def LogicalOpParentheses: DiagGroup<"logical-op-parentheses">;
def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">;
def : DiagGroup<"import">;
def IncompatiblePointerTypes : DiagGroup<"incompatible-pointer-types">;
def : DiagGroup<"init-self">;
def : DiagGroup<"inline">;
def : DiagGroup<"int-to-pointer-cast">;
def : DiagGroup<"invalid-pch">;
def LiteralRange : DiagGroup<"literal-range">;
def LocalTypeTemplateArgs : DiagGroup<"local-type-template-args">;
def : DiagGroup<"main">;
def MalformedWarningCheck : DiagGroup<"malformed-warning-check">;
def Main : DiagGroup<"main">;
def MissingBraces : DiagGroup<"missing-braces">;
def MissingDeclarations: DiagGroup<"missing-declarations">;
def : DiagGroup<"missing-format-attribute">;
@ -84,6 +93,7 @@ def : DiagGroup<"newline-eof">;
def LongLong : DiagGroup<"long-long">;
def MismatchedTags : DiagGroup<"mismatched-tags">;
def MissingFieldInitializers : DiagGroup<"missing-field-initializers">;
def ModuleBuild : DiagGroup<"module-build">;
def NullDereference : DiagGroup<"null-dereference">;
def InitializerOverrides : DiagGroup<"initializer-overrides">;
def NonNull : DiagGroup<"nonnull">;
@ -95,6 +105,9 @@ def OutOfLineDeclaration : DiagGroup<"out-of-line-declaration">;
def : DiagGroup<"overflow">;
def OverlengthStrings : DiagGroup<"overlength-strings">;
def OverloadedVirtual : DiagGroup<"overloaded-virtual">;
def ObjCMissingSuperCalls : DiagGroup<"objc-missing-super-calls">;
def ObjCRetainBlockProperty : DiagGroup<"objc-noncopy-retain-block-property">;
def ObjCContinuationPropertyType :DiagGroup<"objc-continuation-property-type">;
def Packed : DiagGroup<"packed">;
def Padded : DiagGroup<"padded">;
def PointerArith : DiagGroup<"pointer-arith">;
@ -108,6 +121,8 @@ def ReturnType : DiagGroup<"return-type">;
def BindToTemporaryCopy : DiagGroup<"bind-to-temporary-copy">;
def SelfAssignment : DiagGroup<"self-assign">;
def SemiBeforeMethodBody : DiagGroup<"semicolon-before-method-body">;
def Sentinel : DiagGroup<"sentinel">;
def MissingMethodReturnType : DiagGroup<"missing-method-return-type">;
def : DiagGroup<"sequence-point">;
def Shadow : DiagGroup<"shadow">;
def : DiagGroup<"shorten-64-to-32">;
@ -152,6 +167,7 @@ def UnknownPragmas : DiagGroup<"unknown-pragmas">;
def UnknownAttributes : DiagGroup<"attributes">;
def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args">;
def UnusedArgument : DiagGroup<"unused-argument">;
def UnusedComparison : DiagGroup<"unused-comparison">;
def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">;
def UnneededInternalDecl : DiagGroup<"unneeded-internal-declaration">;
def UnneededMemberFunction : DiagGroup<"unneeded-member-function">;
@ -160,9 +176,11 @@ def UnusedMemberFunction : DiagGroup<"unused-member-function",
[UnneededMemberFunction]>;
def UnusedLabel : DiagGroup<"unused-label">;
def UnusedParameter : DiagGroup<"unused-parameter">;
def UnusedValue : DiagGroup<"unused-value">;
def UnusedResult : DiagGroup<"unused-result">;
def UnusedValue : DiagGroup<"unused-value", [UnusedComparison, UnusedResult]>;
def UnusedVariable : DiagGroup<"unused-variable">;
def UsedButMarkedUnused : DiagGroup<"used-but-marked-unused">;
def UserDefinedLiterals : DiagGroup<"user-defined-literals">;
def ReadOnlySetterAttrs : DiagGroup<"readonly-setter-attrs">;
def Reorder : DiagGroup<"reorder">;
def UndeclaredSelector : DiagGroup<"undeclared-selector">;
@ -183,6 +201,7 @@ def Selector : DiagGroup<"selector">;
def NonfragileAbi2 : DiagGroup<"nonfragile-abi2">;
def Protocol : DiagGroup<"protocol">;
def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">;
def OverridingMethodMismatch : DiagGroup<"overriding-method-mismatch">;
def : DiagGroup<"variadic-macros">;
def VariadicMacros : DiagGroup<"variadic-macros">;
def VectorConversions : DiagGroup<"vector-conversions">; // clang specific
@ -202,9 +221,11 @@ def DuplicateArgDecl : DiagGroup<"duplicate-method-arg">;
// missing parentheses; it is off by default. We do not include it
// in -Wparentheses because most users who use -Wparentheses explicitly
// do not want these warnings.
def ParenthesesOnEquality : DiagGroup<"parentheses-equality">;
def Parentheses : DiagGroup<"parentheses",
[LogicalOpParentheses,
BitwiseOpParentheses]>;
BitwiseOpParentheses,
ParenthesesOnEquality]>;
// -Wconversion has its own warnings, but we split a few out for
// legacy reasons:
@ -216,6 +237,7 @@ def Conversion : DiagGroup<"conversion",
[DiagGroup<"shorten-64-to-32">,
DiagGroup<"constant-conversion">,
DiagGroup<"literal-conversion">,
DiagGroup<"string-conversion">,
DiagGroup<"sign-conversion">,
BoolConversions]>,
DiagCategory<"Value Conversion Issue">;
@ -228,11 +250,12 @@ def Unused : DiagGroup<"unused",
DiagCategory<"Unused Entity Issue">;
// Format settings.
def FormatInvalidSpecifier : DiagGroup<"format-invalid-specifier">;
def FormatSecurity : DiagGroup<"format-security">;
def FormatY2K : DiagGroup<"format-y2k">;
def Format : DiagGroup<"format",
[FormatExtraArgs, FormatZeroLength, NonNull,
FormatSecurity, FormatY2K]>,
FormatSecurity, FormatY2K, FormatInvalidSpecifier]>,
DiagCategory<"Format String Issue">;
def FormatNonLiteral : DiagGroup<"format-nonliteral", [FormatSecurity]>;
def Format2 : DiagGroup<"format=2",
@ -243,6 +266,7 @@ def Extra : DiagGroup<"extra", [
IgnoredQualifiers,
InitializerOverrides,
SemiBeforeMethodBody,
MissingMethodReturnType,
SignCompare,
UnusedParameter
]>;
@ -265,12 +289,15 @@ def Most : DiagGroup<"most", [
Uninitialized,
UnknownPragmas,
Unused,
VectorConversions,
VolatileRegisterVar,
ObjCMissingSuperCalls,
OverloadedVirtual
]>;
// -Wall is -Wmost -Wparentheses
// Thread Safety warnings
def ThreadSafety : DiagGroup<"thread-safety">;
// -Wall is -Wmost -Wparentheses -Wtop-level-comparison
def : DiagGroup<"all", [Most, Parentheses]>;
// Aliases.
@ -283,14 +310,16 @@ def : DiagGroup<"comments", [Comment]>; // -Wcomments = -Wcomment
def NonGCC : DiagGroup<"non-gcc",
[SignCompare, Conversion, LiteralRange]>;
// A warning group for warnings about using C++0x features as extensions in
// A warning group for warnings about using C++11 features as extensions in
// earlier C++ versions.
def CXX0xStaticNonIntegralInitializer :
DiagGroup<"c++0x-static-nonintegral-init">;
def CXX0x : DiagGroup<"c++0x-extensions", [CXX0xStaticNonIntegralInitializer]>;
def CXX11 : DiagGroup<"c++11-extensions">;
def : DiagGroup<"c++0x-extensions", [CXX11]>;
def DelegatingCtorCycles :
DiagGroup<"delegating-ctor-cycles">;
// A warning group for warnings about using C1X features as extensions.
def C1X : DiagGroup<"c1x-extensions">;
// A warning group for warnings about GCC extensions.
def GNU : DiagGroup<"gnu", [GNUDesignator, VLA]>;
@ -299,3 +328,4 @@ def Microsoft : DiagGroup<"microsoft">;
def ObjCNonUnifiedException : DiagGroup<"objc-nonunified-exceptions">;
def ObjCProtocolMethodImpl : DiagGroup<"objc-protocol-method-implementation">;

View File

@ -16,10 +16,16 @@
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/StringRef.h"
#include "clang/Basic/LLVM.h"
namespace llvm {
template<typename T, unsigned> class SmallVector;
}
namespace clang {
class Diagnostic;
class DiagnosticsEngine;
class SourceLocation;
struct WarningOption;
// Import the diagnostic enums themselves.
namespace diag {
@ -43,7 +49,7 @@ namespace clang {
// Get typedefs for common diagnostics.
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
SFINAE,ACCESS,CATEGORY,BRIEF,FULL) ENUM,
SFINAE,ACCESS,CATEGORY,NOWERROR,SHOWINSYSHEADER,BRIEF,FULL) ENUM,
#include "clang/Basic/DiagnosticCommonKinds.inc"
NUM_BUILTIN_COMMON_DIAGNOSTICS
#undef DIAG
@ -59,20 +65,47 @@ namespace clang {
MAP_IGNORE = 1, //< Map this diagnostic to nothing, ignore it.
MAP_WARNING = 2, //< Map this diagnostic to a warning.
MAP_ERROR = 3, //< Map this diagnostic to an error.
MAP_FATAL = 4, //< Map this diagnostic to a fatal error.
/// Map this diagnostic to "warning", but make it immune to -Werror. This
/// happens when you specify -Wno-error=foo.
MAP_WARNING_NO_WERROR = 5,
/// Map this diagnostic to "warning", but make it immune to
/// -Wno-system-headers.
MAP_WARNING_SHOW_IN_SYSTEM_HEADER = 6,
/// Map this diagnostic to "error", but make it immune to -Wfatal-errors.
/// This happens for -Wno-fatal-errors=foo.
MAP_ERROR_NO_WFATAL = 7
MAP_FATAL = 4 //< Map this diagnostic to a fatal error.
};
}
class DiagnosticMappingInfo {
unsigned Mapping : 3;
unsigned IsUser : 1;
unsigned IsPragma : 1;
unsigned HasShowInSystemHeader : 1;
unsigned HasNoWarningAsError : 1;
unsigned HasNoErrorAsFatal : 1;
public:
static DiagnosticMappingInfo Make(diag::Mapping Mapping, bool IsUser,
bool IsPragma) {
DiagnosticMappingInfo Result;
Result.Mapping = Mapping;
Result.IsUser = IsUser;
Result.IsPragma = IsPragma;
Result.HasShowInSystemHeader = 0;
Result.HasNoWarningAsError = 0;
Result.HasNoErrorAsFatal = 0;
return Result;
}
diag::Mapping getMapping() const { return diag::Mapping(Mapping); }
void setMapping(diag::Mapping Value) { Mapping = Value; }
bool isUser() const { return IsUser; }
bool isPragma() const { return IsPragma; }
bool hasShowInSystemHeader() const { return HasShowInSystemHeader; }
void setShowInSystemHeader(bool Value) { HasShowInSystemHeader = Value; }
bool hasNoWarningAsError() const { return HasNoWarningAsError; }
void setNoWarningAsError(bool Value) { HasNoWarningAsError = Value; }
bool hasNoErrorAsFatal() const { return HasNoErrorAsFatal; }
void setNoErrorAsFatal(bool Value) { HasNoErrorAsFatal = Value; }
};
/// \brief Used for handling and querying diagnostic IDs. Can be used and shared
/// by multiple Diagnostics for multiple translation units.
class DiagnosticIDs : public llvm::RefCountedBase<DiagnosticIDs> {
@ -93,7 +126,7 @@ class DiagnosticIDs : public llvm::RefCountedBase<DiagnosticIDs> {
/// getCustomDiagID - Return an ID for a diagnostic with the specified message
/// and level. If this is the first request for this diagnosic, it is
/// registered and created, otherwise the existing ID is returned.
unsigned getCustomDiagID(Level L, llvm::StringRef Message);
unsigned getCustomDiagID(Level L, StringRef Message);
//===--------------------------------------------------------------------===//
// Diagnostic classification and reporting interfaces.
@ -101,14 +134,18 @@ class DiagnosticIDs : public llvm::RefCountedBase<DiagnosticIDs> {
/// getDescription - Given a diagnostic ID, return a description of the
/// issue.
llvm::StringRef getDescription(unsigned DiagID) const;
StringRef getDescription(unsigned DiagID) const;
/// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic
/// level of the specified diagnostic ID is a Warning or Extension.
/// This only works on builtin diagnostics, not custom ones, and is not legal to
/// call on NOTEs.
/// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic level
/// of the specified diagnostic ID is a Warning or Extension. This only works
/// on builtin diagnostics, not custom ones, and is not legal to call on
/// NOTEs.
static bool isBuiltinWarningOrExtension(unsigned DiagID);
/// \brief Return true if the specified diagnostic is mapped to errors by
/// default.
static bool isDefaultMappingAsError(unsigned DiagID);
/// \brief Determine whether the given built-in diagnostic ID is a
/// Note.
static bool isBuiltinNote(unsigned DiagID);
@ -132,7 +169,7 @@ class DiagnosticIDs : public llvm::RefCountedBase<DiagnosticIDs> {
/// getWarningOptionForDiag - Return the lowest-level warning option that
/// enables the specified diagnostic. If there is no -Wfoo flag that controls
/// the diagnostic, this returns null.
static llvm::StringRef getWarningOptionForDiag(unsigned DiagID);
static StringRef getWarningOptionForDiag(unsigned DiagID);
/// getCategoryNumberForDiag - Return the category number that a specified
/// DiagID belongs to, or 0 if no category.
@ -143,7 +180,7 @@ class DiagnosticIDs : public llvm::RefCountedBase<DiagnosticIDs> {
/// getCategoryNameFromID - Given a category ID, return the name of the
/// category.
static llvm::StringRef getCategoryNameFromID(unsigned CategoryID);
static StringRef getCategoryNameFromID(unsigned CategoryID);
/// \brief Enumeration describing how the the emission of a diagnostic should
/// be treated when it occurs during C++ template argument deduction.
@ -182,56 +219,80 @@ class DiagnosticIDs : public llvm::RefCountedBase<DiagnosticIDs> {
static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID);
/// getName - Given a diagnostic ID, return its name
static llvm::StringRef getName(unsigned DiagID);
static StringRef getName(unsigned DiagID);
/// getIdFromName - Given a diagnostic name, return its ID, or 0
static unsigned getIdFromName(llvm::StringRef Name);
static unsigned getIdFromName(StringRef Name);
/// getBriefExplanation - Given a diagnostic ID, return a brief explanation
/// of the issue
static llvm::StringRef getBriefExplanation(unsigned DiagID);
static StringRef getBriefExplanation(unsigned DiagID);
/// getFullExplanation - Given a diagnostic ID, return a full explanation
/// of the issue
static llvm::StringRef getFullExplanation(unsigned DiagID);
static StringRef getFullExplanation(unsigned DiagID);
/// Iterator class used for traversing all statically declared
/// diagnostics.
class diag_iterator {
const void *impl;
friend class DiagnosticIDs;
diag_iterator(const void *im) : impl(im) {}
public:
diag_iterator &operator++();
bool operator==(const diag_iterator &x) const { return impl == x.impl; }
bool operator!=(const diag_iterator &x) const { return impl != x.impl; }
llvm::StringRef getDiagName() const;
unsigned getDiagID() const;
};
static diag_iterator diags_begin();
static diag_iterator diags_end();
/// \brief Get the set of all diagnostic IDs in the group with the given name.
///
/// \param Diags [out] - On return, the diagnostics in the group.
/// \returns True if the given group is unknown, false otherwise.
bool getDiagnosticsInGroup(StringRef Group,
llvm::SmallVectorImpl<diag::kind> &Diags) const;
private:
/// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g.
/// "unknown-pragmas" to have the specified mapping. This returns true and
/// ignores the request if "Group" was unknown, false otherwise.
bool setDiagnosticGroupMapping(llvm::StringRef Group, diag::Mapping Map,
SourceLocation Loc, Diagnostic &Diag) const;
/// \brief Based on the way the client configured the Diagnostic
/// \brief Get the set of all diagnostic IDs in the given group.
///
/// \param Diags [out] - On return, the diagnostics in the group.
void getDiagnosticsInGroup(const WarningOption *Group,
llvm::SmallVectorImpl<diag::kind> &Diags) const;
/// \brief Based on the way the client configured the DiagnosticsEngine
/// object, classify the specified diagnostic ID into a Level, consumable by
/// the DiagnosticClient.
///
/// \param Loc The source location we are interested in finding out the
/// diagnostic state. Can be null in order to query the latest state.
DiagnosticIDs::Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
const Diagnostic &Diag,
diag::Mapping *mapping = 0) const;
const DiagnosticsEngine &Diag) const;
/// getDiagnosticLevel - This is an internal implementation helper used when
/// DiagClass is already known.
DiagnosticIDs::Level getDiagnosticLevel(unsigned DiagID,
unsigned DiagClass,
SourceLocation Loc,
const Diagnostic &Diag,
diag::Mapping *mapping = 0) const;
const DiagnosticsEngine &Diag) const;
/// ProcessDiag - This is the method used to report a diagnostic that is
/// finally fully formed.
///
/// \returns true if the diagnostic was emitted, false if it was
/// suppressed.
bool ProcessDiag(Diagnostic &Diag) const;
bool ProcessDiag(DiagnosticsEngine &Diag) const;
/// \brief Whether the diagnostic may leave the AST in a state where some
/// invariants can break.
bool isUnrecoverable(unsigned DiagID) const;
friend class Diagnostic;
friend class DiagnosticsEngine;
};
} // end namespace clang

View File

@ -24,6 +24,11 @@ def escaped_newline_block_comment_end : Warning<
def backslash_newline_space : Warning<
"backslash and newline separated by space">;
// Digraphs.
def warn_cxx98_compat_less_colon_colon : Warning<
"'<::' is treated as digraph '<:' (aka '[') followed by ':' in C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
// Trigraphs.
def trigraph_ignored : Warning<"trigraph ignored">, InGroup<Trigraphs>;
def trigraph_ignored_block_comment : Warning<
@ -38,12 +43,16 @@ def ext_multi_line_bcpl_comment : Extension<"multi-line // comment">,
def ext_bcpl_comment : Extension<
"// comments are not allowed in this language">,
InGroup<Comment>;
def ext_no_newline_eof : Extension<"no newline at end of file">;
def ext_backslash_newline_eof : Extension<"backslash-newline at end of file">;
def ext_no_newline_eof : Extension<"no newline at end of file">,
InGroup<DiagGroup<"newline-eof">>;
def ext_dollar_in_identifier : Extension<"'$' in identifier">;
def charize_microsoft_ext : Extension<"@# is a microsoft extension">;
def ext_token_used : Extension<"extension used">;
def ext_token_used : Extension<"extension used">,
InGroup<DiagGroup<"language-extension-token">>;
def warn_cxx11_keyword : Warning<"'%0' is a keyword in C++11">,
InGroup<CXX11Compat>;
def warn_unterminated_string : ExtWarn<"missing terminating '\"' character">;
def warn_unterminated_char : ExtWarn<"missing terminating ' character">;
@ -55,6 +64,18 @@ def err_unterminated___pragma : Error<"missing terminating ')' character">;
def err_conflict_marker : Error<"version control conflict marker in file">;
def err_raw_delim_too_long : Error<
"raw string delimiter longer than 16 characters"
"; use PREFIX( )PREFIX to delimit raw string">;
def err_invalid_char_raw_delim : Error<
"invalid character '%0' character in raw string delimiter"
"; use PREFIX( )PREFIX to delimit raw string">;
def err_unterminated_raw_string : Error<
"raw string missing terminating delimiter )%0\"">;
def warn_cxx98_compat_raw_string_literal : Warning<
"raw string literals are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
def ext_multichar_character_literal : ExtWarn<
"multi-character character constant">, InGroup<MultiChar>;
def ext_four_char_character_literal : Extension<
@ -77,17 +98,14 @@ def err_invalid_suffix_integer_constant : Error<
"invalid suffix '%0' on integer constant">;
def err_invalid_suffix_float_constant : Error<
"invalid suffix '%0' on floating constant">;
def warn_extraneous_wide_char_constant : Warning<
"extraneous characters in wide character constant ignored">;
def warn_extraneous_char_constant : Warning<
"extraneous characters in character constant ignored">;
def warn_char_constant_too_large : Warning<
"character constant too long for its type">;
def err_exponent_has_no_digits : Error<"exponent has no digits">;
def ext_imaginary_constant : Extension<"imaginary constants are an extension">;
def err_hexconstant_requires_exponent : Error<
"hexadecimal floating constants require an exponent">;
def ext_hexconstant_cplusplus : Extension<
"hexadecimal floating constants are a C99 feature that is incompatible with "
"C++0x">, InGroup<CXXHexFloats>;
def ext_hexconstant_invalid : Extension<
"hexadecimal floating constants are a C99 feature">;
def ext_binary_literal : Extension<
@ -102,6 +120,11 @@ def warn_ucn_escape_too_large : ExtWarn<
"character unicode escape sequence too long for its type">;
def warn_ucn_not_valid_in_c89 : ExtWarn<
"unicode escape sequences are only valid in C99 or C++">;
def warn_cxx98_compat_unicode_literal : Warning<
"unicode literals are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
def err_unsupported_string_concat : Error<
"unsupported non-standard concatenation of string literals">;
//===----------------------------------------------------------------------===//
// PTH Diagnostics
@ -167,6 +190,9 @@ def ext_pp_bad_vaargs_use : Extension<
def ext_pp_macro_redef : ExtWarn<"%0 macro redefined">;
def ext_variadic_macro : Extension<"variadic macros were introduced in C99">,
InGroup<VariadicMacros>;
def warn_cxx98_compat_variadic_macro : Warning<
"variadic macros are incompatible with C++98">,
InGroup<CXX98CompatPedantic>, DefaultIgnore;
def ext_named_variadic_macro : Extension<
"named variadic macros are a GNU extension">, InGroup<VariadicMacros>;
def ext_embedded_directive : Extension<
@ -175,10 +201,13 @@ def ext_missing_varargs_arg : Extension<
"varargs argument missing, but tolerated as an extension">;
def ext_empty_fnmacro_arg : Extension<
"empty macro arguments were standardized in C99">;
def warn_cxx98_compat_empty_fnmacro_arg : Warning<
"empty macro argument list is incompatible with C++98">,
InGroup<CXX98CompatPedantic>, DefaultIgnore;
def err_pp_invalid_directive : Error<"invalid preprocessing directive">;
def err_pp_hash_error : Error<"#error%0">;
def warn_pp_file_not_found : Warning<"'%0' file not found">, DefaultFatal;
def err_pp_file_not_found : Error<"'%0' file not found">, DefaultFatal;
def err_pp_error_opening_file : Error<
"error opening file '%0': %1">, DefaultFatal;
def err_pp_empty_filename : Error<"empty filename">;
@ -230,6 +259,13 @@ def err_pp_used_poisoned_id : Error<"attempt to use a poisoned identifier">;
def err_feature_check_malformed : Error<
"builtin feature check macro requires a parenthesized identifier">;
def err_warning_check_malformed : Error<
"builtin warning check macro requires a parenthesized string">,
InGroup<MalformedWarningCheck>;
def warn_has_warning_invalid_option :
ExtWarn<"__has_warning expected option name (e.g. \"-Wundef\")">,
InGroup<MalformedWarningCheck>;
def err__Pragma_malformed : Error<
"_Pragma takes a parenthesized string literal">;
def err_pragma_comment_malformed : Error<
@ -315,5 +351,20 @@ def err_pp_linemarker_invalid_pop : Error<
"invalid line marker flag '2': cannot pop empty include stack">;
def ext_pp_line_too_big : Extension<
"C requires #line number to be less than %0, allowed as extension">;
def warn_cxx98_compat_pp_line_too_big : Warning<
"#line number greater than 32767 is incompatible with C++98">,
InGroup<CXX98CompatPedantic>, DefaultIgnore;
def err_pp_export_non_macro : Error<"no macro named %0 to export">;
def err_pp_arc_cf_code_audited_syntax : Error<"expected 'begin' or 'end'">;
def err_pp_double_begin_of_arc_cf_code_audited : Error<
"already inside '#pragma clang arc_cf_code_audited'">;
def err_pp_unmatched_end_of_arc_cf_code_audited : Error<
"not currently inside '#pragma clang arc_cf_code_audited'">;
def err_pp_include_in_arc_cf_code_audited : Error<
"cannot #include files inside '#pragma clang arc_cf_code_audited'">;
def err_pp_eof_in_arc_cf_code_audited : Error<
"'#pragma clang arc_cf_code_audited' was not ended within this file">;
}

View File

@ -28,10 +28,6 @@ def ext_extra_struct_semi : Extension<
def ext_extra_ivar_semi : Extension<
"extra ';' inside instance variable list">;
def auto_storage_class : ExtWarn<
"'auto' storage class specifier is redundant and will be "
"removed in future releases">;
def ext_duplicate_declspec : Extension<"duplicate '%0' declaration specifier">;
def ext_plain_complex : ExtWarn<
"plain '_Complex' requires a type specifier; assuming '_Complex double'">;
@ -57,7 +53,7 @@ def ext_c99_variable_decl_in_for_loop : Extension<
def ext_c99_compound_literal : Extension<
"compound literals are a C99-specific feature">;
def ext_enumerator_list_comma : Extension<
"commas at the end of enumerator lists are a %select{C99|C++0x}0-specific "
"commas at the end of enumerator lists are a %select{C99|C++11}0-specific "
"feature">;
def err_enumerator_list_missing_comma : Error<
"missing ',' between enumerators">;
@ -68,12 +64,15 @@ def ext_ms_enum_fixed_underlying_type : Extension<
InGroup<Microsoft>;
def ext_c1x_generic_selection : Extension<
"generic selections are a C1X-specific feature">;
"generic selections are a C1X-specific feature">, InGroup<C1X>;
def err_duplicate_default_assoc : Error<
"duplicate default generic association">;
def note_previous_default_assoc : Note<
"previous default generic association is here">;
def ext_c1x_alignas : Extension<
"_Alignas is a C1X-specific feature">, InGroup<C1X>;
def ext_gnu_indirect_goto : Extension<
"use of GNU indirect-goto extension">, InGroup<GNU>;
def ext_gnu_address_of_label : Extension<
@ -188,16 +187,26 @@ def err_invalid_reference_qualifier_application : Error<
def err_illegal_decl_reference_to_reference : Error<
"%0 declared as a reference to a reference">;
def ext_rvalue_reference : ExtWarn<
"rvalue references are a C++0x extension">, InGroup<CXX0x>;
"rvalue references are a C++11 extension">, InGroup<CXX11>;
def ext_ref_qualifier : ExtWarn<
"reference qualifiers on functions are a C++0x extension">, InGroup<CXX0x>;
"reference qualifiers on functions are a C++11 extension">, InGroup<CXX11>;
def ext_inline_namespace : ExtWarn<
"inline namespaces are a C++0x feature">, InGroup<CXX0x>;
"inline namespaces are a C++11 feature">, InGroup<CXX11>;
def err_generalized_initializer_lists : Error<
"generalized initializer lists are a C++0x extension unsupported in Clang">;
"generalized initializer lists are a C++11 extension unsupported in Clang">;
def ext_generalized_initializer_lists : ExtWarn<
"generalized initializer lists are a C++0x extension unsupported in Clang">,
InGroup<CXX0x>;
"generalized initializer lists are a C++11 extension unsupported in Clang">,
InGroup<CXX11>;
def ext_auto_type_specifier : ExtWarn<
"'auto' type specifier is a C++11 extension">, InGroup<CXX11>;
def warn_auto_storage_class : Warning<
"'auto' storage class specifier is redundant and incompatible with C++11">,
InGroup<CXX11Compat>;
def ext_auto_storage_class : ExtWarn<
"'auto' storage class specifier is not permitted in C++11, and will not "
"be supported in future releases">;
def ext_for_range : ExtWarn<
"range-based for loop is a C++11 extension">, InGroup<CXX11>;
def err_argument_required_after_attribute : Error<
"argument required after attribute">;
def err_missing_param : Error<"expected parameter declarator">;
@ -219,6 +228,9 @@ def err_typename_invalid_storageclass : Error<
"type name does not allow storage class to be specified">;
def err_typename_invalid_functionspec : Error<
"type name does not allow function specifier to be specified">;
def err_typename_identifiers_only : Error<
"typename is allowed for identifiers only">;
def err_invalid_decl_spec_combination : Error<
"cannot combine with previous '%0' declaration specifier">;
def err_invalid_vector_decl_spec_combination : Error<
@ -250,7 +262,7 @@ def err_unexected_colon_in_nested_name_spec : Error<
def err_bool_redeclaration : Error<
"redeclaration of C++ built-in type 'bool'">;
def ext_c1x_static_assert : Extension<
"_Static_assert is a C1X-specific feature">;
"_Static_assert is a C1X-specific feature">, InGroup<C1X>;
/// Objective-C parser diagnostics
def err_expected_minus_or_plus : Error<
@ -342,6 +354,8 @@ def err_destructor_template_id : Error<
"destructor name %0 does not refer to a template">;
def err_default_arg_unparsed : Error<
"unexpected end of default argument expression">;
def err_parser_impl_limit_overflow : Error<
"parser recursion limit reached, program too complex">, DefaultFatal;
// C++ derived classes
def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
@ -357,10 +371,15 @@ def err_default_delete_in_multiple_declaration : Error<
"'= %select{default|delete}0' is a function definition and must occur in a "
"standalone declaration">;
def warn_cxx98_compat_alignas : Warning<"'alignas' is incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
def warn_cxx98_compat_attribute : Warning<
"attributes are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
def err_cxx0x_attribute_forbids_arguments : Error<
"C++0x attribute '%0' cannot have an argument list">;
"C++11 attribute '%0' cannot have an argument list">;
def err_cxx0x_attribute_requires_arguments : Error<
"C++0x attribute '%0' must have an argument list">;
"C++1 attribute '%0' must have an argument list">;
def err_attributes_not_allowed : Error<"an attribute list cannot appear here">;
/// C++ Templates
@ -385,7 +404,7 @@ def err_two_right_angle_brackets_need_space : Error<
"a space is required between consecutive right angle brackets (use '> >')">;
def warn_cxx0x_right_shift_in_template_arg : Warning<
"use of right-shift operator ('>>') in template argument will require "
"parentheses in C++0x">;
"parentheses in C++11">;
def err_multiple_template_declarators : Error<
"%select{|a template declaration|an explicit template specialization|"
"an explicit template instantiation}0 can "
@ -446,31 +465,31 @@ def err_missing_whitespace_digraph : Error<
" which forms the digraph '<:' (aka '[') and a ':', did you mean '< ::'?">;
def warn_deleted_function_accepted_as_extension: ExtWarn<
"deleted function definition accepted as a C++0x extension">, InGroup<CXX0x>;
"deleted function definition accepted as a C++11 extension">, InGroup<CXX11>;
def warn_defaulted_function_accepted_as_extension: ExtWarn<
"defaulted function definition accepted as a C++0x extension">,
InGroup<CXX0x>;
"defaulted function definition accepted as a C++11 extension">,
InGroup<CXX11>;
// C++0x in-class member initialization
// C++11 in-class member initialization
def warn_nonstatic_member_init_accepted_as_extension: ExtWarn<
"in-class initialization of non-static data member accepted as a C++0x extension">,
InGroup<CXX0x>;
"in-class initialization of non-static data member accepted as a C++11 extension">,
InGroup<CXX11>;
def err_bitfield_member_init: Error<
"bitfield member cannot have an in-class initializer">;
def err_incomplete_array_member_init: Error<
"array bound cannot be deduced from an in-class initializer">;
// C++0x alias-declaration
// C++11 alias-declaration
def ext_alias_declaration : ExtWarn<
"alias declarations accepted as a C++0x extension">, InGroup<CXX0x>;
"alias declarations accepted as a C++11 extension">, InGroup<CXX11>;
def err_alias_declaration_not_identifier : Error<
"name defined in alias declaration must be an identifier">;
def err_alias_declaration_specialization : Error<
"%select{partial specialization|explicit specialization|explicit instantiation}0 of alias templates is not permitted">;
// C++0x override control
// C++11 override control
def ext_override_control_keyword : Extension<
"'%0' keyword accepted as a C++0x extension">, InGroup<CXX0x>;
"'%0' keyword accepted as a C++11 extension">, InGroup<CXX11>;
def err_duplicate_virt_specifier : Error<
"class member already marked '%0'">;
@ -487,6 +506,15 @@ def err_paren_sizeof_parameter_pack : Error<
def err_sizeof_parameter_pack : Error<
"expected parenthesized parameter pack name in 'sizeof...' expression">;
// C++11 lambda expressions
def err_expected_comma_or_rsquare : Error<
"expected ',' or ']' in lambda capture list">;
def err_this_captured_by_reference : Error<
"'this' cannot be captured by reference">;
def err_expected_capture : Error<
"expected variable name or 'this' in lambda capture list">;
def err_expected_lambda_body : Error<"expected body of lambda expression">;
// Availability attribute
def err_expected_version : Error<
"expected a version of the form 'major[.minor[.subminor]]'">;
@ -559,6 +587,14 @@ def err_seh___except_filter : Error<
def err_seh___finally_block : Error<
"%0 only allowed in __finally block">;
} // end of Parse Issue category.
let CategoryName = "Modules Issue" in {
def err_module_expected_ident : Error<
"expected a module name after '__import_module__'">;
def err_module_expected_semi : Error<
"expected a semicolon name after module name">;
}
} // end of Parser diagnostics

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