Vendor import of clang release_31 branch r155985:

http://llvm.org/svn/llvm-project/cfe/branches/release_31@155985
This commit is contained in:
Dimitry Andric 2012-05-03 16:53:59 +00:00
parent dbe13110f5
commit 6b9a6e390f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/clang/dist/; revision=234973
svn path=/vendor/clang/clang-release_31-r155985/; revision=234974; tag=vendor/clang/clang-release_31-r155985
263 changed files with 4663 additions and 4896 deletions

View File

@ -66,6 +66,10 @@ set(CLANG_RESOURCE_DIR "" CACHE STRING
set(C_INCLUDE_DIRS "" CACHE STRING
"Colon separated list of directories clang will search for headers.")
set(GCC_INSTALL_PREFIX "" CACHE PATH "Directory where gcc is installed." )
set(DEFAULT_SYSROOT "" CACHE PATH
"Default <path> to all compiler invocations for --sysroot=<path>." )
set(CLANG_VENDOR "" CACHE STRING
"Vendor-specific text for showing with version information.")

View File

@ -1079,6 +1079,11 @@ def name(self):
self._name_map[value] = key
return self._name_map[self]
@property
def spelling(self):
"""Retrieve the spelling of this TypeKind."""
return TypeKind_spelling(self.value)
@staticmethod
def from_id(id):
if id >= len(TypeKind._kinds) or TypeKind._kinds[id] is None:
@ -1088,6 +1093,10 @@ def from_id(id):
def __repr__(self):
return 'TypeKind.%s' % (self.name,)
TypeKind_spelling = lib.clang_getTypeKindSpelling
TypeKind_spelling.argtypes = [c_uint]
TypeKind_spelling.restype = _CXString
TypeKind_spelling.errcheck = _CXString.from_result
TypeKind.INVALID = TypeKind(0)

View File

@ -1,5 +1,4 @@
from clang.cindex import CursorKind
from clang.cindex import Index
from clang.cindex import TypeKind
from nose.tools import raises
from .util import get_cursor
@ -109,6 +108,14 @@ def test_equal():
assert a.type != None
assert a.type != 'foo'
def test_typekind_spelling():
"""Ensure TypeKind.spelling works."""
tu = get_tu('int a;')
a = get_cursor(tu, 'a')
assert a is not None
assert a.type.kind.spelling == 'Int'
def test_function_argument_types():
"""Ensure that Type.argument_types() works as expected."""
tu = get_tu('void f(int, int);')

View File

@ -7,7 +7,6 @@ set(LLVM_USED_LIBS
clangStaticAnalyzerFrontend
clangStaticAnalyzerCheckers
clangStaticAnalyzerCore
clangIndex
clangAnalysis
clangRewrite
clangAST

View File

@ -64,6 +64,9 @@ class TypeSourceInfo {
/// \brief Return the TypeLoc wrapper for the type source info.
TypeLoc getTypeLoc() const; // implemented in TypeLoc.h
/// \brief Override the type stored in this TypeSourceInfo. Use with caution!
void overrideType(QualType T) { Ty = T; }
};
/// TranslationUnitDecl - The top declaration context.
@ -242,11 +245,7 @@ class NamedDecl : public Decl {
bool visibilityExplicit() const { return explicit_; }
void setLinkage(Linkage L) { linkage_ = L; }
void setVisibility(Visibility V) { visibility_ = V; }
void setVisibility(Visibility V, bool E) { visibility_ = V; explicit_ = E; }
void setVisibility(LinkageInfo Other) {
setVisibility(Other.visibility(), Other.visibilityExplicit());
}
void mergeLinkage(Linkage L) {
setLinkage(minLinkage(linkage(), L));

View File

@ -861,7 +861,6 @@ class Decl {
void dumpXML(raw_ostream &OS) const;
private:
const Attr *getAttrsImpl() const;
void setAttrsImpl(const AttrVec& Attrs, ASTContext &Ctx);
void setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC,
ASTContext &Ctx);

View File

@ -67,6 +67,8 @@ class DeclContext::all_lookups_iterator {
DeclContext::all_lookups_iterator DeclContext::lookups_begin() const {
DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext();
if (hasExternalVisibleStorage())
getParentASTContext().getExternalSource()->completeVisibleDeclsMap(Primary);
if (StoredDeclsMap *Map = Primary->buildLookup())
return all_lookups_iterator(Map->begin(), Map->end());
return all_lookups_iterator();
@ -74,6 +76,8 @@ DeclContext::all_lookups_iterator DeclContext::lookups_begin() const {
DeclContext::all_lookups_iterator DeclContext::lookups_end() const {
DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext();
if (hasExternalVisibleStorage())
getParentASTContext().getExternalSource()->completeVisibleDeclsMap(Primary);
if (StoredDeclsMap *Map = Primary->buildLookup())
return all_lookups_iterator(Map->end(), Map->end());
return all_lookups_iterator();

View File

@ -581,16 +581,6 @@ class Expr : public Stmt {
/// member expression.
static QualType findBoundMemberType(const Expr *expr);
/// \brief Result type of CanThrow().
enum CanThrowResult {
CT_Cannot,
CT_Dependent,
CT_Can
};
/// \brief Test if this expression, if evaluated, might throw, according to
/// the rules of C++ [expr.unary.noexcept].
CanThrowResult CanThrow(ASTContext &C) const;
/// IgnoreImpCasts - Skip past any implicit casts which might
/// surround this expression. Only skips ImplicitCastExprs.
Expr *IgnoreImpCasts() LLVM_READONLY;
@ -3608,6 +3598,10 @@ class InitListExpr : public Expr {
return LBraceLoc.isValid() && RBraceLoc.isValid();
}
// Is this an initializer for an array of characters, initialized by a string
// literal or an @encode?
bool isStringLiteralInit() const;
SourceLocation getLBraceLoc() const { return LBraceLoc; }
void setLBraceLoc(SourceLocation Loc) { LBraceLoc = Loc; }
SourceLocation getRBraceLoc() const { return RBraceLoc; }

View File

@ -126,6 +126,12 @@ class ExternalASTSource {
virtual DeclContextLookupResult
FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name);
/// \brief Ensures that the table of all visible declarations inside this
/// context is up to date.
///
/// The default implementation of this functino is a no-op.
virtual void completeVisibleDeclsMap(const DeclContext *DC);
/// \brief Finds all declarations lexically contained within the given
/// DeclContext, after applying an optional filter predicate.
///

View File

@ -1870,6 +1870,7 @@ DEF_TRAVERSE_STMT(GotoStmt, { })
DEF_TRAVERSE_STMT(IfStmt, { })
DEF_TRAVERSE_STMT(IndirectGotoStmt, { })
DEF_TRAVERSE_STMT(LabelStmt, { })
DEF_TRAVERSE_STMT(AttributedStmt, { })
DEF_TRAVERSE_STMT(NullStmt, { })
DEF_TRAVERSE_STMT(ObjCAtCatchStmt, { })
DEF_TRAVERSE_STMT(ObjCAtFinallyStmt, { })

View File

@ -20,6 +20,7 @@
#include "clang/AST/StmtIterator.h"
#include "clang/AST/DeclGroup.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
@ -794,6 +795,47 @@ class LabelStmt : public Stmt {
};
/// \brief Represents an attribute applied to a statement.
///
/// Represents an attribute applied to a statement. For example:
/// [[omp::for(...)]] for (...) { ... }
///
class AttributedStmt : public Stmt {
Stmt *SubStmt;
SourceLocation AttrLoc;
AttrVec Attrs;
// TODO: It can be done as Attr *Attrs[1]; and variable size array as in
// StringLiteral
friend class ASTStmtReader;
public:
AttributedStmt(SourceLocation loc, const AttrVec &attrs, Stmt *substmt)
: Stmt(AttributedStmtClass), SubStmt(substmt), AttrLoc(loc), Attrs(attrs) {
}
// \brief Build an empty attributed statement.
explicit AttributedStmt(EmptyShell Empty)
: Stmt(AttributedStmtClass, Empty) {
}
SourceLocation getAttrLoc() const { return AttrLoc; }
const AttrVec &getAttrs() const { return Attrs; }
Stmt *getSubStmt() { return SubStmt; }
const Stmt *getSubStmt() const { return SubStmt; }
SourceRange getSourceRange() const LLVM_READONLY {
return SourceRange(AttrLoc, SubStmt->getLocEnd());
}
child_range children() { return child_range(&SubStmt, &SubStmt + 1); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == AttributedStmtClass;
}
static bool classof(const AttributedStmt *) { return true; }
};
/// IfStmt - This represents an if/then/else.
///
class IfStmt : public Stmt {

View File

@ -79,6 +79,7 @@ namespace clang {
class CXXRecordDecl;
class EnumDecl;
class FieldDecl;
class FunctionDecl;
class ObjCInterfaceDecl;
class ObjCProtocolDecl;
class ObjCMethodDecl;
@ -2700,7 +2701,9 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
ExtProtoInfo() :
Variadic(false), HasTrailingReturn(false), TypeQuals(0),
ExceptionSpecType(EST_None), RefQualifier(RQ_None),
NumExceptions(0), Exceptions(0), NoexceptExpr(0), ConsumedArguments(0) {}
NumExceptions(0), Exceptions(0), NoexceptExpr(0),
ExceptionSpecDecl(0), ExceptionSpecTemplate(0),
ConsumedArguments(0) {}
FunctionType::ExtInfo ExtInfo;
bool Variadic : 1;
@ -2711,6 +2714,8 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
unsigned NumExceptions;
const QualType *Exceptions;
Expr *NoexceptExpr;
FunctionDecl *ExceptionSpecDecl;
FunctionDecl *ExceptionSpecTemplate;
const bool *ConsumedArguments;
};
@ -2756,6 +2761,11 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
// NoexceptExpr - Instead of Exceptions, there may be a single Expr* pointing
// to the expression in the noexcept() specifier.
// ExceptionSpecDecl, ExceptionSpecTemplate - Instead of Exceptions, there may
// be a pair of FunctionDecl* pointing to the function which should be used to
// instantiate this function type's exception specification, and the function
// from which it should be instantiated.
// 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.
@ -2795,6 +2805,9 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
EPI.Exceptions = exception_begin();
} else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) {
EPI.NoexceptExpr = getNoexceptExpr();
} else if (EPI.ExceptionSpecType == EST_Uninstantiated) {
EPI.ExceptionSpecDecl = getExceptionSpecDecl();
EPI.ExceptionSpecTemplate = getExceptionSpecTemplate();
}
if (hasAnyConsumedArgs())
EPI.ConsumedArguments = getConsumedArgsBuffer();
@ -2838,9 +2851,26 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
// NoexceptExpr sits where the arguments end.
return *reinterpret_cast<Expr *const *>(arg_type_end());
}
/// \brief If this function type has an uninstantiated exception
/// specification, this is the function whose exception specification
/// is represented by this type.
FunctionDecl *getExceptionSpecDecl() const {
if (getExceptionSpecType() != EST_Uninstantiated)
return 0;
return reinterpret_cast<FunctionDecl * const *>(arg_type_end())[0];
}
/// \brief If this function type has an uninstantiated exception
/// specification, this is the function whose exception specification
/// should be instantiated to find the exception specification for
/// this type.
FunctionDecl *getExceptionSpecTemplate() const {
if (getExceptionSpecType() != EST_Uninstantiated)
return 0;
return reinterpret_cast<FunctionDecl * const *>(arg_type_end())[1];
}
bool isNothrow(ASTContext &Ctx) const {
ExceptionSpecificationType EST = getExceptionSpecType();
assert(EST != EST_Delayed);
assert(EST != EST_Delayed && EST != EST_Uninstantiated);
if (EST == EST_DynamicNone || EST == EST_BasicNoexcept)
return true;
if (EST != EST_ComputedNoexcept)

View File

@ -205,11 +205,11 @@ class VTableLayout {
typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy;
private:
uint64_t NumVTableComponents;
VTableComponent *VTableComponents;
llvm::OwningArrayPtr<VTableComponent> VTableComponents;
/// VTableThunks - Contains thunks needed by vtables.
uint64_t NumVTableThunks;
VTableThunkTy *VTableThunks;
llvm::OwningArrayPtr<VTableThunkTy> VTableThunks;
/// Address points - Address points for all vtables.
AddressPointsMapTy AddressPoints;
@ -227,11 +227,11 @@ class VTableLayout {
}
vtable_component_iterator vtable_component_begin() const {
return VTableComponents;
return VTableComponents.get();
}
vtable_component_iterator vtable_component_end() const {
return VTableComponents+NumVTableComponents;
return VTableComponents.get()+NumVTableComponents;
}
uint64_t getNumVTableThunks() const {
@ -239,11 +239,11 @@ class VTableLayout {
}
vtable_thunk_iterator vtable_thunk_begin() const {
return VTableThunks;
return VTableThunks.get();
}
vtable_thunk_iterator vtable_thunk_end() const {
return VTableThunks+NumVTableThunks;
return VTableThunks.get()+NumVTableThunks;
}
uint64_t getAddressPoint(BaseSubobject Base) const {

View File

@ -129,7 +129,7 @@ class ProgramPoint {
static bool classof(const ProgramPoint*) { return true; }
bool operator==(const ProgramPoint & RHS) const {
return Data1 == Data1 &&
return Data1 == RHS.Data1 &&
Data2 == RHS.Data2 &&
L == RHS.L &&
Tag == RHS.Tag;

View File

@ -412,6 +412,9 @@ BUILTIN(__builtin_ia32_cvtps2pd256, "V4dV4f", "")
BUILTIN(__builtin_ia32_cvttpd2dq256, "V4iV4d", "")
BUILTIN(__builtin_ia32_cvtpd2dq256, "V4iV4d", "")
BUILTIN(__builtin_ia32_cvttps2dq256, "V8iV8f", "")
BUILTIN(__builtin_ia32_vperm2f128_pd256, "V4dV4dV4dIc", "")
BUILTIN(__builtin_ia32_vperm2f128_ps256, "V8fV8fV8fIc", "")
BUILTIN(__builtin_ia32_vperm2f128_si256, "V8iV8iV8iIc", "")
BUILTIN(__builtin_ia32_vinsertf128_pd256, "V4dV4dV2dIc", "")
BUILTIN(__builtin_ia32_vinsertf128_ps256, "V8fV8fV4fIc", "")
BUILTIN(__builtin_ia32_vinsertf128_si256, "V8iV8iV4iIc", "")
@ -560,9 +563,8 @@ BUILTIN(__builtin_ia32_pbroadcastw128, "V8sV8s", "")
BUILTIN(__builtin_ia32_pbroadcastd128, "V4iV4i", "")
BUILTIN(__builtin_ia32_pbroadcastq128, "V2LLiV2LLi", "")
BUILTIN(__builtin_ia32_permvarsi256, "V8iV8iV8i", "")
BUILTIN(__builtin_ia32_permdf256, "V4dV4dIc", "")
BUILTIN(__builtin_ia32_permvarsf256, "V8fV8fV8f", "")
BUILTIN(__builtin_ia32_permdi256, "V4LLiV4LLiIc", "")
BUILTIN(__builtin_ia32_permti256, "V4LLiV4LLiV4LLiIc", "")
BUILTIN(__builtin_ia32_extract128i256, "V2LLiV4LLiIc", "")
BUILTIN(__builtin_ia32_insert128i256, "V4LLiV4LLiV2LLiIc", "")
BUILTIN(__builtin_ia32_maskloadd256, "V8iV8iC*V8i", "")

View File

@ -151,9 +151,9 @@ ConversionResult ConvertUTF16toUTF32 (
ConversionResult ConvertUTF32toUTF16 (
const UTF32** sourceStart, const UTF32* sourceEnd,
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
#endif
Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);
#endif
Boolean isLegalUTF8String(const UTF8 *source, const UTF8 *sourceEnd);

View File

@ -1,110 +0,0 @@
//=== DelayedCleanupPool.h - Delayed Clean-up Pool Implementation *- C++ -*===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines a facility to delay calling cleanup methods until specific
// points.
//
//===----------------------------------------------------------------------===//
#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"
namespace clang {
/// \brief Gathers pairs of pointer-to-object/pointer-to-cleanup-function
/// allowing the cleanup functions to get called (with the pointer as parameter)
/// at specific points.
///
/// The use case is to simplify clean-up of certain resources that, while their
/// lifetime is well-known and restricted, cleaning them up manually is easy to
/// miss and cause a leak.
///
/// The same pointer can be added multiple times; its clean-up function will
/// only be called once.
class DelayedCleanupPool {
public:
typedef void (*CleanupFn)(void *ptr);
/// \brief Adds a pointer and its associated cleanup function to be called
/// at a later point.
///
/// \returns false if the pointer is already added, true otherwise.
bool delayCleanup(void *ptr, CleanupFn fn) {
assert(ptr && "Expected valid pointer to object");
assert(fn && "Expected valid pointer to function");
CleanupFn &mapFn = Ptrs[ptr];
assert((!mapFn || mapFn == fn) &&
"Adding a pointer with different cleanup function!");
if (!mapFn) {
mapFn = fn;
Cleanups.push_back(std::make_pair(ptr, fn));
return true;
}
return false;
}
template <typename T>
bool delayDelete(T *ptr) {
return delayCleanup(ptr, cleanupWithDelete<T>);
}
template <typename T, void (T::*Fn)()>
bool delayMemberFunc(T *ptr) {
return delayCleanup(ptr, cleanupWithMemberFunc<T, Fn>);
}
void doCleanup() {
for (SmallVector<std::pair<void *, CleanupFn>, 8>::reverse_iterator
I = Cleanups.rbegin(), E = Cleanups.rend(); I != E; ++I)
I->second(I->first);
Cleanups.clear();
Ptrs.clear();
}
~DelayedCleanupPool() {
doCleanup();
}
private:
llvm::DenseMap<void *, CleanupFn> Ptrs;
SmallVector<std::pair<void *, CleanupFn>, 8> Cleanups;
template <typename T>
static void cleanupWithDelete(void *ptr) {
delete static_cast<T *>(ptr);
}
template <typename T, void (T::*Fn)()>
static void cleanupWithMemberFunc(void *ptr) {
(static_cast<T *>(ptr)->*Fn)();
}
};
/// \brief RAII object for triggering a cleanup of a DelayedCleanupPool.
class DelayedCleanupPoint {
DelayedCleanupPool &Pool;
public:
DelayedCleanupPoint(DelayedCleanupPool &pool) : Pool(pool) { }
~DelayedCleanupPoint() {
Pool.doCleanup();
}
};
} // end namespace clang
#endif

View File

@ -410,6 +410,8 @@ def ext_ellipsis_exception_spec : Extension<
"exception specification of '...' is a Microsoft extension">;
def err_dynamic_and_noexcept_specification : Error<
"cannot have both throw() and noexcept() clause on the same function">;
def err_except_spec_unparsed : Error<
"unexpected end of exception specification">;
def warn_cxx98_compat_noexcept_decl : Warning<
"noexcept specifications are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;

View File

@ -231,9 +231,13 @@ def err_using_decl_can_not_refer_to_namespace : Error<
"using declaration can not refer to namespace">;
def err_using_decl_constructor : Error<
"using declaration can not refer to a constructor">;
def warn_cxx98_compat_using_decl_constructor : Warning<
"inherited constructors are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
def err_using_decl_constructor_unsupported : Error<
"inheriting constructors are not supported">;
// FIXME: Replace the above error with this warning if support for
// inheriting constructors is implemented.
//def warn_cxx98_compat_using_decl_constructor : Warning<
// "inheriting constructors are incompatible with C++98">,
// InGroup<CXX98Compat>, DefaultIgnore;
def err_using_decl_destructor : Error<
"using declaration can not refer to a destructor">;
def err_using_decl_template_id : Error<
@ -1547,9 +1551,6 @@ def warn_objc_redundant_literal_use : Warning<
"using %0 with a literal is redundant">, InGroup<ObjCRedundantLiteralUse>;
}
def warn_bool_for_boolean_literal : Warning<
"BOOL of type %0 is non-intergal and unsuitable for a "
"boolean literal - ignored">, InGroup<DiagGroup<"numeric-literals">>;
def err_only_annotate_after_access_spec : Error<
"access specifier can only have annotation attributes">;
def err_attribute_section_invalid_for_target : Error<
@ -1563,6 +1564,9 @@ def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning<
def warn_attribute_ignored : Warning<"%0 attribute ignored">;
def warn_unknown_attribute_ignored : Warning<
"unknown attribute %0 ignored">, InGroup<UnknownAttributes>;
def warn_attribute_invalid_on_stmt : Warning<
"attribute %0 cannot be specified on a statement">,
InGroup<IgnoredAttributes>;
def warn_declspec_attribute_ignored : Warning<
"attribute %0 is ignored, place it after \"%select{class|struct|union|enum}1\" to apply attribute to type declaration">, InGroup<IgnoredAttributes>;
def warn_attribute_precede_definition : Warning<
@ -2583,6 +2587,8 @@ def note_template_enum_def_here : Note<
"in instantiation of enumeration %q0 requested here">;
def note_template_type_alias_instantiation_here : Note<
"in instantiation of template type alias %0 requested here">;
def note_template_exception_spec_instantiation_here : Note<
"in instantiation of exception specification for %0 requested here">;
def note_default_arg_instantiation_here : Note<
"in instantiation of default argument for '%0' required here">;
@ -3798,6 +3804,9 @@ def warn_null_in_comparison_operation : Warning<
def err_invalid_this_use : Error<
"invalid use of 'this' outside of a non-static member function">;
def err_this_static_member_func : Error<
"'this' cannot be%select{| implicitly}0 used in a static member function "
"declaration">;
def err_invalid_member_use_in_static_method : Error<
"invalid use of member %0 in static member function">;
def err_invalid_qualified_function_type : Error<
@ -3907,7 +3916,7 @@ def err_nosetter_property_incdec : Error<
def err_nogetter_property_compound_assignment : Error<
"a getter method is needed to perform a compound assignment on a property">;
def err_nogetter_property_incdec : Error<
"no getter method %1 for %select{increment|decrement} of property">;
"no getter method %1 for %select{increment|decrement}0 of property">;
def error_no_subobject_property_setting : Error<
"expression is not assignable">;
def err_qualified_objc_access : Error<

View File

@ -16,7 +16,7 @@
namespace clang {
/// \brief The various types of exception specifications that exist in C++0x.
/// \brief The various types of exception specifications that exist in C++11.
enum ExceptionSpecificationType {
EST_None, ///< no exception specification
EST_DynamicNone, ///< throw()
@ -24,7 +24,8 @@ enum ExceptionSpecificationType {
EST_MSAny, ///< Microsoft throw(...) extension
EST_BasicNoexcept, ///< noexcept
EST_ComputedNoexcept, ///< noexcept(expression)
EST_Delayed ///< not known yet
EST_Delayed, ///< not known yet
EST_Uninstantiated ///< not instantiated yet
};
inline bool isDynamicExceptionSpec(ExceptionSpecificationType ESpecType) {
@ -35,6 +36,19 @@ inline bool isNoexceptExceptionSpec(ExceptionSpecificationType ESpecType) {
return ESpecType == EST_BasicNoexcept || ESpecType == EST_ComputedNoexcept;
}
/// \brief Possible results from evaluation of a noexcept expression.
enum CanThrowResult {
CT_Cannot,
CT_Dependent,
CT_Can
};
inline CanThrowResult mergeCanThrow(CanThrowResult CT1, CanThrowResult CT2) {
// CanThrowResult constants are ordered so that the maximum is the correct
// merge result.
return CT1 > CT2 ? CT1 : CT2;
}
} // end namespace clang
#endif // LLVM_CLANG_BASIC_EXCEPTIONSPECIFICATIONTYPE_H

View File

@ -132,7 +132,7 @@ class OnDiskChainedHashTableGenerator {
class Bucket {
public:
io::Offset off;
Item* head;
Item* head;
unsigned length;
Bucket() {}
@ -201,6 +201,7 @@ class OnDiskChainedHashTableGenerator {
// Write out the number of items in the bucket.
Emit16(out, B.length);
assert(B.length != 0 && "Bucket has a head but zero length?");
// Write out the entries in the bucket.
for (Item *I = B.head; I ; I = I->next) {
@ -398,31 +399,30 @@ class OnDiskChainedHashTable {
}
key_iterator key_end() { return key_iterator(); }
/// \brief Iterates over all the entries in the table, returning
/// a key/data pair.
class item_iterator {
/// \brief Iterates over all the entries in the table, returning the data.
class data_iterator {
const unsigned char* Ptr;
unsigned NumItemsInBucketLeft;
unsigned NumEntriesLeft;
Info *InfoObj;
public:
typedef std::pair<external_key_type, data_type> value_type;
typedef data_type value_type;
item_iterator(const unsigned char* const Ptr, unsigned NumEntries,
data_iterator(const unsigned char* const Ptr, unsigned NumEntries,
Info *InfoObj)
: Ptr(Ptr), NumItemsInBucketLeft(0), NumEntriesLeft(NumEntries),
InfoObj(InfoObj) { }
item_iterator()
data_iterator()
: Ptr(0), NumItemsInBucketLeft(0), NumEntriesLeft(0), InfoObj(0) { }
bool operator==(const item_iterator& X) const {
bool operator==(const data_iterator& X) const {
return X.NumEntriesLeft == NumEntriesLeft;
}
bool operator!=(const item_iterator& X) const {
bool operator!=(const data_iterator& X) const {
return X.NumEntriesLeft != NumEntriesLeft;
}
item_iterator& operator++() { // Preincrement
data_iterator& operator++() { // Preincrement
if (!NumItemsInBucketLeft) {
// 'Items' starts with a 16-bit unsigned integer representing the
// number of items in this bucket.
@ -438,8 +438,8 @@ class OnDiskChainedHashTable {
--NumEntriesLeft;
return *this;
}
item_iterator operator++(int) { // Postincrement
item_iterator tmp = *this; ++*this; return tmp;
data_iterator operator++(int) { // Postincrement
data_iterator tmp = *this; ++*this; return tmp;
}
value_type operator*() const {
@ -454,15 +454,14 @@ class OnDiskChainedHashTable {
// Read the key.
const internal_key_type& Key =
InfoObj->ReadKey(LocalPtr, L.first);
return std::make_pair(InfoObj->GetExternalKey(Key),
InfoObj->ReadData(Key, LocalPtr + L.first, L.second));
return InfoObj->ReadData(Key, LocalPtr + L.first, L.second);
}
};
item_iterator item_begin() {
return item_iterator(Base + 4, getNumEntries(), &InfoObj);
data_iterator data_begin() {
return data_iterator(Base + 4, getNumEntries(), &InfoObj);
}
item_iterator item_end() { return item_iterator(); }
data_iterator data_end() { return data_iterator(); }
Info &getInfoObj() { return InfoObj; }

View File

@ -12,6 +12,7 @@ class DStmt<Stmt base, bit abstract = 0> : Stmt<abstract> {
def NullStmt : Stmt;
def CompoundStmt : Stmt;
def LabelStmt : Stmt;
def AttributedStmt : Stmt;
def IfStmt : Stmt;
def SwitchStmt : Stmt;
def WhileStmt : Stmt;

View File

@ -132,6 +132,11 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
IntType SizeType, IntMaxType, UIntMaxType, PtrDiffType, IntPtrType, WCharType,
WIntType, Char16Type, Char32Type, Int64Type, SigAtomicType;
/// Flag whether the Objective-C built-in boolean type should be signed char.
/// Otherwise, when this flag is not set, the normal built-in boolean type is
/// used.
unsigned UseSignedCharForObjCBool : 1;
/// Control whether the alignment of bit-field types is respected when laying
/// out structures. If true, then the alignment of the bit-field type will be
/// used to (a) impact the alignment of the containing structure, and (b)
@ -299,6 +304,16 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
return MCountName;
}
/// useSignedCharForObjCBool - Check if the Objective-C built-in boolean
/// type should be signed char. Otherwise, if this returns false, the
/// normal built-in boolean type should also be used for Objective-C.
bool useSignedCharForObjCBool() const {
return UseSignedCharForObjCBool;
}
void noSignedCharForObjCBool() {
UseSignedCharForObjCBool = false;
}
/// useBitFieldTypeAlignment() - Check whether the alignment of bit-field
/// types is respected when laying out structures.
bool useBitFieldTypeAlignment() const {

View File

@ -105,6 +105,7 @@ TOK(eod) // End of preprocessing directive (end of line inside a
// directive).
TOK(code_completion) // Code completion marker
TOK(cxx_defaultarg_end) // C++ default argument end marker
TOK(cxx_exceptspec_end) // C++ exception-specification end marker
// C99 6.4.9: Comments.
TOK(comment) // Comment (only in -E -C[C] mode)

View File

@ -4,8 +4,11 @@
/* Relative directory for resource files */
#define CLANG_RESOURCE_DIR "${CLANG_RESOURCE_DIR}"
/* Directory where gcc is installed. */
#define GCC_INSTALL_PREFIX "${GCC_INSTALL_PREFIX}"
/* Directories clang will search for headers */
#define C_INCLUDE_DIRS "${C_INCLUDE_DIRS}"
/* Default <path> to all compiler invocations for --sysroot=<path>. */
#define DEFAULT_SYSROOT "${DEFAULT_SYSROOT}"
/* Directory where gcc is installed. */
#define GCC_INSTALL_PREFIX "${GCC_INSTALL_PREFIX}"

View File

@ -9,13 +9,16 @@
/* Relative directory for resource files */
#undef CLANG_RESOURCE_DIR
/* Directory where gcc is installed. */
#undef GCC_INSTALL_PREFIX
/* Directories clang will search for headers */
#undef C_INCLUDE_DIRS
/* Linker version detected at compile time. */
#undef HOST_LINK_VERSION
/* Default <path> to all compiler invocations for --sysroot=<path>. */
#undef DEFAULT_SYSROOT
/* Directory where gcc is installed. */
#undef GCC_INSTALL_PREFIX
#endif

View File

@ -428,9 +428,6 @@ def ast_view : Flag<"-ast-view">,
HelpText<"Build ASTs and view them with GraphViz">;
def print_decl_contexts : Flag<"-print-decl-contexts">,
HelpText<"Print DeclContexts and their Decls">;
def pubnames_dump : Flag<"-pubnames-dump">,
HelpText<"Print all of the public (global) names in the source, e.g., the "
"names of all global declarations and macros">;
def emit_module : Flag<"-emit-module">,
HelpText<"Generate pre-compiled module file from a module map">;
def emit_pth : Flag<"-emit-pth">,

View File

@ -92,6 +92,9 @@ class Compilation {
return FailureResultFiles;
}
/// Returns the sysroot path.
StringRef getSysRoot() const;
/// getArgsForToolChain - Return the derived argument list for the
/// tool chain \arg TC (or the default tool chain, if TC is not
/// specified).

View File

@ -14,7 +14,6 @@
#ifndef LLVM_CLANG_FRONTEND_ASTUNIT_H
#define LLVM_CLANG_FRONTEND_ASTUNIT_H
#include "clang/Index/ASTLocation.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/CodeCompleteConsumer.h"
@ -57,8 +56,6 @@ class SourceManager;
class TargetInfo;
class ASTFrontendAction;
using namespace idx;
/// \brief Utility class for loading a ASTContext from an AST file.
///
class ASTUnit : public ModuleLoader {
@ -134,9 +131,6 @@ class ASTUnit : public ModuleLoader {
/// The name of the original source file used to generate this ASTUnit.
std::string OriginalSourceFile;
// Critical optimization when using clang_getCursor().
ASTLocation LastLoc;
/// \brief The set of diagnostics produced when creating the preamble.
SmallVector<StoredDiagnostic, 4> PreambleDiagnostics;
@ -474,10 +468,6 @@ class ASTUnit : public ModuleLoader {
bool getOwnsRemappedFileBuffers() const { return OwnsRemappedFileBuffers; }
void setOwnsRemappedFileBuffers(bool val) { OwnsRemappedFileBuffers = val; }
void setLastASTLocation(ASTLocation ALoc) { LastLoc = ALoc; }
ASTLocation getLastASTLocation() const { return LastLoc; }
StringRef getMainFileName() const;
typedef std::vector<Decl *>::iterator top_level_iterator;

View File

@ -173,15 +173,6 @@ class PrintPreambleAction : public FrontendAction {
virtual bool usesPreprocessorOnly() const { return true; }
};
class PubnamesDumpAction : public ASTFrontendAction {
protected:
virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
StringRef InFile);
public:
virtual bool hasCodeCompletionSupport() const { return false; }
};
//===----------------------------------------------------------------------===//
// Preprocessor Actions
//===----------------------------------------------------------------------===//

View File

@ -42,7 +42,6 @@ namespace frontend {
PrintDeclContext, ///< Print DeclContext and their Decls.
PrintPreamble, ///< Print the "preamble" of the input file
PrintPreprocessedInput, ///< -E mode.
PubnamesDump, ///< Print all of the "public" names in the source.
RewriteMacros, ///< Expand macros but not #includes.
RewriteObjC, ///< ObjC->C Rewriter.
RewriteTest, ///< Rewriter playground

View File

@ -18,6 +18,8 @@
#include "clang/Frontend/DiagnosticRenderer.h"
struct SourceColumnMap;
namespace clang {
/// \brief Class to encapsulate the logic for formatting and printing a textual
@ -103,15 +105,16 @@ class TextDiagnostic : public DiagnosticRenderer {
SmallVectorImpl<CharSourceRange>& Ranges,
ArrayRef<FixItHint> Hints);
void emitSnippet(StringRef SourceLine);
void highlightRange(const CharSourceRange &R,
unsigned LineNo, FileID FID,
const std::string &SourceLine,
const SourceColumnMap &map,
std::string &CaretLine);
std::string buildFixItInsertionLine(unsigned LineNo,
const char *LineStart,
const char *LineEnd,
const SourceColumnMap &map,
ArrayRef<FixItHint> Hints);
void expandTabs(std::string &SourceLine, std::string &CaretLine);
void emitParseableFixits(ArrayRef<FixItHint> Hints);
};

View File

@ -1,173 +0,0 @@
//===--- ASTLocation.h - A <Decl, Stmt> pair --------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// ASTLocation is Decl or a Stmt and its immediate Decl parent.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_INDEX_ASTLOCATION_H
#define LLVM_CLANG_INDEX_ASTLOCATION_H
#include "clang/AST/TypeLoc.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/Support/Compiler.h"
namespace clang {
class Decl;
class Stmt;
class NamedDecl;
namespace idx {
class TranslationUnit;
/// \brief Represents a Decl or a Stmt and its immediate Decl parent. It's
/// immutable.
///
/// ASTLocation is intended to be used as a "pointer" into the AST. It is either
/// just a Decl, or a Stmt and its Decl parent. Since a single Stmt is devoid
/// of context, its parent Decl provides all the additional missing information
/// like the declaration context, ASTContext, etc.
///
class ASTLocation {
public:
enum NodeKind {
N_Decl, N_NamedRef, N_Stmt, N_Type
};
struct NamedRef {
NamedDecl *ND;
SourceLocation Loc;
NamedRef() : ND(0) { }
NamedRef(NamedDecl *nd, SourceLocation loc) : ND(nd), Loc(loc) { }
};
private:
llvm::PointerIntPair<Decl *, 2, NodeKind> ParentDecl;
union {
Decl *D;
Stmt *Stm;
struct {
NamedDecl *ND;
unsigned RawLoc;
} NDRef;
struct {
void *TyPtr;
void *Data;
} Ty;
};
public:
ASTLocation() { }
explicit ASTLocation(const Decl *d)
: ParentDecl(const_cast<Decl*>(d), N_Decl), D(const_cast<Decl*>(d)) { }
ASTLocation(const Decl *parentDecl, const Stmt *stm)
: ParentDecl(const_cast<Decl*>(parentDecl), N_Stmt),
Stm(const_cast<Stmt*>(stm)) {
if (!stm) ParentDecl.setPointer(0);
}
ASTLocation(const Decl *parentDecl, NamedDecl *ndRef, SourceLocation loc)
: ParentDecl(const_cast<Decl*>(parentDecl), N_NamedRef) {
if (ndRef) {
NDRef.ND = ndRef;
NDRef.RawLoc = loc.getRawEncoding();
} else
ParentDecl.setPointer(0);
}
ASTLocation(const Decl *parentDecl, TypeLoc tyLoc)
: ParentDecl(const_cast<Decl*>(parentDecl), N_Type) {
if (tyLoc) {
Ty.TyPtr = tyLoc.getType().getAsOpaquePtr();
Ty.Data = tyLoc.getOpaqueData();
} else
ParentDecl.setPointer(0);
}
bool isValid() const { return ParentDecl.getPointer() != 0; }
bool isInvalid() const { return !isValid(); }
NodeKind getKind() const {
assert(isValid());
return (NodeKind)ParentDecl.getInt();
}
Decl *getParentDecl() const { return ParentDecl.getPointer(); }
Decl *AsDecl() const {
assert(getKind() == N_Decl);
return D;
}
Stmt *AsStmt() const {
assert(getKind() == N_Stmt);
return Stm;
}
NamedRef AsNamedRef() const {
assert(getKind() == N_NamedRef);
return NamedRef(NDRef.ND, SourceLocation::getFromRawEncoding(NDRef.RawLoc));
}
TypeLoc AsTypeLoc() const {
assert(getKind() == N_Type);
return TypeLoc(QualType::getFromOpaquePtr(Ty.TyPtr), Ty.Data);
}
Decl *dyn_AsDecl() const { return isValid() && getKind() == N_Decl ? D : 0; }
Stmt *dyn_AsStmt() const {
return isValid() && getKind() == N_Stmt ? Stm : 0;
}
NamedRef dyn_AsNamedRef() const {
return getKind() == N_Type ? AsNamedRef() : NamedRef();
}
TypeLoc dyn_AsTypeLoc() const {
return getKind() == N_Type ? AsTypeLoc() : TypeLoc();
}
bool isDecl() const { return isValid() && getKind() == N_Decl; }
bool isStmt() const { return isValid() && getKind() == N_Stmt; }
bool isNamedRef() const { return isValid() && getKind() == N_NamedRef; }
bool isType() const { return isValid() && getKind() == N_Type; }
/// \brief Returns the declaration that this ASTLocation references.
///
/// If this points to a Decl, that Decl is returned.
/// If this points to an Expr that references a Decl, that Decl is returned,
/// otherwise it returns NULL.
Decl *getReferencedDecl();
const Decl *getReferencedDecl() const {
return const_cast<ASTLocation*>(this)->getReferencedDecl();
}
SourceRange getSourceRange() const LLVM_READONLY;
void print(raw_ostream &OS) const;
};
/// \brief Like ASTLocation but also contains the TranslationUnit that the
/// ASTLocation originated from.
class TULocation : public ASTLocation {
TranslationUnit *TU;
public:
TULocation(TranslationUnit *tu, ASTLocation astLoc)
: ASTLocation(astLoc), TU(tu) {
assert(tu && "Passed null translation unit");
}
TranslationUnit *getTU() const { return TU; }
};
} // namespace idx
} // namespace clang
#endif

View File

@ -1,56 +0,0 @@
//===--- Analyzer.h - Analysis for indexing information ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares the Analyzer interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_INDEX_ANALYZER_H
#define LLVM_CLANG_INDEX_ANALYZER_H
namespace clang {
class Decl;
class ObjCMessageExpr;
namespace idx {
class Program;
class IndexProvider;
class TULocationHandler;
/// \brief Provides indexing information, like finding all references of an
/// Entity across translation units.
class Analyzer {
Program &Prog;
IndexProvider &Idxer;
Analyzer(const Analyzer&); // do not implement
Analyzer &operator=(const Analyzer &); // do not implement
public:
explicit Analyzer(Program &prog, IndexProvider &idxer)
: Prog(prog), Idxer(idxer) { }
/// \brief Find all TULocations for declarations of the given Decl and pass
/// them to Handler.
void FindDeclarations(Decl *D, TULocationHandler &Handler);
/// \brief Find all TULocations for references of the given Decl and pass
/// them to Handler.
void FindReferences(Decl *D, TULocationHandler &Handler);
/// \brief Find methods that may respond to the given message and pass them
/// to Handler.
void FindObjCMethods(ObjCMessageExpr *MsgE, TULocationHandler &Handler);
};
} // namespace idx
} // namespace clang
#endif

View File

@ -1,50 +0,0 @@
//===--- DeclReferenceMap.h - Map Decls to their references -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// DeclReferenceMap creates a mapping from Decls to the ASTLocations that
// reference them.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_INDEX_DECLREFERENCEMAP_H
#define LLVM_CLANG_INDEX_DECLREFERENCEMAP_H
#include "clang/Index/ASTLocation.h"
#include "clang/Index/STLExtras.h"
#include <map>
namespace clang {
class ASTContext;
class NamedDecl;
namespace idx {
/// \brief Maps NamedDecls with the ASTLocations that reference them.
///
/// References are mapped and retrieved using the canonical decls.
class DeclReferenceMap {
public:
explicit DeclReferenceMap(ASTContext &Ctx);
typedef std::multimap<NamedDecl*, ASTLocation> MapTy;
typedef pair_value_iterator<MapTy::iterator> astlocation_iterator;
astlocation_iterator refs_begin(NamedDecl *D) const;
astlocation_iterator refs_end(NamedDecl *D) const;
bool refs_empty(NamedDecl *D) const;
private:
mutable MapTy Map;
};
} // end idx namespace
} // end clang namespace
#endif

View File

@ -1,149 +0,0 @@
//===--- Entity.h - Cross-translation-unit "token" for decls ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Entity is a ASTContext-independent way to refer to declarations that are
// visible across translation units.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_INDEX_ENTITY_H
#define LLVM_CLANG_INDEX_ENTITY_H
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include <string>
namespace clang {
class ASTContext;
class Decl;
namespace idx {
class Program;
class EntityImpl;
/// \brief A ASTContext-independent way to refer to declarations.
///
/// Entity is basically the link for declarations that are semantically the same
/// in multiple ASTContexts. A client will convert a Decl into an Entity and
/// later use that Entity to find the "same" Decl into another ASTContext.
/// Declarations that are semantically the same and visible across translation
/// units will be associated with the same Entity.
///
/// An Entity may also refer to declarations that cannot be visible across
/// translation units, e.g. static functions with the same name in multiple
/// translation units will be associated with different Entities.
///
/// Entities can be checked for equality but note that the same Program object
/// should be used when getting Entities.
///
class Entity {
/// \brief Stores the Decl directly if it is not visible outside of its own
/// translation unit, otherwise it stores the associated EntityImpl.
llvm::PointerUnion<Decl *, EntityImpl *> Val;
explicit Entity(Decl *D);
explicit Entity(EntityImpl *impl) : Val(impl) { }
friend class EntityGetter;
public:
Entity() { }
/// \brief Find the Decl that can be referred to by this entity.
Decl *getDecl(ASTContext &AST) const;
/// \brief If this Entity represents a declaration that is internal to its
/// translation unit, getInternalDecl() returns it.
Decl *getInternalDecl() const {
assert(isInternalToTU() && "This Entity is not internal!");
return Val.get<Decl *>();
}
/// \brief Get a printable name for debugging purpose.
std::string getPrintableName() const;
/// \brief Get an Entity associated with the given Decl.
/// \returns invalid Entity if an Entity cannot refer to this Decl.
static Entity get(Decl *D, Program &Prog);
/// \brief Get an Entity associated with a name in the global namespace.
static Entity get(StringRef Name, Program &Prog);
/// \brief true if the Entity is not visible outside the trasnlation unit.
bool isInternalToTU() const {
assert(isValid() && "This Entity is not valid!");
return Val.is<Decl *>();
}
bool isValid() const { return !Val.isNull(); }
bool isInvalid() const { return !isValid(); }
void *getAsOpaquePtr() const { return Val.getOpaqueValue(); }
static Entity getFromOpaquePtr(void *Ptr) {
Entity Ent;
Ent.Val = llvm::PointerUnion<Decl *, EntityImpl *>::getFromOpaqueValue(Ptr);
return Ent;
}
friend bool operator==(const Entity &LHS, const Entity &RHS) {
return LHS.getAsOpaquePtr() == RHS.getAsOpaquePtr();
}
// For use in a std::map.
friend bool operator < (const Entity &LHS, const Entity &RHS) {
return LHS.getAsOpaquePtr() < RHS.getAsOpaquePtr();
}
// For use in DenseMap/DenseSet.
static Entity getEmptyMarker() {
Entity Ent;
Ent.Val =
llvm::PointerUnion<Decl *, EntityImpl *>::getFromOpaqueValue((void*)-1);
return Ent;
}
static Entity getTombstoneMarker() {
Entity Ent;
Ent.Val =
llvm::PointerUnion<Decl *, EntityImpl *>::getFromOpaqueValue((void*)-2);
return Ent;
}
};
} // namespace idx
} // namespace clang
namespace llvm {
/// Define DenseMapInfo so that Entities can be used as keys in DenseMap and
/// DenseSets.
template<>
struct DenseMapInfo<clang::idx::Entity> {
static inline clang::idx::Entity getEmptyKey() {
return clang::idx::Entity::getEmptyMarker();
}
static inline clang::idx::Entity getTombstoneKey() {
return clang::idx::Entity::getTombstoneMarker();
}
static unsigned getHashValue(clang::idx::Entity);
static inline bool
isEqual(clang::idx::Entity LHS, clang::idx::Entity RHS) {
return LHS == RHS;
}
};
template <>
struct isPodLike<clang::idx::Entity> { static const bool value = true; };
} // end namespace llvm
#endif

View File

@ -1,149 +0,0 @@
//== GlobalCallGraph.h - Call graph building --------------------*- C++ -*--==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defined the CallGraph and CallGraphNode classes.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_INDEX_CALLGRAPH
#define LLVM_CLANG_INDEX_CALLGRAPH
#include "clang/Index/ASTLocation.h"
#include "clang/Index/Entity.h"
#include "clang/Index/Program.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/STLExtras.h"
#include <vector>
#include <map>
using namespace clang;
namespace clang {
namespace idx {
class CallGraphNode {
Entity F;
typedef std::pair<ASTLocation, CallGraphNode*> CallRecord;
std::vector<CallRecord> CalledFunctions;
public:
CallGraphNode(Entity f) : F(f) {}
typedef std::vector<CallRecord>::iterator iterator;
typedef std::vector<CallRecord>::const_iterator const_iterator;
iterator begin() { return CalledFunctions.begin(); }
iterator end() { return CalledFunctions.end(); }
const_iterator begin() const { return CalledFunctions.begin(); }
const_iterator end() const { return CalledFunctions.end(); }
void addCallee(ASTLocation L, CallGraphNode *Node) {
CalledFunctions.push_back(std::make_pair(L, Node));
}
bool hasCallee() const { return begin() != end(); }
std::string getName() const { return F.getPrintableName(); }
Decl *getDecl(ASTContext &Ctx) const { return F.getDecl(Ctx); }
};
class CallGraph {
/// Program manages all Entities.
Program &Prog;
typedef std::map<Entity, CallGraphNode *> FunctionMapTy;
/// FunctionMap owns all CallGraphNodes.
FunctionMapTy FunctionMap;
/// CallerCtx maps a caller to its ASTContext.
llvm::DenseMap<CallGraphNode *, ASTContext *> CallerCtx;
/// Root node is the 'main' function or 0.
CallGraphNode *Root;
/// ExternalCallingNode has edges to all external functions.
CallGraphNode *ExternalCallingNode;
public:
CallGraph(Program &P);
~CallGraph();
typedef FunctionMapTy::iterator iterator;
typedef FunctionMapTy::const_iterator const_iterator;
iterator begin() { return FunctionMap.begin(); }
iterator end() { return FunctionMap.end(); }
const_iterator begin() const { return FunctionMap.begin(); }
const_iterator end() const { return FunctionMap.end(); }
CallGraphNode *getRoot() { return Root; }
CallGraphNode *getExternalCallingNode() { return ExternalCallingNode; }
void addTU(ASTContext &AST);
Program &getProgram() { return Prog; }
CallGraphNode *getOrInsertFunction(idx::Entity F);
Decl *getDecl(CallGraphNode *Node);
void print(raw_ostream &os);
void dump();
void ViewCallGraph() const;
};
}} // end clang idx namespace
namespace llvm {
template <> struct GraphTraits<clang::idx::CallGraph> {
typedef clang::idx::CallGraph GraphType;
typedef clang::idx::CallGraphNode NodeType;
typedef std::pair<clang::idx::ASTLocation, NodeType*> CGNPairTy;
typedef std::pointer_to_unary_function<CGNPairTy, NodeType*> CGNDerefFun;
typedef mapped_iterator<NodeType::iterator, CGNDerefFun> ChildIteratorType;
static NodeType *getEntryNode(GraphType *CG) {
return CG->getExternalCallingNode();
}
static ChildIteratorType child_begin(NodeType *N) {
return map_iterator(N->begin(), CGNDerefFun(CGNDeref));
}
static ChildIteratorType child_end(NodeType *N) {
return map_iterator(N->end(), CGNDerefFun(CGNDeref));
}
typedef std::pair<clang::idx::Entity, NodeType*> PairTy;
typedef std::pointer_to_unary_function<PairTy, NodeType*> DerefFun;
typedef mapped_iterator<GraphType::const_iterator, DerefFun> nodes_iterator;
static nodes_iterator nodes_begin(const GraphType &CG) {
return map_iterator(CG.begin(), DerefFun(CGDeref));
}
static nodes_iterator nodes_end(const GraphType &CG) {
return map_iterator(CG.end(), DerefFun(CGDeref));
}
static NodeType *CGNDeref(CGNPairTy P) { return P.second; }
static NodeType *CGDeref(PairTy P) { return P.second; }
};
} // end llvm namespace
#endif

View File

@ -1,100 +0,0 @@
//===--- GlobalSelector.h - Cross-translation-unit "token" for selectors --===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// GlobalSelector is a ASTContext-independent way to refer to selectors.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_INDEX_GLOBALSELECTOR_H
#define LLVM_CLANG_INDEX_GLOBALSELECTOR_H
#include "llvm/ADT/DenseMap.h"
#include <string>
namespace clang {
class ASTContext;
class Selector;
namespace idx {
class Program;
/// \brief A ASTContext-independent way to refer to selectors.
class GlobalSelector {
void *Val;
explicit GlobalSelector(void *val) : Val(val) { }
public:
GlobalSelector() : Val(0) { }
/// \brief Get the ASTContext-specific selector.
Selector getSelector(ASTContext &AST) const;
bool isValid() const { return Val != 0; }
bool isInvalid() const { return !isValid(); }
/// \brief Get a printable name for debugging purpose.
std::string getPrintableName() const;
/// \brief Get a GlobalSelector for the ASTContext-specific selector.
static GlobalSelector get(Selector Sel, Program &Prog);
void *getAsOpaquePtr() const { return Val; }
static GlobalSelector getFromOpaquePtr(void *Ptr) {
return GlobalSelector(Ptr);
}
friend bool operator==(const GlobalSelector &LHS, const GlobalSelector &RHS) {
return LHS.getAsOpaquePtr() == RHS.getAsOpaquePtr();
}
// For use in a std::map.
friend bool operator< (const GlobalSelector &LHS, const GlobalSelector &RHS) {
return LHS.getAsOpaquePtr() < RHS.getAsOpaquePtr();
}
// For use in DenseMap/DenseSet.
static GlobalSelector getEmptyMarker() { return GlobalSelector((void*)-1); }
static GlobalSelector getTombstoneMarker() {
return GlobalSelector((void*)-2);
}
};
} // namespace idx
} // namespace clang
namespace llvm {
/// Define DenseMapInfo so that GlobalSelectors can be used as keys in DenseMap
/// and DenseSets.
template<>
struct DenseMapInfo<clang::idx::GlobalSelector> {
static inline clang::idx::GlobalSelector getEmptyKey() {
return clang::idx::GlobalSelector::getEmptyMarker();
}
static inline clang::idx::GlobalSelector getTombstoneKey() {
return clang::idx::GlobalSelector::getTombstoneMarker();
}
static unsigned getHashValue(clang::idx::GlobalSelector);
static inline bool
isEqual(clang::idx::GlobalSelector LHS, clang::idx::GlobalSelector RHS) {
return LHS == RHS;
}
};
template <>
struct isPodLike<clang::idx::GlobalSelector> { static const bool value = true;};
} // end namespace llvm
#endif

View File

@ -1,82 +0,0 @@
//===--- Handlers.h - Interfaces for receiving information ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Abstract interfaces for receiving information.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_INDEX_HANDLERS_H
#define LLVM_CLANG_INDEX_HANDLERS_H
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/SmallVector.h"
namespace clang {
namespace idx {
class Entity;
class TranslationUnit;
class TULocation;
/// \brief Abstract interface for receiving Entities.
class EntityHandler {
public:
typedef Entity receiving_type;
virtual ~EntityHandler();
virtual void Handle(Entity Ent) = 0;
};
/// \brief Abstract interface for receiving TranslationUnits.
class TranslationUnitHandler {
public:
typedef TranslationUnit* receiving_type;
virtual ~TranslationUnitHandler();
virtual void Handle(TranslationUnit *TU) = 0;
};
/// \brief Abstract interface for receiving TULocations.
class TULocationHandler {
public:
typedef TULocation receiving_type;
virtual ~TULocationHandler();
virtual void Handle(TULocation TULoc) = 0;
};
/// \brief Helper for the Handler classes. Stores the objects into a vector.
/// example:
/// @code
/// Storing<TranslationUnitHandler> TURes;
/// IndexProvider.GetTranslationUnitsFor(Entity, TURes);
/// for (Storing<TranslationUnitHandler>::iterator
/// I = TURes.begin(), E = TURes.end(); I != E; ++I) { ....
/// @endcode
template <typename handler_type>
class Storing : public handler_type {
typedef typename handler_type::receiving_type receiving_type;
typedef SmallVector<receiving_type, 8> StoreTy;
StoreTy Store;
public:
virtual void Handle(receiving_type Obj) {
Store.push_back(Obj);
}
typedef typename StoreTy::const_iterator iterator;
iterator begin() const { return Store.begin(); }
iterator end() const { return Store.end(); }
};
} // namespace idx
} // namespace clang
#endif

View File

@ -1,38 +0,0 @@
//===--- IndexProvider.h - Maps information to translation units -*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Maps information to TranslationUnits.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_INDEX_INDEXPROVIDER_H
#define LLVM_CLANG_INDEX_INDEXPROVIDER_H
namespace clang {
namespace idx {
class Entity;
class TranslationUnitHandler;
class GlobalSelector;
/// \brief Maps information to TranslationUnits.
class IndexProvider {
public:
virtual ~IndexProvider();
virtual void GetTranslationUnitsFor(Entity Ent,
TranslationUnitHandler &Handler) = 0;
virtual void GetTranslationUnitsFor(GlobalSelector Sel,
TranslationUnitHandler &Handler) = 0;
};
} // namespace idx
} // namespace clang
#endif

View File

@ -1,71 +0,0 @@
//===--- Indexer.h - IndexProvider implementation ---------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// IndexProvider implementation.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_INDEX_INDEXER_H
#define LLVM_CLANG_INDEX_INDEXER_H
#include "clang/Index/IndexProvider.h"
#include "clang/Index/Entity.h"
#include "clang/Index/GlobalSelector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/DenseMap.h"
#include <map>
namespace clang {
class ASTContext;
class FunctionDecl;
namespace idx {
class Program;
class TranslationUnit;
/// \brief Maps information to TranslationUnits.
class Indexer : public IndexProvider {
public:
typedef llvm::SmallPtrSet<TranslationUnit *, 4> TUSetTy;
typedef llvm::DenseMap<ASTContext *, TranslationUnit *> CtxTUMapTy;
typedef std::map<Entity, TUSetTy> MapTy;
typedef std::map<GlobalSelector, TUSetTy> SelMapTy;
typedef std::map<Entity, std::pair<FunctionDecl*,TranslationUnit*> > DefMapTy;
explicit Indexer(Program &prog) :
Prog(prog) { }
Program &getProgram() const { return Prog; }
/// \brief Find all Entities and map them to the given translation unit.
void IndexAST(TranslationUnit *TU);
virtual void GetTranslationUnitsFor(Entity Ent,
TranslationUnitHandler &Handler);
virtual void GetTranslationUnitsFor(GlobalSelector Sel,
TranslationUnitHandler &Handler);
std::pair<FunctionDecl*, TranslationUnit*> getDefinitionFor(Entity Ent);
private:
Program &Prog;
MapTy Map;
// Map a function Entity to the its definition.
DefMapTy DefMap;
CtxTUMapTy CtxTUMap;
SelMapTy SelMap;
};
} // namespace idx
} // namespace clang
#endif

View File

@ -1,45 +0,0 @@
//===--- Program.h - Cross-translation unit information ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares the idx::Program interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_INDEX_PROGRAM_H
#define LLVM_CLANG_INDEX_PROGRAM_H
namespace clang {
class ASTContext;
namespace idx {
class EntityHandler;
/// \brief Top level object that owns and maintains information
/// that is common across translation units.
class Program {
void *Impl;
Program(const Program&); // do not implement
Program &operator=(const Program &); // do not implement
friend class Entity;
friend class GlobalSelector;
public:
Program();
~Program();
/// \brief Traverses the AST and passes all the entities to the Handler.
void FindEntities(ASTContext &Ctx, EntityHandler &Handler);
};
} // namespace idx
} // namespace clang
#endif

View File

@ -1,63 +0,0 @@
//===--- STLExtras.h - Helper STL related templates -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Helper templates for using with the STL.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_INDEX_STLEXTRAS_H
#define LLVM_CLANG_INDEX_STLEXTRAS_H
namespace clang {
namespace idx {
/// \brief Wraps an iterator whose value_type is a pair, and provides
/// pair's second object as the value.
template <typename iter_type>
class pair_value_iterator {
iter_type I;
public:
typedef typename iter_type::value_type::second_type value_type;
typedef value_type& reference;
typedef value_type* pointer;
typedef typename iter_type::iterator_category iterator_category;
typedef typename iter_type::difference_type difference_type;
pair_value_iterator() { }
pair_value_iterator(iter_type i) : I(i) { }
reference operator*() const { return I->second; }
pointer operator->() const { return &I->second; }
pair_value_iterator& operator++() {
++I;
return *this;
}
pair_value_iterator operator++(int) {
pair_value_iterator tmp(*this);
++(*this);
return tmp;
}
friend bool operator==(pair_value_iterator L, pair_value_iterator R) {
return L.I == R.I;
}
friend bool operator!=(pair_value_iterator L, pair_value_iterator R) {
return L.I != R.I;
}
};
} // end idx namespace
} // end clang namespace
#endif

View File

@ -1,57 +0,0 @@
//===--- SelectorMap.h - Maps selectors to methods and messages -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// SelectorMap creates a mapping from selectors to ObjC method declarations
// and ObjC message expressions.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_INDEX_SELECTORMAP_H
#define LLVM_CLANG_INDEX_SELECTORMAP_H
#include "clang/Index/ASTLocation.h"
#include "clang/Index/STLExtras.h"
#include "clang/Basic/IdentifierTable.h"
#include <map>
namespace clang {
class ASTContext;
class ObjCMethodDecl;
namespace idx {
/// \brief Maps NamedDecls with the ASTLocations that reference them.
///
/// References are mapped and retrieved using the canonical decls.
class SelectorMap {
public:
explicit SelectorMap(ASTContext &Ctx);
typedef std::multimap<Selector, ObjCMethodDecl *> SelMethMapTy;
typedef std::multimap<Selector, ASTLocation> SelRefMapTy;
typedef pair_value_iterator<SelMethMapTy::iterator> method_iterator;
typedef pair_value_iterator<SelRefMapTy::iterator> astlocation_iterator;
method_iterator methods_begin(Selector Sel) const;
method_iterator methods_end(Selector Sel) const;
astlocation_iterator refs_begin(Selector Sel) const;
astlocation_iterator refs_end(Selector Sel) const;
private:
mutable SelMethMapTy SelMethMap;
mutable SelRefMapTy SelRefMap;
};
} // end idx namespace
} // end clang namespace
#endif

View File

@ -1,41 +0,0 @@
//===--- TranslationUnit.h - Interface for a translation unit ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Abstract interface for a translation unit.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_INDEX_TRANSLATIONUNIT_H
#define LLVM_CLANG_INDEX_TRANSLATIONUNIT_H
namespace clang {
class ASTContext;
class DiagnosticsEngine;
class Preprocessor;
namespace idx {
class DeclReferenceMap;
class SelectorMap;
/// \brief Abstract interface for a translation unit.
class TranslationUnit {
public:
virtual ~TranslationUnit();
virtual ASTContext &getASTContext() = 0;
virtual Preprocessor &getPreprocessor() = 0;
virtual DiagnosticsEngine &getDiagnostic() = 0;
virtual DeclReferenceMap &getDeclReferenceMap() = 0;
virtual SelectorMap &getSelectorMap() = 0;
};
} // namespace idx
} // namespace clang
#endif

View File

@ -15,7 +15,6 @@
#define LLVM_CLANG_PARSE_PARSER_H
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/DelayedCleanupPool.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/CodeCompletionHandler.h"
#include "clang/Sema/Sema.h"
@ -192,9 +191,9 @@ class Parser : public CodeCompletionHandler {
/// Factory object for creating AttributeList objects.
AttributeFactory AttrFactory;
/// \brief Gathers and cleans up objects when parsing of a top-level
/// declaration is finished.
DelayedCleanupPool TopLevelDeclCleanupPool;
/// \brief Gathers and cleans up TemplateIdAnnotations when parsing of a
/// top-level declaration is finished.
SmallVector<TemplateIdAnnotation *, 16> TemplateIds;
IdentifierInfo *getSEHExceptKeyword();
@ -568,9 +567,7 @@ class Parser : public CodeCompletionHandler {
const char *&PrevSpec, unsigned &DiagID,
bool &isInvalid);
/// \brief Get the TemplateIdAnnotation from the token and put it in the
/// cleanup pool so that it gets destroyed when parsing the current top level
/// declaration is finished.
/// \brief Get the TemplateIdAnnotation from the token.
TemplateIdAnnotation *takeTemplateIdAnnotation(const Token &tok);
/// TentativeParsingAction - An object that is used as a kind of "tentative
@ -858,7 +855,7 @@ class Parser : public CodeCompletionHandler {
/// argument (C++ [class.mem]p2).
struct LateParsedMethodDeclaration : public LateParsedDeclaration {
explicit LateParsedMethodDeclaration(Parser *P, Decl *M)
: Self(P), Method(M), TemplateScope(false) { }
: Self(P), Method(M), TemplateScope(false), ExceptionSpecTokens(0) { }
virtual void ParseLexedMethodDeclarations();
@ -878,6 +875,10 @@ class Parser : public CodeCompletionHandler {
/// method will be stored so that they can be reintroduced into
/// scope at the appropriate times.
SmallVector<LateParsedDefaultArgument, 8> DefaultArgs;
/// \brief The set of tokens that make up an exception-specification that
/// has not yet been parsed.
CachedTokens *ExceptionSpecTokens;
};
/// LateParsedMemberInitializer - An initializer for a non-static class data
@ -1420,11 +1421,13 @@ class Parser : public CodeCompletionHandler {
// C++ 15: C++ Throw Expression
ExprResult ParseThrowExpression();
ExceptionSpecificationType MaybeParseExceptionSpecification(
ExceptionSpecificationType tryParseExceptionSpecification(
bool Delayed,
SourceRange &SpecificationRange,
SmallVectorImpl<ParsedType> &DynamicExceptions,
SmallVectorImpl<SourceRange> &DynamicExceptionRanges,
ExprResult &NoexceptExpr);
ExprResult &NoexceptExpr,
CachedTokens *&ExceptionSpecTokens);
// EndLoc is filled with the location of the last token of the specification.
ExceptionSpecificationType ParseDynamicExceptionSpecification(
@ -1517,42 +1520,40 @@ class Parser : public CodeCompletionHandler {
//===--------------------------------------------------------------------===//
// C99 6.8: Statements and Blocks.
StmtResult ParseStatement(SourceLocation *TrailingElseLoc = NULL) {
StmtResult ParseStatement(SourceLocation *TrailingElseLoc = 0) {
StmtVector Stmts(Actions);
return ParseStatementOrDeclaration(Stmts, true, TrailingElseLoc);
}
StmtResult ParseStatementOrDeclaration(StmtVector& Stmts,
StmtResult ParseStatementOrDeclaration(StmtVector &Stmts,
bool OnlyStatement,
SourceLocation *TrailingElseLoc = NULL);
StmtResult ParseExprStatement(ParsedAttributes &Attrs);
StmtResult ParseLabeledStatement(ParsedAttributes &Attr);
StmtResult ParseCaseStatement(ParsedAttributes &Attr,
bool MissingCase = false,
SourceLocation *TrailingElseLoc = 0);
StmtResult ParseStatementOrDeclarationAfterAttributes(
StmtVector &Stmts,
bool OnlyStatement,
SourceLocation *TrailingElseLoc,
ParsedAttributesWithRange &Attrs);
StmtResult ParseExprStatement();
StmtResult ParseLabeledStatement(ParsedAttributesWithRange &attrs);
StmtResult ParseCaseStatement(bool MissingCase = false,
ExprResult Expr = ExprResult());
StmtResult ParseDefaultStatement(ParsedAttributes &Attr);
StmtResult ParseCompoundStatement(ParsedAttributes &Attr,
bool isStmtExpr = false);
StmtResult ParseCompoundStatement(ParsedAttributes &Attr,
bool isStmtExpr,
StmtResult ParseDefaultStatement();
StmtResult ParseCompoundStatement(bool isStmtExpr = false);
StmtResult ParseCompoundStatement(bool isStmtExpr,
unsigned ScopeFlags);
StmtResult ParseCompoundStatementBody(bool isStmtExpr = false);
bool ParseParenExprOrCondition(ExprResult &ExprResult,
Decl *&DeclResult,
SourceLocation Loc,
bool ConvertToBoolean);
StmtResult ParseIfStatement(ParsedAttributes &Attr,
SourceLocation *TrailingElseLoc);
StmtResult ParseSwitchStatement(ParsedAttributes &Attr,
SourceLocation *TrailingElseLoc);
StmtResult ParseWhileStatement(ParsedAttributes &Attr,
SourceLocation *TrailingElseLoc);
StmtResult ParseDoStatement(ParsedAttributes &Attr);
StmtResult ParseForStatement(ParsedAttributes &Attr,
SourceLocation *TrailingElseLoc);
StmtResult ParseGotoStatement(ParsedAttributes &Attr);
StmtResult ParseContinueStatement(ParsedAttributes &Attr);
StmtResult ParseBreakStatement(ParsedAttributes &Attr);
StmtResult ParseReturnStatement(ParsedAttributes &Attr);
StmtResult ParseIfStatement(SourceLocation *TrailingElseLoc);
StmtResult ParseSwitchStatement(SourceLocation *TrailingElseLoc);
StmtResult ParseWhileStatement(SourceLocation *TrailingElseLoc);
StmtResult ParseDoStatement();
StmtResult ParseForStatement(SourceLocation *TrailingElseLoc);
StmtResult ParseGotoStatement();
StmtResult ParseContinueStatement();
StmtResult ParseBreakStatement();
StmtResult ParseReturnStatement();
StmtResult ParseAsmStatement(bool &msAsm);
StmtResult ParseMicrosoftAsmStatement(SourceLocation AsmLoc);
@ -1586,7 +1587,7 @@ class Parser : public CodeCompletionHandler {
/// \brief The behavior of this __if_exists or __if_not_exists block
/// should.
IfExistsBehavior Behavior;
};
};
bool ParseMicrosoftIfExistsCondition(IfExistsCondition& Result);
void ParseMicrosoftIfExistsStatement(StmtVector &Stmts);
@ -1602,14 +1603,14 @@ class Parser : public CodeCompletionHandler {
//===--------------------------------------------------------------------===//
// C++ 6: Statements and Blocks
StmtResult ParseCXXTryBlock(ParsedAttributes &Attr);
StmtResult ParseCXXTryBlock();
StmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc);
StmtResult ParseCXXCatchBlock();
//===--------------------------------------------------------------------===//
// MS: SEH Statements and Blocks
StmtResult ParseSEHTryBlock(ParsedAttributes &Attr);
StmtResult ParseSEHTryBlock();
StmtResult ParseSEHTryBlockCommon(SourceLocation Loc);
StmtResult ParseSEHExceptBlock(SourceLocation Loc);
StmtResult ParseSEHFinallyBlock(SourceLocation Loc);
@ -1883,6 +1884,7 @@ class Parser : public CodeCompletionHandler {
void ProhibitAttributes(ParsedAttributesWithRange &attrs) {
if (!attrs.Range.isValid()) return;
DiagnoseProhibitedAttributes(attrs);
attrs.clear();
}
void DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs);
@ -1967,7 +1969,7 @@ class Parser : public CodeCompletionHandler {
void ParseTypeofSpecifier(DeclSpec &DS);
SourceLocation ParseDecltypeSpecifier(DeclSpec &DS);
void AnnotateExistingDecltypeSpecifier(const DeclSpec &DS,
void AnnotateExistingDecltypeSpecifier(const DeclSpec &DS,
SourceLocation StartLoc,
SourceLocation EndLoc);
void ParseUnderlyingTypeSpecifier(DeclSpec &DS);
@ -2106,8 +2108,8 @@ class Parser : public CodeCompletionHandler {
ParsingDeclRAIIObject *DiagsFromTParams = 0);
void ParseConstructorInitializer(Decl *ConstructorDecl);
MemInitResult ParseMemInitializer(Decl *ConstructorDecl);
void HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo,
Decl *ThisDecl);
void HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo,
Decl *ThisDecl);
//===--------------------------------------------------------------------===//
// C++ 10: Derived classes [class.derived]

View File

@ -1150,6 +1150,10 @@ struct DeclaratorChunk {
/// \brief Pointer to the expression in the noexcept-specifier of this
/// function, if it has one.
Expr *NoexceptExpr;
/// \brief Pointer to the cached tokens for an exception-specification
/// that has not yet been parsed.
CachedTokens *ExceptionSpecTokens;
};
/// TrailingReturnType - If this isn't null, it's the trailing return type
@ -1172,6 +1176,8 @@ struct DeclaratorChunk {
delete[] ArgInfo;
if (getExceptionSpecType() == EST_Dynamic)
delete[] Exceptions;
else if (getExceptionSpecType() == EST_Delayed)
delete ExceptionSpecTokens;
}
/// isKNRPrototype - Return true if this is a K&R style identifier list,
@ -1347,6 +1353,7 @@ struct DeclaratorChunk {
SourceRange *ExceptionRanges,
unsigned NumExceptions,
Expr *NoexceptExpr,
CachedTokens *ExceptionSpecTokens,
SourceLocation LocalRangeBegin,
SourceLocation LocalRangeEnd,
Declarator &TheDeclarator,

View File

@ -178,8 +178,11 @@ namespace clang {
ParsedTemplateArgument *getTemplateArgs() {
return reinterpret_cast<ParsedTemplateArgument *>(this + 1);
}
static TemplateIdAnnotation* Allocate(unsigned NumArgs) {
/// \brief Creates a new TemplateIdAnnotation with NumArgs arguments and
/// appends it to List.
static TemplateIdAnnotation *
Allocate(unsigned NumArgs, SmallVectorImpl<TemplateIdAnnotation*> &List) {
TemplateIdAnnotation *TemplateId
= (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) +
sizeof(ParsedTemplateArgument) * NumArgs);
@ -193,6 +196,7 @@ namespace clang {
for (unsigned I = 0; I != NumArgs; ++I)
new (TemplateArgs + I) ParsedTemplateArgument();
List.push_back(TemplateId);
return TemplateId;
}

View File

@ -81,13 +81,8 @@ class Scope {
/// SwitchScope - This is a scope that corresponds to a switch statement.
SwitchScope = 0x800,
/// ThisScope - This is the scope of a struct/union/class definition,
/// outside of any member function definition, where 'this' is nonetheless
/// usable.
ThisScope = 0x1000,
/// TryScope - This is the scope of a C++ try statement.
TryScope = 0x2000
TryScope = 0x1000
};
private:
/// The parent scope for this scope. This is null for the translation-unit

View File

@ -446,11 +446,13 @@ class Sema {
Sema &S;
DeclContext *SavedContext;
ProcessingContextState SavedContextState;
QualType SavedCXXThisTypeOverride;
public:
ContextRAII(Sema &S, DeclContext *ContextToPush)
: S(S), SavedContext(S.CurContext),
SavedContextState(S.DelayedDiagnostics.pushContext())
SavedContextState(S.DelayedDiagnostics.pushContext()),
SavedCXXThisTypeOverride(S.CXXThisTypeOverride)
{
assert(ContextToPush && "pushing null context");
S.CurContext = ContextToPush;
@ -460,6 +462,7 @@ class Sema {
if (!SavedContext) return;
S.CurContext = SavedContext;
S.DelayedDiagnostics.popContext(SavedContextState);
S.CXXThisTypeOverride = SavedCXXThisTypeOverride;
SavedContext = 0;
}
@ -646,7 +649,7 @@ class Sema {
/// A stack of expression evaluation contexts.
SmallVector<ExpressionEvaluationContextRecord, 8> ExprEvalContexts;
/// SpecialMemberOverloadResult - The overloading result for a special member
/// function.
///
@ -898,11 +901,15 @@ class Sema {
TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy);
TypeSourceInfo *GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
TypeSourceInfo *ReturnTypeInfo);
/// \brief Package the given type and TSI into a ParsedType.
ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo);
DeclarationNameInfo GetNameForDeclarator(Declarator &D);
DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name);
static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo = 0);
CanThrowResult canThrow(const Expr *E);
const FunctionProtoType *ResolveExceptionSpec(SourceLocation Loc,
const FunctionProtoType *FPT);
bool CheckSpecifiedExceptionType(QualType T, const SourceRange &Range);
bool CheckDistantExceptionSpec(QualType T);
bool CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New);
@ -1974,6 +1981,10 @@ class Sema {
bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC);
bool CheckNoReturnAttr(const AttributeList &attr);
/// \brief Stmt attributes - this routine is the top level dispatcher.
StmtResult ProcessStmtAttributes(Stmt *Stmt, AttributeList *Attrs,
SourceRange Range);
void WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method,
bool &IncompleteImpl, unsigned DiagID);
void WarnConflictingTypedMethods(ObjCMethodDecl *Method,
@ -2251,6 +2262,9 @@ class Sema {
StmtResult ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
SourceLocation ColonLoc, Stmt *SubStmt);
StmtResult ActOnAttributedStmt(SourceLocation AttrLoc, const AttrVec &Attrs,
Stmt *SubStmt);
StmtResult ActOnIfStmt(SourceLocation IfLoc,
FullExprArg CondVal, Decl *CondVar,
Stmt *ThenVal,
@ -3039,7 +3053,7 @@ class Sema {
/// implicitly-declared special member functions.
class ImplicitExceptionSpecification {
// Pointer to allow copying
ASTContext *Context;
Sema *Self;
// We order exception specifications thus:
// noexcept is the most restrictive, but is only used in C++0x.
// throw() comes next.
@ -3063,9 +3077,9 @@ class Sema {
}
public:
explicit ImplicitExceptionSpecification(ASTContext &Context)
: Context(&Context), ComputedEST(EST_BasicNoexcept) {
if (!Context.getLangOpts().CPlusPlus0x)
explicit ImplicitExceptionSpecification(Sema &Self)
: Self(&Self), ComputedEST(EST_BasicNoexcept) {
if (!Self.Context.getLangOpts().CPlusPlus0x)
ComputedEST = EST_DynamicNone;
}
@ -3083,7 +3097,7 @@ class Sema {
const QualType *data() const { return Exceptions.data(); }
/// \brief Integrate another called method into the collected data.
void CalledDecl(CXXMethodDecl *Method);
void CalledDecl(SourceLocation CallLoc, CXXMethodDecl *Method);
/// \brief Integrate an invoked expression into the collected data.
void CalledExpr(Expr *E);
@ -3135,6 +3149,25 @@ class Sema {
ImplicitExceptionSpecification
ComputeDefaultedDtorExceptionSpec(CXXRecordDecl *ClassDecl);
/// \brief Check the given exception-specification and update the
/// extended prototype information with the results.
void checkExceptionSpecification(ExceptionSpecificationType EST,
ArrayRef<ParsedType> DynamicExceptions,
ArrayRef<SourceRange> DynamicExceptionRanges,
Expr *NoexceptExpr,
llvm::SmallVectorImpl<QualType> &Exceptions,
FunctionProtoType::ExtProtoInfo &EPI);
/// \brief Add an exception-specification to the given member function
/// (or member function template). The exception-specification was parsed
/// after the method itself was declared.
void actOnDelayedExceptionSpecification(Decl *Method,
ExceptionSpecificationType EST,
SourceRange SpecificationRange,
ArrayRef<ParsedType> DynamicExceptions,
ArrayRef<SourceRange> DynamicExceptionRanges,
Expr *NoexceptExpr);
/// \brief Determine if a special member function should have a deleted
/// definition when it is defaulted.
bool ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
@ -3240,6 +3273,22 @@ class Sema {
/// special member function.
bool isImplicitlyDeleted(FunctionDecl *FD);
/// \brief Check whether 'this' shows up in the type of a static member
/// function after the (naturally empty) cv-qualifier-seq would be.
///
/// \returns true if an error occurred.
bool checkThisInStaticMemberFunctionType(CXXMethodDecl *Method);
/// \brief Whether this' shows up in the exception specification of a static
/// member function.
bool checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method);
/// \brief Check whether 'this' shows up in the attributes of the given
/// static member function.
///
/// \returns true if an error occurred.
bool checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method);
/// MaybeBindToTemporary - If the passed in expression has a record type with
/// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise
/// it simply returns the passed in expression.
@ -3321,6 +3370,29 @@ class Sema {
/// \returns The type of 'this', if possible. Otherwise, returns a NULL type.
QualType getCurrentThisType();
/// \brief When non-NULL, the C++ 'this' expression is allowed despite the
/// current context not being a non-static member function. In such cases,
/// this provides the type used for 'this'.
QualType CXXThisTypeOverride;
/// \brief RAII object used to temporarily allow the C++ 'this' expression
/// to be used, with the given qualifiers on the current class type.
class CXXThisScopeRAII {
Sema &S;
QualType OldCXXThisTypeOverride;
bool Enabled;
public:
/// \brief Introduce a new scope where 'this' may be allowed (when enabled),
/// using the given declaration (which is either a class template or a
/// class) along with the given qualifiers.
/// along with the qualifiers placed on '*this'.
CXXThisScopeRAII(Sema &S, Decl *ContextDecl, unsigned CXXThisTypeQuals,
bool Enabled = true);
~CXXThisScopeRAII();
};
/// \brief Make sure the value of 'this' is actually available in the current
/// context, if it is a potentially evaluated context.
///
@ -3330,6 +3402,11 @@ class Sema {
/// capture list.
void CheckCXXThisCapture(SourceLocation Loc, bool Explicit = false);
/// \brief Determine whether the given type is the type of *this that is used
/// outside of the body of a member function for a type that is currently
/// being defined.
bool isThisOutsideMemberFunctionBody(QualType BaseType);
/// ActOnCXXBoolLiteral - Parse {true,false} literals.
ExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
@ -5120,7 +5197,11 @@ class Sema {
/// We are checking the validity of a default template argument that
/// has been used when naming a template-id.
DefaultTemplateArgumentChecking
DefaultTemplateArgumentChecking,
/// We are instantiating the exception specification for a function
/// template which was deferred until it was needed.
ExceptionSpecInstantiation
} Kind;
/// \brief The point of instantiation within the source code.
@ -5168,6 +5249,7 @@ class Sema {
switch (X.Kind) {
case TemplateInstantiation:
case ExceptionSpecInstantiation:
return true;
case PriorTemplateArgumentSubstitution:
@ -5285,6 +5367,13 @@ class Sema {
Decl *Entity,
SourceRange InstantiationRange = SourceRange());
struct ExceptionSpecification {};
/// \brief Note that we are instantiating an exception specification
/// of a function template.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
FunctionDecl *Entity, ExceptionSpecification,
SourceRange InstantiationRange = SourceRange());
/// \brief Note that we are instantiating a default argument in a
/// template-id.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
@ -5474,7 +5563,9 @@ class Sema {
TypeSourceInfo *SubstFunctionDeclType(TypeSourceInfo *T,
const MultiLevelTemplateArgumentList &TemplateArgs,
SourceLocation Loc,
DeclarationName Entity);
DeclarationName Entity,
CXXRecordDecl *ThisContext,
unsigned ThisTypeQuals);
ParmVarDecl *SubstParmVarDecl(ParmVarDecl *D,
const MultiLevelTemplateArgumentList &TemplateArgs,
int indexAdjustment,
@ -5582,6 +5673,8 @@ class Sema {
TemplateArgumentListInfo &Result,
const MultiLevelTemplateArgumentList &TemplateArgs);
void InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
FunctionDecl *Function);
void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
FunctionDecl *Function,
bool Recursive = false,
@ -6463,11 +6556,11 @@ class Sema {
/// and reports the appropriate diagnostics. Returns false on success.
/// Can optionally return the value of the expression.
ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
PartialDiagnostic Diag,
const PartialDiagnostic &Diag,
bool AllowFold,
PartialDiagnostic FoldDiag);
const PartialDiagnostic &FoldDiag);
ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
PartialDiagnostic Diag,
const PartialDiagnostic &Diag,
bool AllowFold = true) {
return VerifyIntegerConstantExpression(E, Result, Diag, AllowFold,
PDiag(0));

View File

@ -964,6 +964,8 @@ namespace clang {
STMT_DEFAULT,
/// \brief A LabelStmt record.
STMT_LABEL,
/// \brief An AttributedStmt record.
STMT_ATTRIBUTED,
/// \brief An IfStmt record.
STMT_IF,
/// \brief A SwitchStmt record.

View File

@ -170,6 +170,9 @@ class ReadMethodPoolVisitor;
namespace reader {
class ASTIdentifierLookupTrait;
/// \brief The on-disk hash table used for the DeclContext's Name lookup table.
typedef OnDiskChainedHashTable<ASTDeclContextNameLookupTrait>
ASTDeclContextNameLookupTable;
}
} // end namespace serialization
@ -323,7 +326,9 @@ class ASTReader
// TU, and when we read those update records, the actual context will not
// be available yet (unless it's the TU), so have this pending map using the
// ID as a key. It will be realized when the context is actually loaded.
typedef SmallVector<std::pair<void *, ModuleFile*>, 1> DeclContextVisibleUpdates;
typedef
SmallVector<std::pair<serialization::reader::ASTDeclContextNameLookupTable *,
ModuleFile*>, 1> DeclContextVisibleUpdates;
typedef llvm::DenseMap<serialization::DeclID, DeclContextVisibleUpdates>
DeclContextVisibleUpdatesPending;
@ -1467,7 +1472,7 @@ class ASTReader
llvm::DenseMap<IdentifierInfo *, uint64_t>::iterator Pos);
/// \brief Load all external visible decls in the given DeclContext.
void completeVisibleDeclsMap(DeclContext *DC);
void completeVisibleDeclsMap(const DeclContext *DC);
/// \brief Retrieve the AST context that this AST reader supplements.
ASTContext &getContext() { return Context; }

View File

@ -76,6 +76,7 @@ class ASTWriter : public ASTDeserializationListener,
typedef SmallVectorImpl<uint64_t> RecordDataImpl;
friend class ASTDeclWriter;
friend class ASTStmtWriter;
private:
/// \brief Map that provides the ID numbers of each type within the
/// output stream, plus those deserialized from a chained PCH.

View File

@ -27,9 +27,14 @@ namespace clang {
class DeclContext;
class Module;
template<typename Info> class OnDiskChainedHashTable;
namespace serialization {
namespace reader {
class ASTDeclContextNameLookupTrait;
}
/// \brief Specifies the kind of module that has been loaded.
enum ModuleKind {
MK_Module, ///< File is a module proper.
@ -43,7 +48,8 @@ struct DeclContextInfo {
DeclContextInfo()
: NameLookupTableData(), LexicalDecls(), NumLexicalDecls() {}
void *NameLookupTableData; // an ASTDeclContextNameLookupTable.
OnDiskChainedHashTable<reader::ASTDeclContextNameLookupTrait>
*NameLookupTableData; // an ASTDeclContextNameLookupTable.
const KindDeclIDPair *LexicalDecls;
unsigned NumLexicalDecls;
};

View File

@ -22,11 +22,6 @@
namespace clang {
namespace idx {
class Indexer;
class TranslationUnit;
}
namespace ento {
class CheckerManager;
@ -46,11 +41,6 @@ class AnalysisManager : public BugReporterData {
CheckerManager *CheckerMgr;
/// \brief Provide function definitions in other translation units. This is
/// NULL if we don't have multiple translation units. AnalysisManager does
/// not own the Indexer.
idx::Indexer *Idxer;
enum AnalysisScope { ScopeTU, ScopeDecl } AScope;
/// \brief The maximum number of exploded nodes the analyzer will generate.
@ -99,7 +89,6 @@ class AnalysisManager : public BugReporterData {
StoreManagerCreator storemgr,
ConstraintManagerCreator constraintmgr,
CheckerManager *checkerMgr,
idx::Indexer *idxer,
unsigned maxnodes, unsigned maxvisit,
bool vizdot, bool vizubi, AnalysisPurgeMode purge,
bool eager, bool trim,
@ -137,8 +126,6 @@ class AnalysisManager : public BugReporterData {
CheckerManager *getCheckerManager() const { return CheckerMgr; }
idx::Indexer *getIndexer() const { return Idxer; }
virtual ASTContext &getASTContext() {
return Ctx;
}
@ -186,10 +173,6 @@ class AnalysisManager : public BugReporterData {
bool shouldInlineCall() const { return (IPAMode == Inlining); }
bool hasIndexer() const { return Idxer != 0; }
AnalysisDeclContext *getAnalysisDeclContextInAnotherTU(const Decl *D);
CFG *getCFG(Decl const *D) {
return AnaCtxMgr.getContext(D)->getCFG();
}

View File

@ -425,10 +425,12 @@ class MemRegionVal : public Loc {
public:
explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {}
/// \brief Get the underlining region.
const MemRegion* getRegion() const {
return static_cast<const MemRegion*>(Data);
}
/// \brief Get the underlining region and strip casts.
const MemRegion* stripCasts() const;
template <typename REGION>

View File

@ -33,22 +33,21 @@
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/YAMLParser.h"
#include <string>
#include <vector>
namespace llvm {
class MemoryBuffer;
} // end namespace llvm
namespace clang {
namespace tooling {
/// \brief Specifies the working directory and command of a compilation.
struct CompileCommand {
CompileCommand() {}
CompileCommand(StringRef Directory, ArrayRef<std::string> CommandLine)
: Directory(Directory), CommandLine(CommandLine) {}
CompileCommand(Twine Directory, ArrayRef<std::string> CommandLine)
: Directory(Directory.str()), CommandLine(CommandLine) {}
/// \brief The working directory the command was executed from.
std::string Directory;
@ -95,6 +94,59 @@ class CompilationDatabase {
StringRef FilePath) const = 0;
};
/// \brief A compilation database that returns a single compile command line.
///
/// Useful when we want a tool to behave more like a compiler invocation.
class FixedCompilationDatabase : public CompilationDatabase {
public:
/// \brief Creates a FixedCompilationDatabase from the arguments after "--".
///
/// Parses the given command line for "--". If "--" is found, the rest of
/// the arguments will make up the command line in the returned
/// FixedCompilationDatabase.
/// The arguments after "--" must not include positional parameters or the
/// argv[0] of the tool. Those will be added by the FixedCompilationDatabase
/// when a CompileCommand is requested. The argv[0] of the returned command
/// line will be "clang-tool".
///
/// Returns NULL in case "--" is not found.
///
/// The argument list is meant to be compatible with normal llvm command line
/// parsing in main methods.
/// int main(int argc, char **argv) {
/// llvm::OwningPtr<FixedCompilationDatabase> Compilations(
/// FixedCompilationDatabase::loadFromCommandLine(argc, argv));
/// cl::ParseCommandLineOptions(argc, argv);
/// ...
/// }
///
/// \param Argc The number of command line arguments - will be changed to
/// the number of arguments before "--", if "--" was found in the argument
/// list.
/// \param Argv Points to the command line arguments.
/// \param Directory The base directory used in the FixedCompilationDatabase.
static FixedCompilationDatabase *loadFromCommandLine(int &Argc,
const char **Argv,
Twine Directory = ".");
/// \brief Constructs a compilation data base from a specified directory
/// and command line.
FixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine);
/// \brief Returns the given compile command.
///
/// Will always return a vector with one entry that contains the directory
/// and command line specified at construction with "clang-tool" as argv[0]
/// and 'FilePath' as positional argument.
virtual std::vector<CompileCommand> getCompileCommands(
StringRef FilePath) const;
private:
/// This is built up to contain a single entry vector to be returned from
/// getCompileCommands after adding the positional argument.
std::vector<CompileCommand> CompileCommands;
};
/// \brief A JSON based compilation database.
///
/// JSON compilation database files must contain a list of JSON objects which
@ -114,7 +166,6 @@ class CompilationDatabase {
/// by setting the flag -DCMAKE_EXPORT_COMPILE_COMMANDS.
class JSONCompilationDatabase : public CompilationDatabase {
public:
/// \brief Loads a JSON compilation database from the specified file.
///
/// Returns NULL and sets ErrorMessage if the database could not be
@ -139,7 +190,7 @@ class JSONCompilationDatabase : public CompilationDatabase {
private:
/// \brief Constructs a JSON compilation database on a memory buffer.
JSONCompilationDatabase(llvm::MemoryBuffer *Database)
: Database(Database) {}
: Database(Database), YAMLStream(Database->getBuffer(), SM) {}
/// \brief Parses the database file and creates the index.
///
@ -147,14 +198,17 @@ class JSONCompilationDatabase : public CompilationDatabase {
/// failed.
bool parse(std::string &ErrorMessage);
// Tuple (directory, commandline) where 'commandline' is a JSON escaped bash
// escaped command line.
typedef std::pair<StringRef, StringRef> CompileCommandRef;
// Tuple (directory, commandline) where 'commandline' pointing to the
// corresponding nodes in the YAML stream.
typedef std::pair<llvm::yaml::ScalarNode*,
llvm::yaml::ScalarNode*> CompileCommandRef;
// Maps file paths to the compile command lines for that file.
llvm::StringMap< std::vector<CompileCommandRef> > IndexByFile;
llvm::OwningPtr<llvm::MemoryBuffer> Database;
llvm::SourceMgr SM;
llvm::yaml::Stream YAMLStream;
};
} // end namespace tooling

View File

@ -481,7 +481,8 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) {
InitBuiltinType(ObjCBuiltinSelTy, BuiltinType::ObjCSel);
// Builtin type for __objc_yes and __objc_no
ObjCBuiltinBoolTy = SignedCharTy;
ObjCBuiltinBoolTy = (Target.useSignedCharForObjCBool() ?
SignedCharTy : BoolTy);
ObjCConstantStringType = QualType();
@ -2193,6 +2194,8 @@ ASTContext::getFunctionType(QualType ResultTy,
Size += EPI.NumExceptions * sizeof(QualType);
else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) {
Size += sizeof(Expr*);
} else if (EPI.ExceptionSpecType == EST_Uninstantiated) {
Size += 2 * sizeof(FunctionDecl*);
}
if (EPI.ConsumedArguments)
Size += NumArgs * sizeof(bool);

View File

@ -69,33 +69,25 @@ typedef NamedDecl::LinkageInfo LinkageInfo;
namespace {
/// Flags controlling the computation of linkage and visibility.
struct LVFlags {
bool ConsiderGlobalVisibility;
bool ConsiderVisibilityAttributes;
bool ConsiderTemplateParameterTypes;
const bool ConsiderGlobalVisibility;
const bool ConsiderVisibilityAttributes;
const bool ConsiderTemplateParameterTypes;
LVFlags() : ConsiderGlobalVisibility(true),
ConsiderVisibilityAttributes(true),
ConsiderTemplateParameterTypes(true) {
}
LVFlags(bool Global, bool Attributes, bool Parameters) :
ConsiderGlobalVisibility(Global),
ConsiderVisibilityAttributes(Attributes),
ConsiderTemplateParameterTypes(Parameters) {
}
/// \brief Returns a set of flags that is only useful for computing the
/// linkage, not the visibility, of a declaration.
static LVFlags CreateOnlyDeclLinkage() {
LVFlags F;
F.ConsiderGlobalVisibility = false;
F.ConsiderVisibilityAttributes = false;
F.ConsiderTemplateParameterTypes = false;
return F;
}
/// Returns a set of flags, otherwise based on these, which ignores
/// off all sources of visibility except template arguments.
LVFlags onlyTemplateVisibility() const {
LVFlags F = *this;
F.ConsiderGlobalVisibility = false;
F.ConsiderVisibilityAttributes = false;
F.ConsiderTemplateParameterTypes = false;
return F;
return LVFlags(false, false, false);
}
};
} // end anonymous namespace
@ -284,7 +276,6 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
if (F.ConsiderVisibilityAttributes) {
if (llvm::Optional<Visibility> Vis = D->getExplicitVisibility()) {
LV.setVisibility(*Vis, true);
F.ConsiderGlobalVisibility = false;
} else {
// If we're declared in a namespace with a visibility attribute,
// use that namespace's visibility, but don't call it explicit.
@ -295,7 +286,6 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
if (!ND) continue;
if (llvm::Optional<Visibility> Vis = ND->getExplicitVisibility()) {
LV.setVisibility(*Vis, true);
F.ConsiderGlobalVisibility = false;
break;
}
}
@ -335,8 +325,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
LinkageInfo TypeLV = getLVForType(Var->getType());
if (TypeLV.linkage() != ExternalLinkage)
return LinkageInfo::uniqueExternal();
LV.mergeVisibilityWithMin(TypeLV.visibility(),
TypeLV.visibilityExplicit());
LV.mergeVisibilityWithMin(TypeLV);
}
if (Var->getStorageClass() == SC_PrivateExtern)
@ -412,7 +401,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
= Function->getTemplateSpecializationInfo()) {
if (shouldConsiderTemplateLV(Function, specInfo)) {
LV.merge(getLVForDecl(specInfo->getTemplate(),
F.onlyTemplateVisibility()));
LVFlags::CreateOnlyDeclLinkage()));
const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments;
LV.mergeWithMin(getLVForTemplateArgumentList(templateArgs, F));
}
@ -436,7 +425,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
if (shouldConsiderTemplateLV(spec)) {
// From the template.
LV.merge(getLVForDecl(spec->getSpecializedTemplate(),
F.onlyTemplateVisibility()));
LVFlags::CreateOnlyDeclLinkage()));
// The arguments at which the template was instantiated.
const TemplateArgumentList &TemplateArgs = spec->getTemplateArgs();
@ -444,12 +433,6 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
}
}
// Consider -fvisibility unless the type has C linkage.
if (F.ConsiderGlobalVisibility)
F.ConsiderGlobalVisibility =
(Context.getLangOpts().CPlusPlus &&
!Tag->getDeclContext()->isExternCContext());
// - an enumerator belonging to an enumeration with external linkage;
} else if (isa<EnumConstantDecl>(D)) {
LinkageInfo EnumLV = getLVForDecl(cast<NamedDecl>(D->getDeclContext()), F);
@ -501,22 +484,47 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {
LinkageInfo LV;
LV.mergeVisibility(D->getASTContext().getLangOpts().getVisibilityMode());
// The flags we're going to use to compute the class's visibility.
LVFlags ClassF = F;
bool DHasExplicitVisibility = false;
// If we have an explicit visibility attribute, merge that in.
if (F.ConsiderVisibilityAttributes) {
if (llvm::Optional<Visibility> Vis = D->getExplicitVisibility()) {
LV.mergeVisibility(*Vis, true);
// Ignore global visibility later, but not this attribute.
F.ConsiderGlobalVisibility = false;
// Ignore both global visibility and attributes when computing our
// parent's visibility.
ClassF = F.onlyTemplateVisibility();
DHasExplicitVisibility = true;
}
}
// Ignore both global visibility and attributes when computing our
// parent's visibility if we already have an explicit one.
LVFlags ClassF = DHasExplicitVisibility ?
LVFlags::CreateOnlyDeclLinkage() : F;
// If we're paying attention to global visibility, apply
// -finline-visibility-hidden if this is an inline method.
//
// Note that we do this before merging information about
// the class visibility.
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
TemplateSpecializationKind TSK = TSK_Undeclared;
if (FunctionTemplateSpecializationInfo *spec
= MD->getTemplateSpecializationInfo()) {
TSK = spec->getTemplateSpecializationKind();
} else if (MemberSpecializationInfo *MSI =
MD->getMemberSpecializationInfo()) {
TSK = MSI->getTemplateSpecializationKind();
}
const FunctionDecl *Def = 0;
// InlineVisibilityHidden only applies to definitions, and
// isInlined() only gives meaningful answers on definitions
// anyway.
if (TSK != TSK_ExplicitInstantiationDeclaration &&
TSK != TSK_ExplicitInstantiationDefinition &&
F.ConsiderGlobalVisibility &&
!LV.visibilityExplicit() &&
MD->getASTContext().getLangOpts().InlineVisibilityHidden &&
MD->hasBody(Def) && Def->isInlined())
LV.mergeVisibility(HiddenVisibility, true);
}
// Class members only have linkage if their class has external
// linkage.
@ -534,8 +542,6 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {
if (MD->getType()->getLinkage() == UniqueExternalLinkage)
return LinkageInfo::uniqueExternal();
TemplateSpecializationKind TSK = TSK_Undeclared;
// If this is a method template specialization, use the linkage for
// the template parameters and arguments.
if (FunctionTemplateSpecializationInfo *spec
@ -547,29 +553,6 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {
LV.merge(getLVForTemplateParameterList(
spec->getTemplate()->getTemplateParameters()));
}
TSK = spec->getTemplateSpecializationKind();
} else if (MemberSpecializationInfo *MSI =
MD->getMemberSpecializationInfo()) {
TSK = MSI->getTemplateSpecializationKind();
}
// If we're paying attention to global visibility, apply
// -finline-visibility-hidden if this is an inline method.
//
// Note that ConsiderGlobalVisibility doesn't yet have information
// about whether containing classes have visibility attributes,
// and that's intentional.
if (TSK != TSK_ExplicitInstantiationDeclaration &&
TSK != TSK_ExplicitInstantiationDefinition &&
F.ConsiderGlobalVisibility &&
MD->getASTContext().getLangOpts().InlineVisibilityHidden) {
// InlineVisibilityHidden only applies to definitions, and
// isInlined() only gives meaningful answers on definitions
// anyway.
const FunctionDecl *Def = 0;
if (MD->hasBody(Def) && Def->isInlined())
LV.setVisibility(HiddenVisibility);
}
// Note that in contrast to basically every other situation, we
@ -597,7 +580,7 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {
if (TypeLV.linkage() != ExternalLinkage)
LV.mergeLinkage(UniqueExternalLinkage);
if (!LV.visibilityExplicit())
LV.mergeVisibility(TypeLV.visibility(), TypeLV.visibilityExplicit());
LV.mergeVisibility(TypeLV);
}
return LV;
@ -802,7 +785,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
LinkageInfo LV;
if (Flags.ConsiderVisibilityAttributes) {
if (llvm::Optional<Visibility> Vis = Function->getExplicitVisibility())
LV.setVisibility(*Vis);
LV.setVisibility(*Vis, true);
}
if (const FunctionDecl *Prev = Function->getPreviousDecl()) {
@ -823,10 +806,10 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
LinkageInfo LV;
if (Var->getStorageClass() == SC_PrivateExtern)
LV.setVisibility(HiddenVisibility);
LV.setVisibility(HiddenVisibility, true);
else if (Flags.ConsiderVisibilityAttributes) {
if (llvm::Optional<Visibility> Vis = Var->getExplicitVisibility())
LV.setVisibility(*Vis);
LV.setVisibility(*Vis, true);
}
if (const VarDecl *Prev = Var->getPreviousDecl()) {

View File

@ -1590,6 +1590,16 @@ void InitListExpr::setArrayFiller(Expr *filler) {
inits[i] = filler;
}
bool InitListExpr::isStringLiteralInit() const {
if (getNumInits() != 1)
return false;
const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(getType());
if (!CAT || !CAT->getElementType()->isIntegerType())
return false;
const Expr *Init = getInit(0)->IgnoreParenImpCasts();
return isa<StringLiteral>(Init) || isa<ObjCEncodeExpr>(Init);
}
SourceRange InitListExpr::getSourceRange() const {
if (SyntacticForm)
return SyntacticForm->getSourceRange();
@ -1986,331 +1996,6 @@ QualType Expr::findBoundMemberType(const Expr *expr) {
return QualType();
}
static Expr::CanThrowResult MergeCanThrow(Expr::CanThrowResult CT1,
Expr::CanThrowResult CT2) {
// CanThrowResult constants are ordered so that the maximum is the correct
// merge result.
return CT1 > CT2 ? CT1 : CT2;
}
static Expr::CanThrowResult CanSubExprsThrow(ASTContext &C, const Expr *CE) {
Expr *E = const_cast<Expr*>(CE);
Expr::CanThrowResult R = Expr::CT_Cannot;
for (Expr::child_range I = E->children(); I && R != Expr::CT_Can; ++I) {
R = MergeCanThrow(R, cast<Expr>(*I)->CanThrow(C));
}
return R;
}
static Expr::CanThrowResult CanCalleeThrow(ASTContext &Ctx, const Expr *E,
const Decl *D,
bool NullThrows = true) {
if (!D)
return NullThrows ? Expr::CT_Can : Expr::CT_Cannot;
// See if we can get a function type from the decl somehow.
const ValueDecl *VD = dyn_cast<ValueDecl>(D);
if (!VD) // If we have no clue what we're calling, assume the worst.
return Expr::CT_Can;
// As an extension, we assume that __attribute__((nothrow)) functions don't
// throw.
if (isa<FunctionDecl>(D) && D->hasAttr<NoThrowAttr>())
return Expr::CT_Cannot;
QualType T = VD->getType();
const FunctionProtoType *FT;
if ((FT = T->getAs<FunctionProtoType>())) {
} else if (const PointerType *PT = T->getAs<PointerType>())
FT = PT->getPointeeType()->getAs<FunctionProtoType>();
else if (const ReferenceType *RT = T->getAs<ReferenceType>())
FT = RT->getPointeeType()->getAs<FunctionProtoType>();
else if (const MemberPointerType *MT = T->getAs<MemberPointerType>())
FT = MT->getPointeeType()->getAs<FunctionProtoType>();
else if (const BlockPointerType *BT = T->getAs<BlockPointerType>())
FT = BT->getPointeeType()->getAs<FunctionProtoType>();
if (!FT)
return Expr::CT_Can;
if (FT->getExceptionSpecType() == EST_Delayed) {
assert(isa<CXXConstructorDecl>(D) &&
"only constructor exception specs can be unknown");
Ctx.getDiagnostics().Report(E->getLocStart(),
diag::err_exception_spec_unknown)
<< E->getSourceRange();
return Expr::CT_Can;
}
return FT->isNothrow(Ctx) ? Expr::CT_Cannot : Expr::CT_Can;
}
static Expr::CanThrowResult CanDynamicCastThrow(const CXXDynamicCastExpr *DC) {
if (DC->isTypeDependent())
return Expr::CT_Dependent;
if (!DC->getTypeAsWritten()->isReferenceType())
return Expr::CT_Cannot;
if (DC->getSubExpr()->isTypeDependent())
return Expr::CT_Dependent;
return DC->getCastKind() == clang::CK_Dynamic? Expr::CT_Can : Expr::CT_Cannot;
}
static Expr::CanThrowResult CanTypeidThrow(ASTContext &C,
const CXXTypeidExpr *DC) {
if (DC->isTypeOperand())
return Expr::CT_Cannot;
Expr *Op = DC->getExprOperand();
if (Op->isTypeDependent())
return Expr::CT_Dependent;
const RecordType *RT = Op->getType()->getAs<RecordType>();
if (!RT)
return Expr::CT_Cannot;
if (!cast<CXXRecordDecl>(RT->getDecl())->isPolymorphic())
return Expr::CT_Cannot;
if (Op->Classify(C).isPRValue())
return Expr::CT_Cannot;
return Expr::CT_Can;
}
Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const {
// C++ [expr.unary.noexcept]p3:
// [Can throw] if in a potentially-evaluated context the expression would
// contain:
switch (getStmtClass()) {
case CXXThrowExprClass:
// - a potentially evaluated throw-expression
return CT_Can;
case CXXDynamicCastExprClass: {
// - a potentially evaluated dynamic_cast expression dynamic_cast<T>(v),
// where T is a reference type, that requires a run-time check
CanThrowResult CT = CanDynamicCastThrow(cast<CXXDynamicCastExpr>(this));
if (CT == CT_Can)
return CT;
return MergeCanThrow(CT, CanSubExprsThrow(C, this));
}
case CXXTypeidExprClass:
// - a potentially evaluated typeid expression applied to a glvalue
// expression whose type is a polymorphic class type
return CanTypeidThrow(C, cast<CXXTypeidExpr>(this));
// - a potentially evaluated call to a function, member function, function
// pointer, or member function pointer that does not have a non-throwing
// exception-specification
case CallExprClass:
case CXXMemberCallExprClass:
case CXXOperatorCallExprClass:
case UserDefinedLiteralClass: {
const CallExpr *CE = cast<CallExpr>(this);
CanThrowResult CT;
if (isTypeDependent())
CT = CT_Dependent;
else if (isa<CXXPseudoDestructorExpr>(CE->getCallee()->IgnoreParens()))
CT = CT_Cannot;
else
CT = CanCalleeThrow(C, this, CE->getCalleeDecl());
if (CT == CT_Can)
return CT;
return MergeCanThrow(CT, CanSubExprsThrow(C, this));
}
case CXXConstructExprClass:
case CXXTemporaryObjectExprClass: {
CanThrowResult CT = CanCalleeThrow(C, this,
cast<CXXConstructExpr>(this)->getConstructor());
if (CT == CT_Can)
return CT;
return MergeCanThrow(CT, CanSubExprsThrow(C, this));
}
case LambdaExprClass: {
const LambdaExpr *Lambda = cast<LambdaExpr>(this);
CanThrowResult CT = Expr::CT_Cannot;
for (LambdaExpr::capture_init_iterator Cap = Lambda->capture_init_begin(),
CapEnd = Lambda->capture_init_end();
Cap != CapEnd; ++Cap)
CT = MergeCanThrow(CT, (*Cap)->CanThrow(C));
return CT;
}
case CXXNewExprClass: {
CanThrowResult CT;
if (isTypeDependent())
CT = CT_Dependent;
else
CT = CanCalleeThrow(C, this, cast<CXXNewExpr>(this)->getOperatorNew());
if (CT == CT_Can)
return CT;
return MergeCanThrow(CT, CanSubExprsThrow(C, this));
}
case CXXDeleteExprClass: {
CanThrowResult CT;
QualType DTy = cast<CXXDeleteExpr>(this)->getDestroyedType();
if (DTy.isNull() || DTy->isDependentType()) {
CT = CT_Dependent;
} else {
CT = CanCalleeThrow(C, this,
cast<CXXDeleteExpr>(this)->getOperatorDelete());
if (const RecordType *RT = DTy->getAs<RecordType>()) {
const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
CT = MergeCanThrow(CT, CanCalleeThrow(C, this, RD->getDestructor()));
}
if (CT == CT_Can)
return CT;
}
return MergeCanThrow(CT, CanSubExprsThrow(C, this));
}
case CXXBindTemporaryExprClass: {
// The bound temporary has to be destroyed again, which might throw.
CanThrowResult CT = CanCalleeThrow(C, this,
cast<CXXBindTemporaryExpr>(this)->getTemporary()->getDestructor());
if (CT == CT_Can)
return CT;
return MergeCanThrow(CT, CanSubExprsThrow(C, this));
}
// ObjC message sends are like function calls, but never have exception
// specs.
case ObjCMessageExprClass:
case ObjCPropertyRefExprClass:
case ObjCSubscriptRefExprClass:
return CT_Can;
// All the ObjC literals that are implemented as calls are
// potentially throwing unless we decide to close off that
// possibility.
case ObjCArrayLiteralClass:
case ObjCDictionaryLiteralClass:
case ObjCNumericLiteralClass:
return CT_Can;
// Many other things have subexpressions, so we have to test those.
// Some are simple:
case ConditionalOperatorClass:
case CompoundLiteralExprClass:
case CXXConstCastExprClass:
case CXXDefaultArgExprClass:
case CXXReinterpretCastExprClass:
case DesignatedInitExprClass:
case ExprWithCleanupsClass:
case ExtVectorElementExprClass:
case InitListExprClass:
case MemberExprClass:
case ObjCIsaExprClass:
case ObjCIvarRefExprClass:
case ParenExprClass:
case ParenListExprClass:
case ShuffleVectorExprClass:
case VAArgExprClass:
return CanSubExprsThrow(C, this);
// Some might be dependent for other reasons.
case ArraySubscriptExprClass:
case BinaryOperatorClass:
case CompoundAssignOperatorClass:
case CStyleCastExprClass:
case CXXStaticCastExprClass:
case CXXFunctionalCastExprClass:
case ImplicitCastExprClass:
case MaterializeTemporaryExprClass:
case UnaryOperatorClass: {
CanThrowResult CT = isTypeDependent() ? CT_Dependent : CT_Cannot;
return MergeCanThrow(CT, CanSubExprsThrow(C, this));
}
// FIXME: We should handle StmtExpr, but that opens a MASSIVE can of worms.
case StmtExprClass:
return CT_Can;
case ChooseExprClass:
if (isTypeDependent() || isValueDependent())
return CT_Dependent;
return cast<ChooseExpr>(this)->getChosenSubExpr(C)->CanThrow(C);
case GenericSelectionExprClass:
if (cast<GenericSelectionExpr>(this)->isResultDependent())
return CT_Dependent;
return cast<GenericSelectionExpr>(this)->getResultExpr()->CanThrow(C);
// Some expressions are always dependent.
case CXXDependentScopeMemberExprClass:
case CXXUnresolvedConstructExprClass:
case DependentScopeDeclRefExprClass:
return CT_Dependent;
case AtomicExprClass:
case AsTypeExprClass:
case BinaryConditionalOperatorClass:
case BlockExprClass:
case CUDAKernelCallExprClass:
case DeclRefExprClass:
case ObjCBridgedCastExprClass:
case ObjCIndirectCopyRestoreExprClass:
case ObjCProtocolExprClass:
case ObjCSelectorExprClass:
case OffsetOfExprClass:
case PackExpansionExprClass:
case PseudoObjectExprClass:
case SubstNonTypeTemplateParmExprClass:
case SubstNonTypeTemplateParmPackExprClass:
case UnaryExprOrTypeTraitExprClass:
case UnresolvedLookupExprClass:
case UnresolvedMemberExprClass:
// FIXME: Can any of the above throw? If so, when?
return CT_Cannot;
case AddrLabelExprClass:
case ArrayTypeTraitExprClass:
case BinaryTypeTraitExprClass:
case TypeTraitExprClass:
case CXXBoolLiteralExprClass:
case CXXNoexceptExprClass:
case CXXNullPtrLiteralExprClass:
case CXXPseudoDestructorExprClass:
case CXXScalarValueInitExprClass:
case CXXThisExprClass:
case CXXUuidofExprClass:
case CharacterLiteralClass:
case ExpressionTraitExprClass:
case FloatingLiteralClass:
case GNUNullExprClass:
case ImaginaryLiteralClass:
case ImplicitValueInitExprClass:
case IntegerLiteralClass:
case ObjCEncodeExprClass:
case ObjCStringLiteralClass:
case ObjCBoolLiteralExprClass:
case OpaqueValueExprClass:
case PredefinedExprClass:
case SizeOfPackExprClass:
case StringLiteralClass:
case UnaryTypeTraitExprClass:
// These expressions can never throw.
return CT_Cannot;
#define STMT(CLASS, PARENT) case CLASS##Class:
#define STMT_RANGE(Base, First, Last)
#define LAST_STMT_RANGE(BASE, FIRST, LAST)
#define EXPR(CLASS, PARENT)
#define ABSTRACT_STMT(STMT)
#include "clang/AST/StmtNodes.inc"
case NoStmtClass:
llvm_unreachable("Invalid class for expression");
}
llvm_unreachable("Bogus StmtClass");
}
Expr* Expr::IgnoreParens() {
Expr* E = this;
while (true) {

View File

@ -934,6 +934,7 @@ static bool IsGlobalLValue(APValue::LValueBase B) {
case Expr::ObjCStringLiteralClass:
case Expr::ObjCEncodeExprClass:
case Expr::CXXTypeidExprClass:
case Expr::CXXUuidofExprClass:
return true;
case Expr::CallExprClass:
return IsStringLiteralCall(cast<CallExpr>(E));
@ -1491,15 +1492,19 @@ static unsigned getBaseIndex(const CXXRecordDecl *Derived,
llvm_unreachable("base class missing from derived class's bases list");
}
/// Extract the value of a character from a string literal.
/// Extract the value of a character from a string literal. CharType is used to
/// determine the expected signedness of the result -- a string literal used to
/// initialize an array of 'signed char' or 'unsigned char' might contain chars
/// of the wrong signedness.
static APSInt ExtractStringLiteralCharacter(EvalInfo &Info, const Expr *Lit,
uint64_t Index) {
uint64_t Index, QualType CharType) {
// FIXME: Support PredefinedExpr, ObjCEncodeExpr, MakeStringConstant
const StringLiteral *S = dyn_cast<StringLiteral>(Lit);
assert(S && "unexpected string literal expression kind");
assert(CharType->isIntegerType() && "unexpected character type");
APSInt Value(S->getCharByteWidth() * Info.Ctx.getCharWidth(),
Lit->getType()->getArrayElementTypeNoTypeQual()->isUnsignedIntegerType());
CharType->isUnsignedIntegerType());
if (Index < S->getLength())
Value = S->getCodeUnit(Index);
return Value;
@ -1546,7 +1551,7 @@ static bool ExtractSubobject(EvalInfo &Info, const Expr *E,
assert(I == N - 1 && "extracting subobject of character?");
assert(!O->hasLValuePath() || O->getLValuePath().empty());
Obj = APValue(ExtractStringLiteralCharacter(
Info, O->getLValueBase().get<const Expr*>(), Index));
Info, O->getLValueBase().get<const Expr*>(), Index, SubType));
return true;
} else if (O->getArrayInitializedElts() > Index)
O = &O->getArrayInitializedElt(Index);
@ -2868,6 +2873,7 @@ class LValueExprEvaluator
bool VisitStringLiteral(const StringLiteral *E) { return Success(E); }
bool VisitObjCEncodeExpr(const ObjCEncodeExpr *E) { return Success(E); }
bool VisitCXXTypeidExpr(const CXXTypeidExpr *E);
bool VisitCXXUuidofExpr(const CXXUuidofExpr *E);
bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E);
bool VisitUnaryDeref(const UnaryOperator *E);
bool VisitUnaryReal(const UnaryOperator *E);
@ -2973,6 +2979,10 @@ bool LValueExprEvaluator::VisitCXXTypeidExpr(const CXXTypeidExpr *E) {
return Success(E);
}
bool LValueExprEvaluator::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {
return Success(E);
}
bool LValueExprEvaluator::VisitMemberExpr(const MemberExpr *E) {
// Handle static data members.
if (const VarDecl *VD = dyn_cast<VarDecl>(E->getMemberDecl())) {
@ -3849,8 +3859,7 @@ bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
// C++11 [dcl.init.string]p1: A char array [...] can be initialized by [...]
// an appropriately-typed string literal enclosed in braces.
if (E->getNumInits() == 1 && E->getInit(0)->isGLValue() &&
Info.Ctx.hasSameUnqualifiedType(E->getType(), E->getInit(0)->getType())) {
if (E->isStringLiteralInit()) {
LValue LV;
if (!EvaluateLValue(E->getInit(0), LV, Info))
return false;
@ -5079,14 +5088,37 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
}
}
// The comparison here must be unsigned, and performed with the same
// width as the pointer.
unsigned PtrSize = Info.Ctx.getTypeSize(LHSTy);
uint64_t CompareLHS = LHSOffset.getQuantity();
uint64_t CompareRHS = RHSOffset.getQuantity();
assert(PtrSize <= 64 && "Unexpected pointer width");
uint64_t Mask = ~0ULL >> (64 - PtrSize);
CompareLHS &= Mask;
CompareRHS &= Mask;
// If there is a base and this is a relational operator, we can only
// compare pointers within the object in question; otherwise, the result
// depends on where the object is located in memory.
if (!LHSValue.Base.isNull() && E->isRelationalOp()) {
QualType BaseTy = getType(LHSValue.Base);
if (BaseTy->isIncompleteType())
return Error(E);
CharUnits Size = Info.Ctx.getTypeSizeInChars(BaseTy);
uint64_t OffsetLimit = Size.getQuantity();
if (CompareLHS > OffsetLimit || CompareRHS > OffsetLimit)
return Error(E);
}
switch (E->getOpcode()) {
default: llvm_unreachable("missing comparison operator");
case BO_LT: return Success(LHSOffset < RHSOffset, E);
case BO_GT: return Success(LHSOffset > RHSOffset, E);
case BO_LE: return Success(LHSOffset <= RHSOffset, E);
case BO_GE: return Success(LHSOffset >= RHSOffset, E);
case BO_EQ: return Success(LHSOffset == RHSOffset, E);
case BO_NE: return Success(LHSOffset != RHSOffset, E);
case BO_LT: return Success(CompareLHS < CompareRHS, E);
case BO_GT: return Success(CompareLHS > CompareRHS, E);
case BO_LE: return Success(CompareLHS <= CompareRHS, E);
case BO_GE: return Success(CompareLHS >= CompareRHS, E);
case BO_EQ: return Success(CompareLHS == CompareRHS, E);
case BO_NE: return Success(CompareLHS != CompareRHS, E);
}
}
}

View File

@ -49,7 +49,10 @@ ExternalASTSource::FindExternalVisibleDeclsByName(const DeclContext *DC,
return DeclContext::lookup_result();
}
ExternalLoadResult
void ExternalASTSource::completeVisibleDeclsMap(const DeclContext *DC) {
}
ExternalLoadResult
ExternalASTSource::FindExternalLexicalDecls(const DeclContext *DC,
bool (*isKindWeWant)(Decl::Kind),
SmallVectorImpl<Decl*> &Result) {

View File

@ -2280,9 +2280,7 @@ void CXXNameMangler::mangleIntegerLiteral(QualType T,
}
/// Mangles a member expression. Implicit accesses are not handled,
/// but that should be okay, because you shouldn't be able to
/// make an implicit access in a function template declaration.
/// Mangles a member expression.
void CXXNameMangler::mangleMemberExpr(const Expr *base,
bool isArrow,
NestedNameSpecifier *qualifier,
@ -2291,8 +2289,17 @@ void CXXNameMangler::mangleMemberExpr(const Expr *base,
unsigned arity) {
// <expression> ::= dt <expression> <unresolved-name>
// ::= pt <expression> <unresolved-name>
Out << (isArrow ? "pt" : "dt");
mangleExpression(base);
if (base) {
if (base->isImplicitCXXThis()) {
// Note: GCC mangles member expressions to the implicit 'this' as
// *this., whereas we represent them as this->. The Itanium C++ ABI
// does not specify anything here, so we follow GCC.
Out << "dtdefpT";
} else {
Out << (isArrow ? "pt" : "dt");
mangleExpression(base);
}
}
mangleUnresolvedName(qualifier, firstQualifierLookup, member, arity);
}
@ -2346,6 +2353,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
// <expr-primary> ::= L <type> <value number> E # integer literal
// ::= L <type <value float> E # floating literal
// ::= L <mangled-name> E # external name
// ::= fpT # 'this' expression
QualType ImplicitlyConvertedToType;
recurse:
@ -2361,7 +2369,6 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
// These all can only appear in local or variable-initialization
// contexts and so should never appear in a mangling.
case Expr::AddrLabelExprClass:
case Expr::CXXThisExprClass:
case Expr::DesignatedInitExprClass:
case Expr::ImplicitValueInitExprClass:
case Expr::ParenListExprClass:
@ -2919,6 +2926,10 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
mangleExpression(cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr());
break;
}
case Expr::CXXThisExprClass:
Out << "fpT";
break;
}
}

View File

@ -97,8 +97,8 @@ Stmt *Stmt::IgnoreImplicit() {
/// \brief Strip off all label-like statements.
///
/// This will strip off label statements, case statements, and default
/// statements recursively.
/// This will strip off label statements, case statements, attributed
/// statements and default statements recursively.
const Stmt *Stmt::stripLabelLikeStatements() const {
const Stmt *S = this;
while (true) {
@ -106,6 +106,8 @@ const Stmt *Stmt::stripLabelLikeStatements() const {
S = LS->getSubStmt();
else if (const SwitchCase *SC = dyn_cast<SwitchCase>(S))
S = SC->getSubStmt();
else if (const AttributedStmt *AS = dyn_cast<AttributedStmt>(S))
S = AS->getSubStmt();
else
return S;
}

View File

@ -169,6 +169,23 @@ void StmtPrinter::VisitLabelStmt(LabelStmt *Node) {
PrintStmt(Node->getSubStmt(), 0);
}
void StmtPrinter::VisitAttributedStmt(AttributedStmt *Node) {
OS << "[[";
bool first = true;
for (AttrVec::const_iterator it = Node->getAttrs().begin(),
end = Node->getAttrs().end();
it != end; ++it) {
if (!first) {
OS << ", ";
first = false;
}
// TODO: check this
(*it)->printPretty(OS, Context);
}
OS << "]] ";
PrintStmt(Node->getSubStmt(), 0);
}
void StmtPrinter::PrintRawIfStmt(IfStmt *If) {
OS << "if (";
PrintExpr(If->getCond());

View File

@ -109,6 +109,11 @@ void StmtProfiler::VisitLabelStmt(const LabelStmt *S) {
VisitDecl(S->getDecl());
}
void StmtProfiler::VisitAttributedStmt(const AttributedStmt *S) {
VisitStmt(S);
// TODO: maybe visit attributes?
}
void StmtProfiler::VisitIfStmt(const IfStmt *S) {
VisitStmt(S);
VisitDecl(S->getConditionVariable());
@ -758,6 +763,7 @@ void StmtProfiler::VisitCXXUuidofExpr(const CXXUuidofExpr *S) {
void StmtProfiler::VisitCXXThisExpr(const CXXThisExpr *S) {
VisitExpr(S);
ID.AddBoolean(S->isImplicit());
}
void StmtProfiler::VisitCXXThrowExpr(const CXXThrowExpr *S) {

View File

@ -1546,6 +1546,14 @@ FunctionProtoType::FunctionProtoType(QualType result, const QualType *args,
else if (epi.NoexceptExpr->isInstantiationDependent())
setInstantiationDependent();
}
} else if (getExceptionSpecType() == EST_Uninstantiated) {
// Store the function decl from which we will resolve our
// exception specification.
FunctionDecl **slot = reinterpret_cast<FunctionDecl**>(argSlot + numArgs);
slot[0] = epi.ExceptionSpecDecl;
slot[1] = epi.ExceptionSpecTemplate;
// This exception specification doesn't make the type dependent, because
// it's not instantiated as part of instantiating the type.
}
if (epi.ConsumedArguments) {
@ -1629,6 +1637,8 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
ID.AddPointer(epi.Exceptions[i].getAsOpaquePtr());
} else if (epi.ExceptionSpecType == EST_ComputedNoexcept && epi.NoexceptExpr){
epi.NoexceptExpr->Profile(ID, Context, false);
} else if (epi.ExceptionSpecType == EST_Uninstantiated) {
ID.AddPointer(epi.ExceptionSpecDecl->getCanonicalDecl());
}
if (epi.ConsumedArguments) {
for (unsigned i = 0; i != NumArgs; ++i)

View File

@ -2157,13 +2157,12 @@ VTableLayout::VTableLayout(uint64_t NumVTableComponents,
VTableThunks(new VTableThunkTy[NumVTableThunks]),
AddressPoints(AddressPoints) {
std::copy(VTableComponents, VTableComponents+NumVTableComponents,
this->VTableComponents);
std::copy(VTableThunks, VTableThunks+NumVTableThunks, this->VTableThunks);
this->VTableComponents.get());
std::copy(VTableThunks, VTableThunks+NumVTableThunks,
this->VTableThunks.get());
}
VTableLayout::~VTableLayout() {
delete[] VTableComponents;
}
VTableLayout::~VTableLayout() { }
VTableContext::~VTableContext() {
llvm::DeleteContainerSeconds(VTableLayouts);

View File

@ -18,6 +18,7 @@
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/CharUnits.h"
#include "clang/Basic/AttrKinds.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Format.h"
@ -1069,6 +1070,9 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) {
case Stmt::LambdaExprClass:
return VisitLambdaExpr(cast<LambdaExpr>(S), asc);
case Stmt::AttributedStmtClass:
return Visit(cast<AttributedStmt>(S)->getSubStmt(), asc);
case Stmt::MemberExprClass:
return VisitMemberExpr(cast<MemberExpr>(S), asc);
@ -1131,7 +1135,7 @@ CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) {
/// VisitChildren - Visit the children of a Stmt.
CFGBlock *CFGBuilder::VisitChildren(Stmt *Terminator) {
CFGBlock *lastBlock = Block;
CFGBlock *lastBlock = Block;
for (Stmt::child_range I = Terminator->children(); I; ++I)
if (Stmt *child = *I)
if (CFGBlock *b = Visit(child))
@ -1280,7 +1284,8 @@ static bool CanThrow(Expr *E, ASTContext &Ctx) {
const FunctionType *FT = Ty->getAs<FunctionType>();
if (FT) {
if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT))
if (Proto->isNothrow(Ctx))
if (Proto->getExceptionSpecType() != EST_Uninstantiated &&
Proto->isNothrow(Ctx))
return false;
}
return true;

View File

@ -1,4 +1,4 @@
set(LLVM_USED_LIBS clangBasic clangAST clangIndex)
set(LLVM_USED_LIBS clangBasic clangAST)
add_clang_library(clangAnalysis
AnalysisDeclContext.cpp

View File

@ -58,6 +58,7 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
Char32Type = UnsignedInt;
Int64Type = SignedLongLong;
SigAtomicType = SignedInt;
UseSignedCharForObjCBool = true;
UseBitFieldTypeAlignment = true;
UseZeroLengthBitfieldAlignment = false;
ZeroLengthBitfieldBoundary = 0;

View File

@ -365,7 +365,7 @@ class OpenBSDTargetInfo : public OSTargetInfo<Target> {
DefineStd(Builder, "unix", Opts);
Builder.defineMacro("__ELF__");
if (Opts.POSIXThreads)
Builder.defineMacro("_POSIX_THREADS");
Builder.defineMacro("_REENTRANT");
}
public:
OpenBSDTargetInfo(const std::string &triple)
@ -3546,7 +3546,10 @@ class MipsTargetInfoBase : public TargetInfo {
virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features,
StringRef Name,
bool Enabled) const {
if (Name == "soft-float" || Name == "single-float") {
if (Name == "soft-float" || Name == "single-float" ||
Name == "o32" || Name == "n32" || Name == "n64" || Name == "eabi" ||
Name == "mips32" || Name == "mips32r2" ||
Name == "mips64" || Name == "mips64r2") {
Features[Name] = Enabled;
return true;
}

View File

@ -32,7 +32,7 @@ std::string getClangRepositoryPath() {
// If the SVN_REPOSITORY is empty, try to use the SVN keyword. This helps us
// pick up a tag in an SVN export, for example.
static StringRef SVNRepository("$URL: http://llvm.org/svn/llvm-project/cfe/trunk/lib/Basic/Version.cpp $");
static StringRef SVNRepository("$URL: http://llvm.org/svn/llvm-project/cfe/branches/release_31/lib/Basic/Version.cpp $");
if (URL.empty()) {
URL = SVNRepository.slice(SVNRepository.find(':'),
SVNRepository.find("/lib/Basic"));

View File

@ -14,5 +14,4 @@ add_subdirectory(Serialization)
add_subdirectory(Frontend)
add_subdirectory(FrontendTool)
add_subdirectory(Tooling)
add_subdirectory(Index)
add_subdirectory(StaticAnalyzer)

View File

@ -491,6 +491,8 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
/// a full-expression so that the block's cleanups are pushed at the
/// right place in the stack.
static void enterBlockScope(CodeGenFunction &CGF, BlockDecl *block) {
assert(CGF.HaveInsertPoint());
// Allocate the block info and place it at the head of the list.
CGBlockInfo &blockInfo =
*new CGBlockInfo(block, CGF.CurFn->getName());

View File

@ -419,16 +419,37 @@ void CodeGenTypes::GetExpandedTypes(QualType type,
uint64_t NumElts = AT->getSize().getZExtValue();
for (uint64_t Elt = 0; Elt < NumElts; ++Elt)
GetExpandedTypes(AT->getElementType(), expandedTypes);
} else if (const RecordType *RT = type->getAsStructureType()) {
} else if (const RecordType *RT = type->getAs<RecordType>()) {
const RecordDecl *RD = RT->getDecl();
assert(!RD->hasFlexibleArrayMember() &&
"Cannot expand structure with flexible array.");
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
i != e; ++i) {
const FieldDecl *FD = *i;
assert(!FD->isBitField() &&
"Cannot expand structure with bit-field members.");
GetExpandedTypes(FD->getType(), expandedTypes);
if (RD->isUnion()) {
// Unions can be here only in degenerative cases - all the fields are same
// after flattening. Thus we have to use the "largest" field.
const FieldDecl *LargestFD = 0;
CharUnits UnionSize = CharUnits::Zero();
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
i != e; ++i) {
const FieldDecl *FD = *i;
assert(!FD->isBitField() &&
"Cannot expand structure with bit-field members.");
CharUnits FieldSize = getContext().getTypeSizeInChars(FD->getType());
if (UnionSize < FieldSize) {
UnionSize = FieldSize;
LargestFD = FD;
}
}
if (LargestFD)
GetExpandedTypes(LargestFD->getType(), expandedTypes);
} else {
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
i != e; ++i) {
const FieldDecl *FD = *i;
assert(!FD->isBitField() &&
"Cannot expand structure with bit-field members.");
GetExpandedTypes(FD->getType(), expandedTypes);
}
}
} else if (const ComplexType *CT = type->getAs<ComplexType>()) {
llvm::Type *EltTy = ConvertType(CT->getElementType());
@ -443,32 +464,55 @@ CodeGenFunction::ExpandTypeFromArgs(QualType Ty, LValue LV,
llvm::Function::arg_iterator AI) {
assert(LV.isSimple() &&
"Unexpected non-simple lvalue during struct expansion.");
llvm::Value *Addr = LV.getAddress();
if (const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) {
unsigned NumElts = AT->getSize().getZExtValue();
QualType EltTy = AT->getElementType();
for (unsigned Elt = 0; Elt < NumElts; ++Elt) {
llvm::Value *EltAddr = Builder.CreateConstGEP2_32(Addr, 0, Elt);
llvm::Value *EltAddr = Builder.CreateConstGEP2_32(LV.getAddress(), 0, Elt);
LValue LV = MakeAddrLValue(EltAddr, EltTy);
AI = ExpandTypeFromArgs(EltTy, LV, AI);
}
} else if (const RecordType *RT = Ty->getAsStructureType()) {
} else if (const RecordType *RT = Ty->getAs<RecordType>()) {
RecordDecl *RD = RT->getDecl();
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
i != e; ++i) {
FieldDecl *FD = *i;
QualType FT = FD->getType();
if (RD->isUnion()) {
// Unions can be here only in degenerative cases - all the fields are same
// after flattening. Thus we have to use the "largest" field.
const FieldDecl *LargestFD = 0;
CharUnits UnionSize = CharUnits::Zero();
// FIXME: What are the right qualifiers here?
LValue LV = EmitLValueForField(Addr, FD, 0);
AI = ExpandTypeFromArgs(FT, LV, AI);
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
i != e; ++i) {
const FieldDecl *FD = *i;
assert(!FD->isBitField() &&
"Cannot expand structure with bit-field members.");
CharUnits FieldSize = getContext().getTypeSizeInChars(FD->getType());
if (UnionSize < FieldSize) {
UnionSize = FieldSize;
LargestFD = FD;
}
}
if (LargestFD) {
// FIXME: What are the right qualifiers here?
LValue SubLV = EmitLValueForField(LV, LargestFD);
AI = ExpandTypeFromArgs(LargestFD->getType(), SubLV, AI);
}
} else {
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
i != e; ++i) {
FieldDecl *FD = *i;
QualType FT = FD->getType();
// FIXME: What are the right qualifiers here?
LValue SubLV = EmitLValueForField(LV, FD);
AI = ExpandTypeFromArgs(FT, SubLV, AI);
}
}
} else if (const ComplexType *CT = Ty->getAs<ComplexType>()) {
QualType EltTy = CT->getElementType();
llvm::Value *RealAddr = Builder.CreateStructGEP(Addr, 0, "real");
llvm::Value *RealAddr = Builder.CreateStructGEP(LV.getAddress(), 0, "real");
EmitStoreThroughLValue(RValue::get(AI++), MakeAddrLValue(RealAddr, EltTy));
llvm::Value *ImagAddr = Builder.CreateStructGEP(Addr, 1, "imag");
llvm::Value *ImagAddr = Builder.CreateStructGEP(LV.getAddress(), 1, "imag");
EmitStoreThroughLValue(RValue::get(AI++), MakeAddrLValue(ImagAddr, EltTy));
} else {
EmitStoreThroughLValue(RValue::get(AI), LV);
@ -1760,26 +1804,38 @@ void CodeGenFunction::ExpandTypeToArgs(QualType Ty, RValue RV,
EltRV = EmitLoadOfLValue(LV);
ExpandTypeToArgs(EltTy, EltRV, Args, IRFuncTy);
}
} else if (const RecordType *RT = Ty->getAsStructureType()) {
} else if (const RecordType *RT = Ty->getAs<RecordType>()) {
RecordDecl *RD = RT->getDecl();
assert(RV.isAggregate() && "Unexpected rvalue during struct expansion");
llvm::Value *Addr = RV.getAggregateAddr();
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
i != e; ++i) {
FieldDecl *FD = *i;
QualType FT = FD->getType();
// FIXME: What are the right qualifiers here?
LValue LV = EmitLValueForField(Addr, FD, 0);
RValue FldRV;
if (FT->isAnyComplexType())
// FIXME: Volatile?
FldRV = RValue::getComplex(LoadComplexFromAddr(LV.getAddress(), false));
else if (CodeGenFunction::hasAggregateLLVMType(FT))
FldRV = LV.asAggregateRValue();
else
FldRV = EmitLoadOfLValue(LV);
ExpandTypeToArgs(FT, FldRV, Args, IRFuncTy);
LValue LV = MakeAddrLValue(RV.getAggregateAddr(), Ty);
if (RD->isUnion()) {
const FieldDecl *LargestFD = 0;
CharUnits UnionSize = CharUnits::Zero();
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
i != e; ++i) {
const FieldDecl *FD = *i;
assert(!FD->isBitField() &&
"Cannot expand structure with bit-field members.");
CharUnits FieldSize = getContext().getTypeSizeInChars(FD->getType());
if (UnionSize < FieldSize) {
UnionSize = FieldSize;
LargestFD = FD;
}
}
if (LargestFD) {
RValue FldRV = EmitRValueForField(LV, LargestFD);
ExpandTypeToArgs(LargestFD->getType(), FldRV, Args, IRFuncTy);
}
} else {
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
i != e; ++i) {
FieldDecl *FD = *i;
RValue FldRV = EmitRValueForField(LV, FD);
ExpandTypeToArgs(FD->getType(), FldRV, Args, IRFuncTy);
}
}
} else if (Ty->isAnyComplexType()) {
ComplexPairTy CV = RV.getComplexVal();

View File

@ -555,15 +555,17 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
QualType FieldType = Field->getType();
llvm::Value *ThisPtr = CGF.LoadCXXThis();
QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl);
LValue LHS;
// If we are initializing an anonymous union field, drill down to the field.
if (MemberInit->isIndirectMemberInitializer()) {
LHS = CGF.EmitLValueForAnonRecordField(ThisPtr,
MemberInit->getIndirectMember(), 0);
FieldType = MemberInit->getIndirectMember()->getAnonField()->getType();
} else {
LHS = CGF.EmitLValueForFieldInitialization(ThisPtr, Field, 0);
LValue ThisLHSLV = CGF.MakeNaturalAlignAddrLValue(ThisPtr, RecordTy);
LHS = CGF.EmitLValueForFieldInitialization(ThisLHSLV, Field);
}
// Special case: if we are in a copy or move constructor, and we are copying
@ -585,7 +587,8 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
unsigned SrcArgIndex = Args.size() - 1;
llvm::Value *SrcPtr
= CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(Args[SrcArgIndex]));
LValue Src = CGF.EmitLValueForFieldInitialization(SrcPtr, Field, 0);
LValue ThisRHSLV = CGF.MakeNaturalAlignAddrLValue(SrcPtr, RecordTy);
LValue Src = CGF.EmitLValueForFieldInitialization(ThisRHSLV, Field);
// Copy the aggregate.
CGF.EmitAggregateCopy(LHS.getAddress(), Src.getAddress(), FieldType,
@ -978,7 +981,9 @@ namespace {
void Emit(CodeGenFunction &CGF, Flags flags) {
// Find the address of the field.
llvm::Value *thisValue = CGF.LoadCXXThis();
LValue LV = CGF.EmitLValueForField(thisValue, field, /*CVRQualifiers=*/0);
QualType RecordTy = CGF.getContext().getTagDeclType(field->getParent());
LValue ThisLV = CGF.MakeAddrLValue(thisValue, RecordTy);
LValue LV = CGF.EmitLValueForField(ThisLV, field);
assert(LV.isSimple());
CGF.emitDestroy(LV.getAddress(), field->getType(), destroyer,

View File

@ -184,7 +184,6 @@ CGDebugInfo::getClassName(const RecordDecl *RD) {
const TemplateArgument *Args;
unsigned NumArgs;
std::string Buffer;
if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
const TemplateSpecializationType *TST =
cast<TemplateSpecializationType>(TAW->getType());
@ -195,16 +194,17 @@ CGDebugInfo::getClassName(const RecordDecl *RD) {
Args = TemplateArgs.data();
NumArgs = TemplateArgs.size();
}
Buffer = RD->getIdentifier()->getNameStart();
StringRef Name = RD->getIdentifier()->getName();
PrintingPolicy Policy(CGM.getLangOpts());
Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args,
NumArgs,
Policy);
std::string TemplateArgList =
TemplateSpecializationType::PrintTemplateArgumentList(Args, NumArgs, Policy);
// Copy this name on the side and use its reference.
char *StrPtr = DebugInfoNames.Allocate<char>(Buffer.length());
memcpy(StrPtr, Buffer.data(), Buffer.length());
return StringRef(StrPtr, Buffer.length());
size_t Length = Name.size() + TemplateArgList.size();
char *StrPtr = DebugInfoNames.Allocate<char>(Length);
memcpy(StrPtr, Name.data(), Name.size());
memcpy(StrPtr + Name.size(), TemplateArgList.data(), TemplateArgList.size());
return StringRef(StrPtr, Length);
}
/// getOrCreateFile - Get the file debug info descriptor for the input location.

View File

@ -1171,6 +1171,10 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) {
// If this was emitted as a global constant, we're done.
if (emission.wasEmittedAsGlobal()) return;
// If we don't have an insertion point, we're done. Sema prevents
// us from jumping into any of these scopes anyway.
if (!HaveInsertPoint()) return;
const VarDecl &D = *emission.Variable;
// Check the type for a cleanup.

View File

@ -24,6 +24,7 @@
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/Intrinsics.h"
#include "llvm/LLVMContext.h"
#include "llvm/Support/MDBuilder.h"
#include "llvm/Target/TargetData.h"
using namespace clang;
using namespace CodeGen;
@ -398,8 +399,8 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E,
break;
case SubobjectAdjustment::FieldAdjustment: {
LValue LV =
CGF.EmitLValueForField(Object, Adjustment.Field, 0);
LValue LV = CGF.MakeAddrLValue(Object, E->getType());
LV = CGF.EmitLValueForField(LV, Adjustment.Field);
if (LV.isSimple()) {
Object = LV.getAddress();
break;
@ -908,16 +909,8 @@ llvm::MDNode *CodeGenFunction::getRangeForLoadFromType(QualType Ty) {
}
}
if (End == Min)
return NULL;
llvm::Value *LowAndHigh[2];
LowAndHigh[0] = llvm::ConstantInt::get(LTy, Min);
LowAndHigh[1] = llvm::ConstantInt::get(LTy, End);
llvm::LLVMContext &C = getLLVMContext();
llvm::MDNode *Range = llvm::MDNode::get(C, LowAndHigh);
return Range;
llvm::MDBuilder MDHelper(getLLVMContext());
return MDHelper.createRange(Min, End);
}
llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
@ -1577,8 +1570,12 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
// Use special handling for lambdas.
if (!V) {
if (FieldDecl *FD = LambdaCaptureFields.lookup(VD))
return EmitLValueForField(CXXABIThisValue, FD, 0);
if (FieldDecl *FD = LambdaCaptureFields.lookup(VD)) {
QualType LambdaTagType = getContext().getTagDeclType(FD->getParent());
LValue LambdaLV = MakeNaturalAlignAddrLValue(CXXABIThisValue,
LambdaTagType);
return EmitLValueForField(LambdaLV, FD);
}
assert(isa<BlockDecl>(CurCodeDecl) && E->refersToEnclosingLocal());
CharUnits alignment = getContext().getDeclAlign(VD);
@ -1973,32 +1970,19 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
}
LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
bool isNonGC = false;
Expr *BaseExpr = E->getBase();
llvm::Value *BaseValue = NULL;
Qualifiers BaseQuals;
// If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar.
if (E->isArrow()) {
BaseValue = EmitScalarExpr(BaseExpr);
const PointerType *PTy =
BaseExpr->getType()->getAs<PointerType>();
BaseQuals = PTy->getPointeeType().getQualifiers();
} else {
LValue BaseLV = EmitLValue(BaseExpr);
if (BaseLV.isNonGC())
isNonGC = true;
// FIXME: this isn't right for bitfields.
BaseValue = BaseLV.getAddress();
QualType BaseTy = BaseExpr->getType();
BaseQuals = BaseTy.getQualifiers();
}
LValue BaseLV;
if (E->isArrow())
BaseLV = MakeNaturalAlignAddrLValue(EmitScalarExpr(BaseExpr),
BaseExpr->getType()->getPointeeType());
else
BaseLV = EmitLValue(BaseExpr);
NamedDecl *ND = E->getMemberDecl();
if (FieldDecl *Field = dyn_cast<FieldDecl>(ND)) {
LValue LV = EmitLValueForField(BaseValue, Field,
BaseQuals.getCVRQualifiers());
LV.setNonGC(isNonGC);
LValue LV = EmitLValueForField(BaseLV, Field);
setObjCGCLValueClass(getContext(), E, LV);
return LV;
}
@ -2032,8 +2016,10 @@ LValue CodeGenFunction::EmitLValueForAnonRecordField(llvm::Value *BaseValue,
IndirectFieldDecl::chain_iterator I = Field->chain_begin(),
IEnd = Field->chain_end();
while (true) {
LValue LV = EmitLValueForField(BaseValue, cast<FieldDecl>(*I),
CVRQualifiers);
QualType RecordTy =
getContext().getTypeDeclType(cast<FieldDecl>(*I)->getParent());
LValue LV = EmitLValueForField(MakeAddrLValue(BaseValue, RecordTy),
cast<FieldDecl>(*I));
if (++I == IEnd) return LV;
assert(LV.isSimple());
@ -2042,19 +2028,25 @@ LValue CodeGenFunction::EmitLValueForAnonRecordField(llvm::Value *BaseValue,
}
}
LValue CodeGenFunction::EmitLValueForField(llvm::Value *baseAddr,
const FieldDecl *field,
unsigned cvr) {
LValue CodeGenFunction::EmitLValueForField(LValue base,
const FieldDecl *field) {
if (field->isBitField())
return EmitLValueForBitfield(baseAddr, field, cvr);
return EmitLValueForBitfield(base.getAddress(), field,
base.getVRQualifiers());
const RecordDecl *rec = field->getParent();
QualType type = field->getType();
CharUnits alignment = getContext().getDeclAlign(field);
// FIXME: It should be impossible to have an LValue without alignment for a
// complete type.
if (!base.getAlignment().isZero())
alignment = std::min(alignment, base.getAlignment());
bool mayAlias = rec->hasAttr<MayAliasAttr>();
llvm::Value *addr = baseAddr;
llvm::Value *addr = base.getAddress();
unsigned cvr = base.getVRQualifiers();
if (rec->isUnion()) {
// For unions, there is no pointer adjustment.
assert(!type->isReferenceType() && "union has reference member");
@ -2117,30 +2109,33 @@ LValue CodeGenFunction::EmitLValueForField(llvm::Value *baseAddr,
}
LValue
CodeGenFunction::EmitLValueForFieldInitialization(llvm::Value *BaseValue,
const FieldDecl *Field,
unsigned CVRQualifiers) {
CodeGenFunction::EmitLValueForFieldInitialization(LValue Base,
const FieldDecl *Field) {
QualType FieldType = Field->getType();
if (!FieldType->isReferenceType())
return EmitLValueForField(BaseValue, Field, CVRQualifiers);
return EmitLValueForField(Base, Field);
const CGRecordLayout &RL =
CGM.getTypes().getCGRecordLayout(Field->getParent());
unsigned idx = RL.getLLVMFieldNo(Field);
llvm::Value *V = Builder.CreateStructGEP(BaseValue, idx);
llvm::Value *V = Builder.CreateStructGEP(Base.getAddress(), idx);
assert(!FieldType.getObjCGCAttr() && "fields cannot have GC attrs");
// Make sure that the address is pointing to the right type. This is critical
// for both unions and structs. A union needs a bitcast, a struct element
// will need a bitcast if the LLVM type laid out doesn't match the desired
// type.
llvm::Type *llvmType = ConvertTypeForMem(FieldType);
unsigned AS = cast<llvm::PointerType>(V->getType())->getAddressSpace();
V = Builder.CreateBitCast(V, llvmType->getPointerTo(AS));
V = EmitBitCastOfLValueToProperType(*this, V, llvmType, Field->getName());
CharUnits Alignment = getContext().getDeclAlign(Field);
// FIXME: It should be impossible to have an LValue without alignment for a
// complete type.
if (!Base.getAlignment().isZero())
Alignment = std::min(Alignment, Base.getAlignment());
return MakeAddrLValue(V, FieldType, Alignment);
}
@ -2378,6 +2373,19 @@ LValue CodeGenFunction::EmitMaterializeTemporaryExpr(
return MakeAddrLValue(RV.getScalarVal(), E->getType());
}
RValue CodeGenFunction::EmitRValueForField(LValue LV,
const FieldDecl *FD) {
QualType FT = FD->getType();
LValue FieldLV = EmitLValueForField(LV, FD);
if (FT->isAnyComplexType())
return RValue::getComplex(
LoadComplexFromAddr(FieldLV.getAddress(),
FieldLV.isVolatileQualified()));
else if (CodeGenFunction::hasAggregateLLVMType(FT))
return FieldLV.asAggregateRValue();
return EmitLoadOfLValue(FieldLV);
}
//===--------------------------------------------------------------------===//
// Expression Emission
@ -3158,11 +3166,10 @@ void CodeGenFunction::SetFPAccuracy(llvm::Value *Val, float Accuracy) {
if (Accuracy == 0.0 || !isa<llvm::Instruction>(Val))
return;
llvm::Value *ULPs = llvm::ConstantFP::get(Builder.getFloatTy(), Accuracy);
llvm::MDNode *Node = llvm::MDNode::get(getLLVMContext(), ULPs);
llvm::MDBuilder MDHelper(getLLVMContext());
llvm::MDNode *Node = MDHelper.createFPMath(Accuracy);
cast<llvm::Instruction>(Val)->setMetadata(llvm::LLVMContext::MD_fpaccuracy,
Node);
cast<llvm::Instruction>(Val)->setMetadata(llvm::LLVMContext::MD_fpmath, Node);
}
namespace {

View File

@ -238,7 +238,10 @@ void AggExprEmitter::EmitMoveFromReturnSlot(const Expr *E, RValue Src) {
// Otherwise, do a final copy,
assert(Dest.getAddr() != Src.getAggregateAddr());
EmitFinalDestCopy(E, Src, /*Ignore*/ true);
std::pair<CharUnits, CharUnits> TypeInfo =
CGF.getContext().getTypeInfoInChars(E->getType());
CharUnits Alignment = std::min(TypeInfo.second, Dest.getAlignment());
EmitFinalDestCopy(E, Src, /*Ignore*/ true, Alignment.getQuantity());
}
/// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired.
@ -348,7 +351,8 @@ void AggExprEmitter::EmitStdInitializerList(llvm::Value *destPtr,
CGF.ErrorUnsupported(initList, "weird std::initializer_list");
return;
}
LValue start = CGF.EmitLValueForFieldInitialization(destPtr, *field, 0);
LValue DestLV = CGF.MakeNaturalAlignAddrLValue(destPtr, initList->getType());
LValue start = CGF.EmitLValueForFieldInitialization(DestLV, *field);
llvm::Value *arrayStart = Builder.CreateStructGEP(alloc, 0, "arraystart");
CGF.EmitStoreThroughLValue(RValue::get(arrayStart), start);
++field;
@ -357,7 +361,7 @@ void AggExprEmitter::EmitStdInitializerList(llvm::Value *destPtr,
CGF.ErrorUnsupported(initList, "weird std::initializer_list");
return;
}
LValue endOrLength = CGF.EmitLValueForFieldInitialization(destPtr, *field, 0);
LValue endOrLength = CGF.EmitLValueForFieldInitialization(DestLV, *field);
if (ctx.hasSameType(field->getType(), elementPtr)) {
// End pointer.
llvm::Value *arrayEnd = Builder.CreateStructGEP(alloc,numInits, "arrayend");
@ -912,28 +916,24 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
return;
}
llvm::Value *DestPtr = EnsureSlot(E->getType()).getAddr();
AggValueSlot Dest = EnsureSlot(E->getType());
LValue DestLV = CGF.MakeAddrLValue(Dest.getAddr(), E->getType(),
Dest.getAlignment());
// Handle initialization of an array.
if (E->getType()->isArrayType()) {
if (E->getNumInits() > 0) {
QualType T1 = E->getType();
QualType T2 = E->getInit(0)->getType();
if (CGF.getContext().hasSameUnqualifiedType(T1, T2)) {
EmitAggLoadOfLValue(E->getInit(0));
return;
}
}
if (E->isStringLiteralInit())
return Visit(E->getInit(0));
QualType elementType =
CGF.getContext().getAsArrayType(E->getType())->getElementType();
llvm::PointerType *APType =
cast<llvm::PointerType>(DestPtr->getType());
cast<llvm::PointerType>(Dest.getAddr()->getType());
llvm::ArrayType *AType =
cast<llvm::ArrayType>(APType->getElementType());
EmitArrayInit(DestPtr, AType, elementType, E);
EmitArrayInit(Dest.getAddr(), AType, elementType, E);
return;
}
@ -966,7 +966,7 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
// FIXME: volatility
FieldDecl *Field = E->getInitializedFieldInUnion();
LValue FieldLoc = CGF.EmitLValueForFieldInitialization(DestPtr, Field, 0);
LValue FieldLoc = CGF.EmitLValueForFieldInitialization(DestLV, Field);
if (NumInitElements) {
// Store the initializer into the field
EmitInitializationToLValue(E->getInit(0), FieldLoc);
@ -1004,8 +1004,8 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
CGF.getTypes().isZeroInitializable(E->getType()))
break;
// FIXME: volatility
LValue LV = CGF.EmitLValueForFieldInitialization(DestPtr, *field, 0);
LValue LV = CGF.EmitLValueForFieldInitialization(DestLV, *field);
// We never generate write-barries for initialized fields.
LV.setNonGC(true);

View File

@ -1815,13 +1815,16 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *Value,
void CodeGenFunction::EmitLambdaExpr(const LambdaExpr *E, AggValueSlot Slot) {
RunCleanupsScope Scope(*this);
LValue SlotLV = MakeAddrLValue(Slot.getAddr(), E->getType(),
Slot.getAlignment());
CXXRecordDecl::field_iterator CurField = E->getLambdaClass()->field_begin();
for (LambdaExpr::capture_init_iterator i = E->capture_init_begin(),
e = E->capture_init_end();
i != e; ++i, ++CurField) {
// Emit initialization
LValue LV = EmitLValueForFieldInitialization(Slot.getAddr(), *CurField, 0);
LValue LV = EmitLValueForFieldInitialization(SlotLV, *CurField);
ArrayRef<VarDecl *> ArrayIndexes;
if (CurField->getType()->isArrayType())
ArrayIndexes = E->getCaptureInitIndexVars(i);

View File

@ -758,17 +758,13 @@ class ConstExprEmitter :
}
llvm::Constant *EmitArrayInitialization(InitListExpr *ILE) {
unsigned NumInitElements = ILE->getNumInits();
if (NumInitElements == 1 &&
CGM.getContext().hasSameUnqualifiedType(ILE->getType(),
ILE->getInit(0)->getType()) &&
(isa<StringLiteral>(ILE->getInit(0)) ||
isa<ObjCEncodeExpr>(ILE->getInit(0))))
if (ILE->isStringLiteralInit())
return Visit(ILE->getInit(0));
llvm::ArrayType *AType =
cast<llvm::ArrayType>(ConvertType(ILE->getType()));
llvm::Type *ElemTy = AType->getElementType();
unsigned NumInitElements = ILE->getNumInits();
unsigned NumElements = AType->getNumElements();
// Initialising an array requires us to automatically

View File

@ -79,6 +79,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
case Stmt::CompoundStmtClass:
case Stmt::DeclStmtClass:
case Stmt::LabelStmtClass:
case Stmt::AttributedStmtClass:
case Stmt::GotoStmtClass:
case Stmt::BreakStmtClass:
case Stmt::ContinueStmtClass:
@ -173,6 +174,8 @@ bool CodeGenFunction::EmitSimpleStmt(const Stmt *S) {
case Stmt::CompoundStmtClass: EmitCompoundStmt(cast<CompoundStmt>(*S)); break;
case Stmt::DeclStmtClass: EmitDeclStmt(cast<DeclStmt>(*S)); break;
case Stmt::LabelStmtClass: EmitLabelStmt(cast<LabelStmt>(*S)); break;
case Stmt::AttributedStmtClass:
EmitAttributedStmt(cast<AttributedStmt>(*S)); break;
case Stmt::GotoStmtClass: EmitGotoStmt(cast<GotoStmt>(*S)); break;
case Stmt::BreakStmtClass: EmitBreakStmt(cast<BreakStmt>(*S)); break;
case Stmt::ContinueStmtClass: EmitContinueStmt(cast<ContinueStmt>(*S)); break;
@ -332,6 +335,10 @@ void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) {
EmitStmt(S.getSubStmt());
}
void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {
EmitStmt(S.getSubStmt());
}
void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {
// If this code is reachable then emit a stop point (if generating
// debug info). We have to do this ourselves because we are on the

View File

@ -22,8 +22,9 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/StmtCXX.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Intrinsics.h"
#include "llvm/Support/MDBuilder.h"
#include "llvm/Target/TargetData.h"
using namespace clang;
using namespace CodeGen;
@ -362,8 +363,12 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
LambdaThisCaptureField);
if (LambdaThisCaptureField) {
// If this lambda captures this, load it.
LValue ThisLValue = EmitLValueForField(CXXABIThisValue,
LambdaThisCaptureField, 0);
QualType LambdaTagType =
getContext().getTagDeclType(LambdaThisCaptureField->getParent());
LValue LambdaLV = MakeNaturalAlignAddrLValue(CXXABIThisValue,
LambdaTagType);
LValue ThisLValue = EmitLValueForField(LambdaLV,
LambdaThisCaptureField);
CXXThisValue = EmitLoadOfLValue(ThisLValue).getScalarVal();
}
} else {

View File

@ -1948,6 +1948,7 @@ class CodeGenFunction : public CodeGenTypeCache {
void EmitLabel(const LabelDecl *D); // helper for EmitLabelStmt.
void EmitLabelStmt(const LabelStmt &S);
void EmitAttributedStmt(const AttributedStmt &S);
void EmitGotoStmt(const GotoStmt &S);
void EmitIndirectGotoStmt(const IndirectGotoStmt &S);
void EmitIfStmt(const IfStmt &S);
@ -2104,6 +2105,8 @@ class CodeGenFunction : public CodeGenTypeCache {
LValue EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E);
LValue EmitOpaqueValueLValue(const OpaqueValueExpr *e);
RValue EmitRValueForField(LValue LV, const FieldDecl *FD);
class ConstantEmission {
llvm::PointerIntPair<llvm::Constant*, 1, bool> ValueAndIsReference;
ConstantEmission(llvm::Constant *C, bool isReference)
@ -2143,15 +2146,13 @@ class CodeGenFunction : public CodeGenTypeCache {
LValue EmitLValueForAnonRecordField(llvm::Value* Base,
const IndirectFieldDecl* Field,
unsigned CVRQualifiers);
LValue EmitLValueForField(llvm::Value* Base, const FieldDecl* Field,
unsigned CVRQualifiers);
LValue EmitLValueForField(LValue Base, const FieldDecl* Field);
/// EmitLValueForFieldInitialization - Like EmitLValueForField, except that
/// if the Field is a reference, this will return the address of the reference
/// and not the address of the value stored in the reference.
LValue EmitLValueForFieldInitialization(llvm::Value* Base,
const FieldDecl* Field,
unsigned CVRQualifiers);
LValue EmitLValueForFieldInitialization(LValue Base,
const FieldDecl* Field);
LValue EmitLValueForIvar(QualType ObjectTy,
llvm::Value* Base, const ObjCIvarDecl *Ivar,

View File

@ -1241,7 +1241,7 @@ CodeGenModule::CreateOrReplaceCXXRuntimeVariable(StringRef Name,
/// GetAddrOfGlobalVar - Return the llvm::Constant for the address of the
/// given global variable. If Ty is non-null and if the global doesn't exist,
/// then it will be greated with the specified type instead of whatever the
/// then it will be created with the specified type instead of whatever the
/// normal requested type would be.
llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D,
llvm::Type *Ty) {

View File

@ -28,7 +28,7 @@ using namespace CodeGen;
CodeGenTBAA::CodeGenTBAA(ASTContext &Ctx, llvm::LLVMContext& VMContext,
const LangOptions &Features, MangleContext &MContext)
: Context(Ctx), VMContext(VMContext), Features(Features), MContext(MContext),
Root(0), Char(0) {
MDHelper(VMContext), Root(0), Char(0) {
}
CodeGenTBAA::~CodeGenTBAA() {
@ -40,7 +40,7 @@ llvm::MDNode *CodeGenTBAA::getRoot() {
// (or a different version of this front-end), their TBAA trees will
// remain distinct, and the optimizer will treat them conservatively.
if (!Root)
Root = getTBAAInfoForNamedType("Simple C/C++ TBAA", 0);
Root = MDHelper.createTBAARoot("Simple C/C++ TBAA");
return Root;
}
@ -51,33 +51,11 @@ llvm::MDNode *CodeGenTBAA::getChar() {
// these special powers only cover user-accessible memory, and doesn't
// include things like vtables.
if (!Char)
Char = getTBAAInfoForNamedType("omnipotent char", getRoot());
Char = MDHelper.createTBAANode("omnipotent char", getRoot());
return Char;
}
/// getTBAAInfoForNamedType - Create a TBAA tree node with the given string
/// as its identifier, and the given Parent node as its tree parent.
llvm::MDNode *CodeGenTBAA::getTBAAInfoForNamedType(StringRef NameStr,
llvm::MDNode *Parent,
bool Readonly) {
// Currently there is only one flag defined - the readonly flag.
llvm::Value *Flags = 0;
if (Readonly)
Flags = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), true);
// Set up the mdnode operand list.
llvm::Value *Ops[] = {
llvm::MDString::get(VMContext, NameStr),
Parent,
Flags
};
// Create the mdnode.
unsigned Len = llvm::array_lengthof(Ops) - !Flags;
return llvm::MDNode::get(VMContext, llvm::makeArrayRef(Ops, Len));
}
static bool TypeHasMayAlias(QualType QTy) {
// Tagged types have declarations, and therefore may have attributes.
if (const TagType *TTy = dyn_cast<TagType>(QTy))
@ -137,7 +115,7 @@ CodeGenTBAA::getTBAAInfo(QualType QTy) {
// "underlying types".
default:
return MetadataCache[Ty] =
getTBAAInfoForNamedType(BTy->getName(Features), getChar());
MDHelper.createTBAANode(BTy->getName(Features), getChar());
}
}
@ -145,7 +123,7 @@ CodeGenTBAA::getTBAAInfo(QualType QTy) {
// TODO: Implement C++'s type "similarity" and consider dis-"similar"
// pointers distinct.
if (Ty->isPointerType())
return MetadataCache[Ty] = getTBAAInfoForNamedType("any pointer",
return MetadataCache[Ty] = MDHelper.createTBAANode("any pointer",
getChar());
// Enum types are distinct types. In C++ they have "underlying types",
@ -173,7 +151,7 @@ CodeGenTBAA::getTBAAInfo(QualType QTy) {
llvm::raw_svector_ostream Out(OutName);
MContext.mangleCXXRTTIName(QualType(ETy, 0), Out);
Out.flush();
return MetadataCache[Ty] = getTBAAInfoForNamedType(OutName, getChar());
return MetadataCache[Ty] = MDHelper.createTBAANode(OutName, getChar());
}
// For now, handle any other kind of type conservatively.
@ -181,5 +159,5 @@ CodeGenTBAA::getTBAAInfo(QualType QTy) {
}
llvm::MDNode *CodeGenTBAA::getTBAAInfoForVTablePtr() {
return getTBAAInfoForNamedType("vtable pointer", getRoot());
return MDHelper.createTBAANode("vtable pointer", getRoot());
}

View File

@ -17,6 +17,7 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/MDBuilder.h"
namespace llvm {
class LLVMContext;
@ -41,6 +42,9 @@ class CodeGenTBAA {
const LangOptions &Features;
MangleContext &MContext;
// MDHelper - Helper for creating metadata.
llvm::MDBuilder MDHelper;
/// MetadataCache - This maps clang::Types to llvm::MDNodes describing them.
llvm::DenseMap<const Type *, llvm::MDNode *> MetadataCache;
@ -55,10 +59,6 @@ class CodeGenTBAA {
/// considered to be equivalent to it.
llvm::MDNode *getChar();
llvm::MDNode *getTBAAInfoForNamedType(StringRef NameStr,
llvm::MDNode *Parent,
bool Readonly = false);
public:
CodeGenTBAA(ASTContext &Ctx, llvm::LLVMContext &VMContext,
const LangOptions &Features,

View File

@ -2527,19 +2527,16 @@ void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const {
static bool isHomogeneousAggregate(QualType Ty, const Type *&Base,
ASTContext &Context,
uint64_t *HAMembers = 0) {
uint64_t Members;
uint64_t Members = 0;
if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) {
if (!isHomogeneousAggregate(AT->getElementType(), Base, Context, &Members))
return false;
Members *= AT->getSize().getZExtValue();
} else if (const RecordType *RT = Ty->getAs<RecordType>()) {
const RecordDecl *RD = RT->getDecl();
if (RD->isUnion() || RD->hasFlexibleArrayMember())
if (RD->hasFlexibleArrayMember())
return false;
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
if (!CXXRD->isAggregate())
return false;
}
Members = 0;
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
i != e; ++i) {
@ -2547,7 +2544,9 @@ static bool isHomogeneousAggregate(QualType Ty, const Type *&Base,
uint64_t FldMembers;
if (!isHomogeneousAggregate(FD->getType(), Base, Context, &FldMembers))
return false;
Members += FldMembers;
Members = (RD->isUnion() ?
std::max(Members, FldMembers) : Members + FldMembers);
}
} else {
Members = 1;
@ -2584,7 +2583,8 @@ static bool isHomogeneousAggregate(QualType Ty, const Type *&Base,
// Homogeneous Aggregates can have at most 4 members of the base type.
if (HAMembers)
*HAMembers = Members;
return (Members <= 4);
return (Members > 0 && Members <= 4);
}
ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty) const {
@ -2609,8 +2609,10 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty) const {
if (getABIKind() == ARMABIInfo::AAPCS_VFP) {
// Homogeneous Aggregates need to be expanded.
const Type *Base = 0;
if (isHomogeneousAggregate(Ty, Base, getContext()))
if (isHomogeneousAggregate(Ty, Base, getContext())) {
assert(Base && "Base class should be set for homogeneous aggregate");
return ABIArgInfo::getExpand();
}
}
// Otherwise, pass by coercing to a structure of the appropriate size.
@ -2776,9 +2778,11 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy) const {
// Check for homogeneous aggregates with AAPCS-VFP.
if (getABIKind() == AAPCS_VFP) {
const Type *Base = 0;
if (isHomogeneousAggregate(RetTy, Base, getContext()))
if (isHomogeneousAggregate(RetTy, Base, getContext())) {
assert(Base && "Base class should be set for homogeneous aggregate");
// Homogeneous Aggregates are returned directly.
return ABIArgInfo::getDirect();
}
}
// Aggregates <= 4 bytes are returned in r0; other aggregates

View File

@ -230,3 +230,7 @@ void Compilation::initCompilationForDiagnostics(void) {
Redirects[1] = new const llvm::sys::Path();
Redirects[2] = new const llvm::sys::Path();
}
StringRef Compilation::getSysRoot(void) const {
return getDriver().SysRoot;
}

View File

@ -49,8 +49,8 @@ Driver::Driver(StringRef ClangExecutable,
bool IsProduction,
DiagnosticsEngine &Diags)
: Opts(createDriverOptTable()), Diags(Diags),
ClangExecutable(ClangExecutable), UseStdLib(true),
DefaultTargetTriple(DefaultTargetTriple),
ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT),
UseStdLib(true), DefaultTargetTriple(DefaultTargetTriple),
DefaultImageName(DefaultImageName),
DriverTitle("clang \"gcc-compatible\" driver"),
CCPrintOptionsFilename(0), CCPrintHeadersFilename(0),
@ -660,9 +660,7 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
llvm::outs() << "\n";
llvm::outs() << "libraries: =" << ResourceDir;
std::string sysroot;
if (Arg *A = C.getArgs().getLastArg(options::OPT__sysroot_EQ))
sysroot = A->getValue(C.getArgs());
StringRef sysroot = C.getSysRoot();
for (ToolChain::path_list::const_iterator it = TC.getFilePaths().begin(),
ie = TC.getFilePaths().end(); it != ie; ++it) {
@ -872,30 +870,30 @@ void Driver::BuildUniversalActions(const ToolChain &TC,
// Handle debug info queries.
Arg *A = Args.getLastArg(options::OPT_g_Group);
if (A && !A->getOption().matches(options::OPT_g0) &&
!A->getOption().matches(options::OPT_gstabs) &&
ContainsCompileOrAssembleAction(Actions.back())) {
// Add a 'dsymutil' step if necessary, when debug info is enabled and we
// have a compile input. We need to run 'dsymutil' ourselves in such cases
// because the debug info will refer to a temporary object file which is
// will be removed at the end of the compilation process.
if (Act->getType() == types::TY_Image) {
ActionList Inputs;
Inputs.push_back(Actions.back());
Actions.pop_back();
Actions.push_back(new DsymutilJobAction(Inputs, types::TY_dSYM));
}
// Verify the output (debug information only) if we passed '-verify'.
if (Args.hasArg(options::OPT_verify)) {
ActionList VerifyInputs;
VerifyInputs.push_back(Actions.back());
Actions.pop_back();
Actions.push_back(new VerifyJobAction(VerifyInputs,
types::TY_Nothing));
}
if (A && !A->getOption().matches(options::OPT_g0) &&
!A->getOption().matches(options::OPT_gstabs) &&
ContainsCompileOrAssembleAction(Actions.back())) {
// Add a 'dsymutil' step if necessary, when debug info is enabled and we
// have a compile input. We need to run 'dsymutil' ourselves in such cases
// because the debug info will refer to a temporary object file which is
// will be removed at the end of the compilation process.
if (Act->getType() == types::TY_Image) {
ActionList Inputs;
Inputs.push_back(Actions.back());
Actions.pop_back();
Actions.push_back(new DsymutilJobAction(Inputs, types::TY_dSYM));
}
// Verify the output (debug information only) if we passed '-verify'.
if (Args.hasArg(options::OPT_verify)) {
ActionList VerifyInputs;
VerifyInputs.push_back(Actions.back());
Actions.pop_back();
Actions.push_back(new VerifyJobAction(VerifyInputs,
types::TY_Nothing));
}
}
}
}

View File

@ -580,7 +580,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
// If no '-miphoneos-version-min' specified on the command line and
// IPHONEOS_DEPLOYMENT_TARGET is not defined, see if we can set the default
// based on isysroot.
// based on -isysroot.
if (iOSTarget.empty()) {
if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
StringRef first, second;
@ -1086,6 +1086,7 @@ bool Generic_GCC::GCCVersion::operator<(const GCCVersion &RHS) const {
// a patch.
if (RHS.Patch == -1) return true; if (Patch == -1) return false;
if (Patch < RHS.Patch) return true; if (Patch > RHS.Patch) return false;
if (PatchSuffix == RHS.PatchSuffix) return false;
// Finally, between completely tied version numbers, the version with the
// suffix loses as we prefer full releases.
@ -1103,7 +1104,7 @@ static StringRef getGCCToolchainDir(const ArgList &Args) {
/// \brief Construct a GCCInstallationDetector from the driver.
///
/// This performs all of the autodetection and sets up the various paths.
/// Once constructed, a GCCInstallation is esentially immutable.
/// Once constructed, a GCCInstallationDetector is essentially immutable.
///
/// FIXME: We shouldn't need an explicit TargetTriple parameter here, and
/// should instead pull the target out of the driver. This is currently
@ -2063,7 +2064,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
// If the GCC installation we found is inside of the sysroot, we want to
// prefer libraries installed in the parent prefix of the GCC installation.
// It is important to *not* use these paths when the GCC installation is
// outside of the system root as that can pick up un-intented libraries.
// outside of the system root as that can pick up unintended libraries.
// This usually happens when there is an external cross compiler on the
// host system, and a more minimal sysroot available that is the target of
// the cross.

View File

@ -377,10 +377,11 @@ void Clang::AddPreprocessingOptions(Compilation &C,
// If we have a --sysroot, and don't have an explicit -isysroot flag, add an
// -isysroot to the CC1 invocation.
if (Arg *A = Args.getLastArg(options::OPT__sysroot_EQ)) {
StringRef sysroot = C.getSysRoot();
if (sysroot != "") {
if (!Args.hasArg(options::OPT_isysroot)) {
CmdArgs.push_back("-isysroot");
CmdArgs.push_back(A->getValue(Args));
CmdArgs.push_back(C.getArgs().MakeArgString(sysroot));
}
}
@ -4016,9 +4017,10 @@ void darwin::Link::AddLinkArgs(Compilation &C,
// Give --sysroot= preference, over the Apple specific behavior to also use
// --isysroot as the syslibroot.
if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ)) {
StringRef sysroot = C.getSysRoot();
if (sysroot != "") {
CmdArgs.push_back("-syslibroot");
CmdArgs.push_back(A->getValue(Args));
CmdArgs.push_back(C.getArgs().MakeArgString(sysroot));
} else if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
CmdArgs.push_back("-syslibroot");
CmdArgs.push_back(A->getValue(Args));

View File

@ -643,8 +643,10 @@ void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> &Diags,
DiagnosticConsumer *Client = 0;
if (CaptureDiagnostics)
Client = new StoredDiagnosticConsumer(AST.StoredDiagnostics);
Diags = CompilerInstance::createDiagnostics(DiagOpts, ArgEnd- ArgBegin,
ArgBegin, Client);
Diags = CompilerInstance::createDiagnostics(DiagOpts, ArgEnd-ArgBegin,
ArgBegin, Client,
/*ShouldOwnClient=*/true,
/*ShouldCloneClient=*/false);
} else if (CaptureDiagnostics) {
Diags->setClient(new StoredDiagnosticConsumer(AST.StoredDiagnostics));
}

View File

@ -651,6 +651,10 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
// created. This complexity should be lifted elsewhere.
getTarget().setForcedLangOptions(getLangOpts());
// rewriter project will change target built-in bool type from its default.
if (getFrontendOpts().ProgramAction == frontend::RewriteObjC)
getTarget().noSignedCharForObjCBool();
// Validate/process some options.
if (getHeaderSearchOpts().Verbose)
OS << "clang -cc1 version " CLANG_VERSION_STRING

View File

@ -429,7 +429,6 @@ static const char *getActionName(frontend::ActionKind Kind) {
case frontend::PrintDeclContext: return "-print-decl-contexts";
case frontend::PrintPreamble: return "-print-preamble";
case frontend::PrintPreprocessedInput: return "-E";
case frontend::PubnamesDump: return "-pubnames-dump";
case frontend::RewriteMacros: return "-rewrite-macros";
case frontend::RewriteObjC: return "-rewrite-objc";
case frontend::RewriteTest: return "-rewrite-test";
@ -1369,8 +1368,6 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.ProgramAction = frontend::PrintPreamble; break;
case OPT_E:
Opts.ProgramAction = frontend::PrintPreprocessedInput; break;
case OPT_pubnames_dump:
Opts.ProgramAction = frontend::PubnamesDump; break;
case OPT_rewrite_macros:
Opts.ProgramAction = frontend::RewriteMacros; break;
case OPT_rewrite_objc:

View File

@ -25,7 +25,6 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/system_error.h"
#include <set>
using namespace clang;
@ -355,77 +354,6 @@ ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI,
return new ASTConsumer();
}
namespace {
class PubnamesDumpConsumer : public ASTConsumer {
Preprocessor &PP;
/// \brief Determine whether the given identifier provides a 'public' name.
bool isPublicName(IdentifierInfo *II) {
// If there are any top-level declarations associated with this
// identifier, it is a public name.
if (II->getFETokenInfo<void>())
return true;
// If this identifier is the name of a non-builtin macro that isn't
// defined on the command line or implicitly by the front end, it is a
// public name.
if (II->hasMacroDefinition()) {
if (MacroInfo *M = PP.getMacroInfo(II))
if (!M->isBuiltinMacro()) {
SourceLocation Loc = M->getDefinitionLoc();
FileID File = PP.getSourceManager().getFileID(Loc);
if (PP.getSourceManager().getFileEntryForID(File))
return true;
}
}
return false;
}
public:
PubnamesDumpConsumer(Preprocessor &PP) : PP(PP) { }
virtual void HandleTranslationUnit(ASTContext &Ctx) {
std::set<StringRef> Pubnames;
// Add the names of any non-builtin macros.
for (IdentifierTable::iterator I = Ctx.Idents.begin(),
IEnd = Ctx.Idents.end();
I != IEnd; ++I) {
if (isPublicName(I->second))
Pubnames.insert(I->first());
}
// If there is an external identifier lookup source, consider those
// identifiers as well.
if (IdentifierInfoLookup *External
= Ctx.Idents.getExternalIdentifierLookup()) {
OwningPtr<IdentifierIterator> Iter(External->getIdentifiers());
do {
StringRef Name = Iter->Next();
if (Name.empty())
break;
if (isPublicName(PP.getIdentifierInfo(Name)))
Pubnames.insert(Name);
} while (true);
}
// Print the names, in lexicographical order.
for (std::set<StringRef>::iterator N = Pubnames.begin(),
NEnd = Pubnames.end();
N != NEnd; ++N) {
llvm::outs() << *N << '\n';
}
}
};
}
ASTConsumer *PubnamesDumpAction::CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) {
return new PubnamesDumpConsumer(CI.getPreprocessor());
}
//===----------------------------------------------------------------------===//
// Preprocessor Actions
//===----------------------------------------------------------------------===//

View File

@ -10,13 +10,17 @@
#include "clang/Frontend/TextDiagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/ConvertUTF.h"
#include "clang/Frontend/DiagnosticOptions.h"
#include "clang/Lex/Lexer.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Locale.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include <algorithm>
using namespace clang;
static const enum raw_ostream::Colors noteColor =
@ -36,23 +40,269 @@ static const enum raw_ostream::Colors savedColor =
/// \brief Number of spaces to indent when word-wrapping.
const unsigned WordWrapIndentation = 6;
int bytesSincePreviousTabOrLineBegin(StringRef SourceLine, size_t i) {
int bytes = 0;
while (0<i) {
if (SourceLine[--i]=='\t')
break;
++bytes;
}
return bytes;
}
/// \brief returns a printable representation of first item from input range
///
/// This function returns a printable representation of the next item in a line
/// of source. If the next byte begins a valid and printable character, that
/// character is returned along with 'true'.
///
/// Otherwise, if the next byte begins a valid, but unprintable character, a
/// printable, escaped representation of the character is returned, along with
/// 'false'. Otherwise a printable, escaped representation of the next byte
/// is returned along with 'false'.
///
/// \note The index is updated to be used with a subsequent call to
/// printableTextForNextCharacter.
///
/// \param SourceLine The line of source
/// \param i Pointer to byte index,
/// \param TabStop used to expand tabs
/// \return pair(printable text, 'true' iff original text was printable)
///
std::pair<SmallString<16>,bool>
printableTextForNextCharacter(StringRef SourceLine, size_t *i,
unsigned TabStop) {
assert(i && "i must not be null");
assert(*i<SourceLine.size() && "must point to a valid index");
if (SourceLine[*i]=='\t') {
assert(0 < TabStop && TabStop <= DiagnosticOptions::MaxTabStop &&
"Invalid -ftabstop value");
unsigned col = bytesSincePreviousTabOrLineBegin(SourceLine, *i);
unsigned NumSpaces = TabStop - col%TabStop;
assert(0 < NumSpaces && NumSpaces <= TabStop
&& "Invalid computation of space amt");
++(*i);
SmallString<16> expandedTab;
expandedTab.assign(NumSpaces, ' ');
return std::make_pair(expandedTab, true);
}
// FIXME: this data is copied from the private implementation of ConvertUTF.h
static const char trailingBytesForUTF8[256] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
};
unsigned char const *begin, *end;
begin = reinterpret_cast<unsigned char const *>(&*(SourceLine.begin() + *i));
end = begin + SourceLine.size();
if (isLegalUTF8Sequence(begin, end)) {
UTF32 c;
UTF32 *cptr = &c;
unsigned char const *original_begin = begin;
char trailingBytes = trailingBytesForUTF8[(unsigned char)SourceLine[*i]];
unsigned char const *cp_end = begin+trailingBytes+1;
ConversionResult res = ConvertUTF8toUTF32(&begin, cp_end, &cptr, cptr+1,
strictConversion);
(void)res;
assert(conversionOK==res);
assert(0 < begin-original_begin
&& "we must be further along in the string now");
*i += begin-original_begin;
if (!llvm::sys::locale::isPrint(c)) {
// If next character is valid UTF-8, but not printable
SmallString<16> expandedCP("<U+>");
while (c) {
expandedCP.insert(expandedCP.begin()+3, llvm::hexdigit(c%16));
c/=16;
}
while (expandedCP.size() < 8)
expandedCP.insert(expandedCP.begin()+3, llvm::hexdigit(0));
return std::make_pair(expandedCP, false);
}
// If next character is valid UTF-8, and printable
return std::make_pair(SmallString<16>(original_begin, cp_end), true);
}
// If next byte is not valid UTF-8 (and therefore not printable)
SmallString<16> expandedByte("<XX>");
unsigned char byte = SourceLine[*i];
expandedByte[1] = llvm::hexdigit(byte / 16);
expandedByte[2] = llvm::hexdigit(byte % 16);
++(*i);
return std::make_pair(expandedByte, false);
}
void expandTabs(std::string &SourceLine, unsigned TabStop) {
size_t i = SourceLine.size();
while (i>0) {
i--;
if (SourceLine[i]!='\t')
continue;
size_t tmp_i = i;
std::pair<SmallString<16>,bool> res
= printableTextForNextCharacter(SourceLine, &tmp_i, TabStop);
SourceLine.replace(i, 1, res.first.c_str());
}
}
/// This function takes a raw source line and produces a mapping from the bytes
/// of the printable representation of the line to the columns those printable
/// characters will appear at (numbering the first column as 0).
///
/// If a byte 'i' corresponds to muliple columns (e.g. the byte contains a tab
/// character) then the the array will map that byte to the first column the
/// tab appears at and the next value in the map will have been incremented
/// more than once.
///
/// If a byte is the first in a sequence of bytes that together map to a single
/// entity in the output, then the array will map that byte to the appropriate
/// column while the subsequent bytes will be -1.
///
/// The last element in the array does not correspond to any byte in the input
/// and instead is the number of columns needed to display the source
///
/// example: (given a tabstop of 8)
///
/// "a \t \u3042" -> {0,1,2,8,9,-1,-1,11}
///
/// (\u3042 is represented in UTF-8 by three bytes and takes two columns to
/// display)
void byteToColumn(StringRef SourceLine, unsigned TabStop,
SmallVectorImpl<int> &out) {
out.clear();
if (SourceLine.empty()) {
out.resize(1u,0);
return;
}
out.resize(SourceLine.size()+1, -1);
int columns = 0;
size_t i = 0;
while (i<SourceLine.size()) {
out[i] = columns;
std::pair<SmallString<16>,bool> res
= printableTextForNextCharacter(SourceLine, &i, TabStop);
columns += llvm::sys::locale::columnWidth(res.first);
}
out.back() = columns;
}
/// This function takes a raw source line and produces a mapping from columns
/// to the byte of the source line that produced the character displaying at
/// that column. This is the inverse of the mapping produced by byteToColumn()
///
/// The last element in the array is the number of bytes in the source string
///
/// example: (given a tabstop of 8)
///
/// "a \t \u3042" -> {0,1,2,-1,-1,-1,-1,-1,3,4,-1,7}
///
/// (\u3042 is represented in UTF-8 by three bytes and takes two columns to
/// display)
void columnToByte(StringRef SourceLine, unsigned TabStop,
SmallVectorImpl<int> &out) {
out.clear();
if (SourceLine.empty()) {
out.resize(1u, 0);
return;
}
int columns = 0;
size_t i = 0;
while (i<SourceLine.size()) {
out.resize(columns+1, -1);
out.back() = i;
std::pair<SmallString<16>,bool> res
= printableTextForNextCharacter(SourceLine, &i, TabStop);
columns += llvm::sys::locale::columnWidth(res.first);
}
out.resize(columns+1, -1);
out.back() = i;
}
struct SourceColumnMap {
SourceColumnMap(StringRef SourceLine, unsigned TabStop)
: m_SourceLine(SourceLine) {
::byteToColumn(SourceLine, TabStop, m_byteToColumn);
::columnToByte(SourceLine, TabStop, m_columnToByte);
assert(m_byteToColumn.size()==SourceLine.size()+1);
assert(0 < m_byteToColumn.size() && 0 < m_columnToByte.size());
assert(m_byteToColumn.size()
== static_cast<unsigned>(m_columnToByte.back()+1));
assert(static_cast<unsigned>(m_byteToColumn.back()+1)
== m_columnToByte.size());
}
int columns() const { return m_byteToColumn.back(); }
int bytes() const { return m_columnToByte.back(); }
int byteToColumn(int n) const {
assert(0<=n && n<static_cast<int>(m_byteToColumn.size()));
return m_byteToColumn[n];
}
int columnToByte(int n) const {
assert(0<=n && n<static_cast<int>(m_columnToByte.size()));
return m_columnToByte[n];
}
StringRef getSourceLine() const {
return m_SourceLine;
}
private:
const std::string m_SourceLine;
SmallVector<int,200> m_byteToColumn;
SmallVector<int,200> m_columnToByte;
};
// used in assert in selectInterestingSourceRegion()
namespace {
struct char_out_of_range {
const char lower,upper;
char_out_of_range(char lower, char upper) :
lower(lower), upper(upper) {}
bool operator()(char c) { return c < lower || upper < c; }
};
}
/// \brief When the source code line we want to print is too long for
/// the terminal, select the "interesting" region.
static void selectInterestingSourceRegion(std::string &SourceLine,
std::string &CaretLine,
std::string &FixItInsertionLine,
unsigned EndOfCaretToken,
unsigned Columns) {
unsigned MaxSize = std::max(SourceLine.size(),
std::max(CaretLine.size(),
FixItInsertionLine.size()));
if (MaxSize > SourceLine.size())
SourceLine.resize(MaxSize, ' ');
if (MaxSize > CaretLine.size())
CaretLine.resize(MaxSize, ' ');
if (!FixItInsertionLine.empty() && MaxSize > FixItInsertionLine.size())
FixItInsertionLine.resize(MaxSize, ' ');
unsigned Columns,
const SourceColumnMap &map) {
unsigned MaxColumns = std::max<unsigned>(map.columns(),
std::max(CaretLine.size(),
FixItInsertionLine.size()));
// if the number of columns is less than the desired number we're done
if (MaxColumns <= Columns)
return;
// no special characters allowed in CaretLine or FixItInsertionLine
assert(CaretLine.end() ==
std::find_if(CaretLine.begin(), CaretLine.end(),
char_out_of_range(' ','~')));
assert(FixItInsertionLine.end() ==
std::find_if(FixItInsertionLine.begin(), FixItInsertionLine.end(),
char_out_of_range(' ','~')));
// Find the slice that we need to display the full caret line
// correctly.
unsigned CaretStart = 0, CaretEnd = CaretLine.size();
@ -64,10 +314,8 @@ static void selectInterestingSourceRegion(std::string &SourceLine,
if (!isspace(CaretLine[CaretEnd - 1]))
break;
// Make sure we don't chop the string shorter than the caret token
// itself.
if (CaretEnd < EndOfCaretToken)
CaretEnd = EndOfCaretToken;
// caret has already been inserted into CaretLine so the above whitespace
// check is guaranteed to include the caret
// If we have a fix-it line, make sure the slice includes all of the
// fix-it information.
@ -81,10 +329,8 @@ static void selectInterestingSourceRegion(std::string &SourceLine,
if (!isspace(FixItInsertionLine[FixItEnd - 1]))
break;
if (FixItStart < CaretStart)
CaretStart = FixItStart;
if (FixItEnd > CaretEnd)
CaretEnd = FixItEnd;
CaretStart = std::min(FixItStart, CaretStart);
CaretEnd = std::max(FixItEnd, CaretEnd);
}
// CaretLine[CaretStart, CaretEnd) contains all of the interesting
@ -92,62 +338,72 @@ static void selectInterestingSourceRegion(std::string &SourceLine,
// number of columns we have, try to grow the slice to encompass
// more context.
// If the end of the interesting region comes before we run out of
// space in the terminal, start at the beginning of the line.
if (Columns > 3 && CaretEnd < Columns - 3)
CaretStart = 0;
unsigned SourceStart = map.columnToByte(std::min<unsigned>(CaretStart,
map.columns()));
unsigned SourceEnd = map.columnToByte(std::min<unsigned>(CaretEnd,
map.columns()));
unsigned CaretColumnsOutsideSource = CaretEnd-CaretStart
- (map.byteToColumn(SourceEnd)-map.byteToColumn(SourceStart));
char const *front_ellipse = " ...";
char const *front_space = " ";
char const *back_ellipse = "...";
unsigned ellipses_space = strlen(front_ellipse) + strlen(back_ellipse);
unsigned TargetColumns = Columns;
if (TargetColumns > 8)
TargetColumns -= 8; // Give us extra room for the ellipses.
unsigned SourceLength = SourceLine.size();
while ((CaretEnd - CaretStart) < TargetColumns) {
// Give us extra room for the ellipses
// and any of the caret line that extends past the source
if (TargetColumns > ellipses_space+CaretColumnsOutsideSource)
TargetColumns -= ellipses_space+CaretColumnsOutsideSource;
while (SourceStart>0 || SourceEnd<SourceLine.size()) {
bool ExpandedRegion = false;
// Move the start of the interesting region left until we've
// pulled in something else interesting.
if (CaretStart == 1)
CaretStart = 0;
else if (CaretStart > 1) {
unsigned NewStart = CaretStart - 1;
if (SourceStart>0) {
unsigned NewStart = SourceStart-1;
// Skip over any whitespace we see here; we're looking for
// another bit of interesting text.
while (NewStart && isspace(SourceLine[NewStart]))
while (NewStart &&
(map.byteToColumn(NewStart)==-1 || isspace(SourceLine[NewStart])))
--NewStart;
// Skip over this bit of "interesting" text.
while (NewStart && !isspace(SourceLine[NewStart]))
while (NewStart &&
(map.byteToColumn(NewStart)!=-1 && !isspace(SourceLine[NewStart])))
--NewStart;
// Move up to the non-whitespace character we just saw.
if (NewStart)
++NewStart;
// If we're still within our limit, update the starting
// position within the source/caret line.
if (CaretEnd - NewStart <= TargetColumns) {
CaretStart = NewStart;
unsigned NewColumns = map.byteToColumn(SourceEnd) -
map.byteToColumn(NewStart);
if (NewColumns <= TargetColumns) {
SourceStart = NewStart;
ExpandedRegion = true;
}
}
// Move the end of the interesting region right until we've
// pulled in something else interesting.
if (CaretEnd != SourceLength) {
assert(CaretEnd < SourceLength && "Unexpected caret position!");
unsigned NewEnd = CaretEnd;
if (SourceEnd<SourceLine.size()) {
unsigned NewEnd = SourceEnd+1;
// Skip over any whitespace we see here; we're looking for
// another bit of interesting text.
while (NewEnd != SourceLength && isspace(SourceLine[NewEnd - 1]))
while (NewEnd<SourceLine.size() &&
(map.byteToColumn(NewEnd)==-1 || isspace(SourceLine[NewEnd])))
++NewEnd;
// Skip over this bit of "interesting" text.
while (NewEnd != SourceLength && !isspace(SourceLine[NewEnd - 1]))
while (NewEnd<SourceLine.size() &&
(map.byteToColumn(NewEnd)!=-1 && !isspace(SourceLine[NewEnd])))
++NewEnd;
if (NewEnd - CaretStart <= TargetColumns) {
CaretEnd = NewEnd;
unsigned NewColumns = map.byteToColumn(NewEnd) -
map.byteToColumn(SourceStart);
if (NewColumns <= TargetColumns) {
SourceEnd = NewEnd;
ExpandedRegion = true;
}
}
@ -156,21 +412,41 @@ static void selectInterestingSourceRegion(std::string &SourceLine,
break;
}
CaretStart = map.byteToColumn(SourceStart);
CaretEnd = map.byteToColumn(SourceEnd) + CaretColumnsOutsideSource;
// [CaretStart, CaretEnd) is the slice we want. Update the various
// output lines to show only this slice, with two-space padding
// before the lines so that it looks nicer.
if (CaretEnd < SourceLine.size())
SourceLine.replace(CaretEnd, std::string::npos, "...");
if (CaretEnd < CaretLine.size())
CaretLine.erase(CaretEnd, std::string::npos);
if (FixItInsertionLine.size() > CaretEnd)
FixItInsertionLine.erase(CaretEnd, std::string::npos);
if (CaretStart > 2) {
SourceLine.replace(0, CaretStart, " ...");
CaretLine.replace(0, CaretStart, " ");
if (FixItInsertionLine.size() >= CaretStart)
FixItInsertionLine.replace(0, CaretStart, " ");
assert(CaretStart!=(unsigned)-1 && CaretEnd!=(unsigned)-1 &&
SourceStart!=(unsigned)-1 && SourceEnd!=(unsigned)-1);
assert(SourceStart <= SourceEnd);
assert(CaretStart <= CaretEnd);
unsigned BackColumnsRemoved
= map.byteToColumn(SourceLine.size())-map.byteToColumn(SourceEnd);
unsigned FrontColumnsRemoved = CaretStart;
unsigned ColumnsKept = CaretEnd-CaretStart;
// We checked up front that the line needed truncation
assert(FrontColumnsRemoved+ColumnsKept+BackColumnsRemoved > Columns);
// The line needs some trunctiona, and we'd prefer to keep the front
// if possible, so remove the back
if (BackColumnsRemoved)
SourceLine.replace(SourceEnd, std::string::npos, back_ellipse);
// If that's enough then we're done
if (FrontColumnsRemoved+ColumnsKept <= Columns)
return;
// Otherwise remove the front as well
if (FrontColumnsRemoved) {
SourceLine.replace(0, SourceStart, front_ellipse);
CaretLine.replace(0, CaretStart, front_space);
if (!FixItInsertionLine.empty())
FixItInsertionLine.replace(0, CaretStart, front_space);
}
}
@ -564,10 +840,13 @@ void TextDiagnostic::emitSnippetAndCaret(
// Get information about the buffer it points into.
bool Invalid = false;
const char *BufStart = SM.getBufferData(FID, &Invalid).data();
StringRef BufData = SM.getBufferData(FID, &Invalid);
if (Invalid)
return;
const char *BufStart = BufData.data();
const char *BufEnd = BufStart + BufData.size();
unsigned LineNo = SM.getLineNumber(FID, FileOffset);
unsigned ColNo = SM.getColumnNumber(FID, FileOffset);
unsigned CaretEndColNo
@ -581,7 +860,7 @@ void TextDiagnostic::emitSnippetAndCaret(
// Compute the line end. Scan forward from the error position to the end of
// the line.
const char *LineEnd = TokPtr;
while (*LineEnd != '\n' && *LineEnd != '\r' && *LineEnd != '\0')
while (*LineEnd != '\n' && *LineEnd != '\r' && LineEnd!=BufEnd)
++LineEnd;
// FIXME: This shouldn't be necessary, but the CaretEndColNo can extend past
@ -596,19 +875,30 @@ void TextDiagnostic::emitSnippetAndCaret(
// length as the line of source code.
std::string CaretLine(LineEnd-LineStart, ' ');
const SourceColumnMap sourceColMap(SourceLine, DiagOpts.TabStop);
// Highlight all of the characters covered by Ranges with ~ characters.
for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(),
E = Ranges.end();
I != E; ++I)
highlightRange(*I, LineNo, FID, SourceLine, CaretLine);
highlightRange(*I, LineNo, FID, sourceColMap, CaretLine);
// Next, insert the caret itself.
if (ColNo-1 < CaretLine.size())
CaretLine[ColNo-1] = '^';
else
CaretLine.push_back('^');
ColNo = sourceColMap.byteToColumn(ColNo-1);
if (CaretLine.size()<ColNo+1)
CaretLine.resize(ColNo+1, ' ');
CaretLine[ColNo] = '^';
expandTabs(SourceLine, CaretLine);
std::string FixItInsertionLine = buildFixItInsertionLine(LineNo,
sourceColMap,
Hints);
// If the source line is too long for our terminal, select only the
// "interesting" source region within that line.
unsigned Columns = DiagOpts.MessageLength;
if (Columns)
selectInterestingSourceRegion(SourceLine, CaretLine, FixItInsertionLine,
Columns, sourceColMap);
// If we are in -fdiagnostics-print-source-range-info mode, we are trying
// to produce easily machine parsable output. Add a space before the
@ -619,23 +909,12 @@ void TextDiagnostic::emitSnippetAndCaret(
CaretLine = ' ' + CaretLine;
}
std::string FixItInsertionLine = buildFixItInsertionLine(LineNo,
LineStart, LineEnd,
Hints);
// If the source line is too long for our terminal, select only the
// "interesting" source region within that line.
unsigned Columns = DiagOpts.MessageLength;
if (Columns && SourceLine.size() > Columns)
selectInterestingSourceRegion(SourceLine, CaretLine, FixItInsertionLine,
CaretEndColNo, Columns);
// Finally, remove any blank spaces from the end of CaretLine.
while (CaretLine[CaretLine.size()-1] == ' ')
CaretLine.erase(CaretLine.end()-1);
// Emit what we have computed.
OS << SourceLine << '\n';
emitSnippet(SourceLine);
if (DiagOpts.ShowColors)
OS.changeColor(caretColor, true);
@ -658,13 +937,49 @@ void TextDiagnostic::emitSnippetAndCaret(
emitParseableFixits(Hints);
}
void TextDiagnostic::emitSnippet(StringRef line)
{
if (line.empty())
return;
size_t i = 0;
std::string to_print;
bool print_reversed = false;
while (i<line.size()) {
std::pair<SmallString<16>,bool> res
= printableTextForNextCharacter(line, &i, DiagOpts.TabStop);
bool was_printable = res.second;
if (DiagOpts.ShowColors
&& was_printable==print_reversed) {
if (print_reversed)
OS.reverseColor();
OS << to_print;
to_print.clear();
if (DiagOpts.ShowColors)
OS.resetColor();
}
print_reversed = !was_printable;
to_print += res.first.str();
}
if (print_reversed && DiagOpts.ShowColors)
OS.reverseColor();
OS << to_print;
if (print_reversed && DiagOpts.ShowColors)
OS.resetColor();
OS << '\n';
}
/// \brief Highlight a SourceRange (with ~'s) for any characters on LineNo.
void TextDiagnostic::highlightRange(const CharSourceRange &R,
unsigned LineNo, FileID FID,
const std::string &SourceLine,
const SourceColumnMap &map,
std::string &CaretLine) {
assert(CaretLine.size() == SourceLine.size() &&
"Expect a correspondence between source and caret line!");
if (!R.isValid()) return;
SourceLocation Begin = SM.getExpansionLoc(R.getBegin());
@ -694,7 +1009,7 @@ void TextDiagnostic::highlightRange(const CharSourceRange &R,
}
// Compute the column number of the end.
unsigned EndColNo = CaretLine.size();
unsigned EndColNo = map.getSourceLine().size();
if (EndLineNo == LineNo) {
EndColNo = SM.getExpansionColumnNumber(End);
if (EndColNo) {
@ -714,15 +1029,17 @@ void TextDiagnostic::highlightRange(const CharSourceRange &R,
// Check that a token range does not highlight only whitespace.
if (R.isTokenRange()) {
// Pick the first non-whitespace column.
while (StartColNo < SourceLine.size() &&
(SourceLine[StartColNo] == ' ' || SourceLine[StartColNo] == '\t'))
while (StartColNo < map.getSourceLine().size() &&
(map.getSourceLine()[StartColNo] == ' ' ||
map.getSourceLine()[StartColNo] == '\t'))
++StartColNo;
// Pick the last non-whitespace column.
if (EndColNo > SourceLine.size())
EndColNo = SourceLine.size();
if (EndColNo > map.getSourceLine().size())
EndColNo = map.getSourceLine().size();
while (EndColNo-1 &&
(SourceLine[EndColNo-1] == ' ' || SourceLine[EndColNo-1] == '\t'))
(map.getSourceLine()[EndColNo-1] == ' ' ||
map.getSourceLine()[EndColNo-1] == '\t'))
--EndColNo;
// If the start/end passed each other, then we are trying to highlight a
@ -731,15 +1048,24 @@ void TextDiagnostic::highlightRange(const CharSourceRange &R,
assert(StartColNo <= EndColNo && "Trying to highlight whitespace??");
}
assert(StartColNo <= map.getSourceLine().size() && "Invalid range!");
assert(EndColNo <= map.getSourceLine().size() && "Invalid range!");
// Fill the range with ~'s.
for (unsigned i = StartColNo; i < EndColNo; ++i)
CaretLine[i] = '~';
StartColNo = map.byteToColumn(StartColNo);
EndColNo = map.byteToColumn(EndColNo);
assert(StartColNo <= EndColNo && "Invalid range!");
if (CaretLine.size() < EndColNo)
CaretLine.resize(EndColNo,' ');
std::fill(CaretLine.begin()+StartColNo,CaretLine.begin()+EndColNo,'~');
}
std::string TextDiagnostic::buildFixItInsertionLine(unsigned LineNo,
const char *LineStart,
const char *LineEnd,
ArrayRef<FixItHint> Hints) {
std::string TextDiagnostic::buildFixItInsertionLine(
unsigned LineNo,
const SourceColumnMap &map,
ArrayRef<FixItHint> Hints) {
std::string FixItInsertionLine;
if (Hints.empty() || !DiagOpts.ShowFixits)
return FixItInsertionLine;
@ -755,13 +1081,32 @@ std::string TextDiagnostic::buildFixItInsertionLine(unsigned LineNo,
// Insert the new code into the line just below the code
// that the user wrote.
unsigned HintColNo
= SM.getColumnNumber(HintLocInfo.first, HintLocInfo.second);
= SM.getColumnNumber(HintLocInfo.first, HintLocInfo.second) - 1;
// hint must start inside the source or right at the end
assert(HintColNo<static_cast<unsigned>(map.bytes())+1);
HintColNo = map.byteToColumn(HintColNo);
// FIXME: if the fixit includes tabs or other characters that do not
// take up a single column per byte when displayed then
// I->CodeToInsert.size() is not a column number and we're mixing
// units (columns + bytes). We should get printable versions
// of each fixit before using them.
unsigned LastColumnModified
= HintColNo - 1 + I->CodeToInsert.size();
= HintColNo + I->CodeToInsert.size();
if (LastColumnModified > static_cast<unsigned>(map.bytes())) {
unsigned LastExistingColumn = map.byteToColumn(map.bytes());
unsigned AddedColumns = LastColumnModified-LastExistingColumn;
LastColumnModified = LastExistingColumn + AddedColumns;
} else {
LastColumnModified = map.byteToColumn(LastColumnModified);
}
if (LastColumnModified > FixItInsertionLine.size())
FixItInsertionLine.resize(LastColumnModified, ' ');
assert(HintColNo+I->CodeToInsert.size() <= FixItInsertionLine.size());
std::copy(I->CodeToInsert.begin(), I->CodeToInsert.end(),
FixItInsertionLine.begin() + HintColNo - 1);
FixItInsertionLine.begin() + HintColNo);
} else {
FixItInsertionLine.clear();
break;
@ -769,72 +1114,11 @@ std::string TextDiagnostic::buildFixItInsertionLine(unsigned LineNo,
}
}
if (FixItInsertionLine.empty())
return FixItInsertionLine;
// Now that we have the entire fixit line, expand the tabs in it.
// Since we don't want to insert spaces in the middle of a word,
// find each word and the column it should line up with and insert
// spaces until they match.
unsigned FixItPos = 0;
unsigned LinePos = 0;
unsigned TabExpandedCol = 0;
unsigned LineLength = LineEnd - LineStart;
while (FixItPos < FixItInsertionLine.size() && LinePos < LineLength) {
// Find the next word in the FixIt line.
while (FixItPos < FixItInsertionLine.size() &&
FixItInsertionLine[FixItPos] == ' ')
++FixItPos;
unsigned CharDistance = FixItPos - TabExpandedCol;
// Walk forward in the source line, keeping track of
// the tab-expanded column.
for (unsigned I = 0; I < CharDistance; ++I, ++LinePos)
if (LinePos >= LineLength || LineStart[LinePos] != '\t')
++TabExpandedCol;
else
TabExpandedCol =
(TabExpandedCol/DiagOpts.TabStop + 1) * DiagOpts.TabStop;
// Adjust the fixit line to match this column.
FixItInsertionLine.insert(FixItPos, TabExpandedCol-FixItPos, ' ');
FixItPos = TabExpandedCol;
// Walk to the end of the word.
while (FixItPos < FixItInsertionLine.size() &&
FixItInsertionLine[FixItPos] != ' ')
++FixItPos;
}
expandTabs(FixItInsertionLine, DiagOpts.TabStop);
return FixItInsertionLine;
}
void TextDiagnostic::expandTabs(std::string &SourceLine,
std::string &CaretLine) {
// Scan the source line, looking for tabs. If we find any, manually expand
// them to spaces and update the CaretLine to match.
for (unsigned i = 0; i != SourceLine.size(); ++i) {
if (SourceLine[i] != '\t') continue;
// Replace this tab with at least one space.
SourceLine[i] = ' ';
// Compute the number of spaces we need to insert.
unsigned TabStop = DiagOpts.TabStop;
assert(0 < TabStop && TabStop <= DiagnosticOptions::MaxTabStop &&
"Invalid -ftabstop value");
unsigned NumSpaces = ((i+TabStop)/TabStop * TabStop) - (i+1);
assert(NumSpaces < TabStop && "Invalid computation of space amt");
// Insert spaces into the SourceLine.
SourceLine.insert(i+1, NumSpaces, ' ');
// Insert spaces or ~'s into CaretLine.
CaretLine.insert(i+1, NumSpaces, CaretLine[i] == '~' ? '~' : ' ');
}
}
void TextDiagnostic::emitParseableFixits(ArrayRef<FixItHint> Hints) {
if (!DiagOpts.ShowParseableFixits)
return;
@ -878,4 +1162,3 @@ void TextDiagnostic::emitParseableFixits(ArrayRef<FixItHint> Hints) {
OS << "\"\n";
}
}

View File

@ -72,7 +72,6 @@ static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
case PrintDeclContext: return new DeclContextPrintAction();
case PrintPreamble: return new PrintPreambleAction();
case PrintPreprocessedInput: return new PrintPreprocessedAction();
case PubnamesDump: return new PubnamesDumpAction();
case RewriteMacros: return new RewriteMacrosAction();
case RewriteObjC: return new RewriteObjCAction();
case RewriteTest: return new RewriteTestAction();

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