Update clang to r84949.
This commit is contained in:
parent
a5f348eb91
commit
73490b8909
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor/clang/dist/; revision=198398 svn path=/vendor/clang/clang-r84949/; revision=198399; tag=vendor/clang/clang-r84949
@ -99,18 +99,84 @@ typedef struct {
|
||||
} CXCursor;
|
||||
|
||||
/* A unique token for looking up "visible" CXDecls from a CXTranslationUnit. */
|
||||
typedef void *CXEntity;
|
||||
typedef void *CXEntity;
|
||||
|
||||
CXIndex clang_createIndex();
|
||||
/**
|
||||
* \brief clang_createIndex() provides a shared context for creating
|
||||
* translation units. It provides two options:
|
||||
*
|
||||
* - excludeDeclarationsFromPCH: When non-zero, allows enumeration of "local"
|
||||
* declarations (when loading any new translation units). A "local" declaration
|
||||
* is one that belongs in the translation unit itself and not in a precompiled
|
||||
* header that was used by the translation unit. If zero, all declarations
|
||||
* will be enumerated.
|
||||
*
|
||||
* - displayDiagnostics: when non-zero, diagnostics will be output. If zero,
|
||||
* diagnostics will be ignored.
|
||||
*
|
||||
* Here is an example:
|
||||
*
|
||||
* // excludeDeclsFromPCH = 1, displayDiagnostics = 1
|
||||
* Idx = clang_createIndex(1, 1);
|
||||
*
|
||||
* // IndexTest.pch was produced with the following command:
|
||||
* // "clang -x c IndexTest.h -emit-ast -o IndexTest.pch"
|
||||
* TU = clang_createTranslationUnit(Idx, "IndexTest.pch");
|
||||
*
|
||||
* // This will load all the symbols from 'IndexTest.pch'
|
||||
* clang_loadTranslationUnit(TU, TranslationUnitVisitor, 0);
|
||||
* clang_disposeTranslationUnit(TU);
|
||||
*
|
||||
* // This will load all the symbols from 'IndexTest.c', excluding symbols
|
||||
* // from 'IndexTest.pch'.
|
||||
* char *args[] = { "-Xclang", "-include-pch=IndexTest.pch", 0 };
|
||||
* TU = clang_createTranslationUnitFromSourceFile(Idx, "IndexTest.c", 2, args);
|
||||
* clang_loadTranslationUnit(TU, TranslationUnitVisitor, 0);
|
||||
* clang_disposeTranslationUnit(TU);
|
||||
*
|
||||
* This process of creating the 'pch', loading it separately, and using it (via
|
||||
* -include-pch) allows 'excludeDeclsFromPCH' to remove redundant callbacks
|
||||
* (which gives the indexer the same performance benefit as the compiler).
|
||||
*/
|
||||
CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
|
||||
int displayDiagnostics);
|
||||
void clang_disposeIndex(CXIndex);
|
||||
|
||||
const char *clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit);
|
||||
|
||||
/*
|
||||
* \brief Create a translation unit from an AST file (-emit-ast).
|
||||
*/
|
||||
CXTranslationUnit clang_createTranslationUnit(
|
||||
CXIndex, const char *ast_filename
|
||||
);
|
||||
/**
|
||||
* \brief Destroy the specified CXTranslationUnit object.
|
||||
*/
|
||||
void clang_disposeTranslationUnit(CXTranslationUnit);
|
||||
|
||||
/**
|
||||
* \brief Return the CXTranslationUnit for a given source file and the provided
|
||||
* command line arguments one would pass to the compiler.
|
||||
*
|
||||
* Note: The 'source_filename' argument is optional. If the caller provides a NULL pointer,
|
||||
* the name of the source file is expected to reside in the specified command line arguments.
|
||||
*
|
||||
* Note: When encountered in 'clang_command_line_args', the following options are ignored:
|
||||
*
|
||||
* '-c'
|
||||
* '-emit-ast'
|
||||
* '-fsyntax-only'
|
||||
* '-o <output file>' (both '-o' and '<output file>' are ignored)
|
||||
*
|
||||
*/
|
||||
CXTranslationUnit clang_createTranslationUnitFromSourceFile(
|
||||
CXIndex CIdx,
|
||||
const char *source_filename /* specify NULL if the source file is in clang_command_line_args */,
|
||||
int num_clang_command_line_args,
|
||||
const char **clang_command_line_args
|
||||
);
|
||||
|
||||
/*
|
||||
Usage: clang_loadTranslationUnit(). Will load the toplevel declarations
|
||||
within a translation unit, issuing a 'callback' for each one.
|
||||
@ -182,9 +248,28 @@ const char *clang_getDeclSource(CXDecl);
|
||||
/*
|
||||
* CXCursor Operations.
|
||||
*/
|
||||
/**
|
||||
Usage: clang_getCursor() will translate a source/line/column position
|
||||
into an AST cursor (to derive semantic information from the source code).
|
||||
*/
|
||||
CXCursor clang_getCursor(CXTranslationUnit, const char *source_name,
|
||||
unsigned line, unsigned column);
|
||||
|
||||
/**
|
||||
Usage: clang_getCursorWithHint() provides the same functionality as
|
||||
clang_getCursor() except that it takes an option 'hint' argument.
|
||||
The 'hint' is a temporary CXLookupHint object (whose lifetime is managed by
|
||||
the caller) that should be initialized with clang_initCXLookupHint().
|
||||
|
||||
FIXME: Add a better comment once getCursorWithHint() has more functionality.
|
||||
*/
|
||||
typedef CXCursor CXLookupHint;
|
||||
CXCursor clang_getCursorWithHint(CXTranslationUnit, const char *source_name,
|
||||
unsigned line, unsigned column,
|
||||
CXLookupHint *hint);
|
||||
|
||||
void clang_initCXLookupHint(CXLookupHint *hint);
|
||||
|
||||
enum CXCursorKind clang_getCursorKind(CXCursor);
|
||||
unsigned clang_isDeclaration(enum CXCursorKind);
|
||||
unsigned clang_isReference(enum CXCursorKind);
|
||||
|
@ -81,12 +81,12 @@ class ASTContext {
|
||||
llvm::FoldingSet<DependentTypeOfExprType> DependentTypeOfExprTypes;
|
||||
llvm::FoldingSet<DependentDecltypeType> DependentDecltypeTypes;
|
||||
llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes;
|
||||
llvm::FoldingSet<SubstTemplateTypeParmType> SubstTemplateTypeParmTypes;
|
||||
llvm::FoldingSet<TemplateSpecializationType> TemplateSpecializationTypes;
|
||||
llvm::FoldingSet<QualifiedNameType> QualifiedNameTypes;
|
||||
llvm::FoldingSet<TypenameType> TypenameTypes;
|
||||
llvm::FoldingSet<ObjCInterfaceType> ObjCInterfaceTypes;
|
||||
llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
|
||||
llvm::FoldingSet<ObjCProtocolListType> ObjCProtocolListTypes;
|
||||
llvm::FoldingSet<ElaboratedType> ElaboratedTypes;
|
||||
|
||||
llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
|
||||
@ -143,6 +143,12 @@ class ASTContext {
|
||||
/// \brief The type for the C sigjmp_buf type.
|
||||
TypeDecl *sigjmp_bufDecl;
|
||||
|
||||
/// \brief Type for the Block descriptor for Blocks CodeGen.
|
||||
RecordDecl *BlockDescriptorType;
|
||||
|
||||
/// \brief Type for the Block descriptor for Blocks CodeGen.
|
||||
RecordDecl *BlockDescriptorExtendedType;
|
||||
|
||||
/// \brief Keeps track of all declaration attributes.
|
||||
///
|
||||
/// Since so few decls have attrs, we keep them in a hash map instead of
|
||||
@ -390,9 +396,47 @@ class ASTContext {
|
||||
/// of the specified type.
|
||||
QualType getBlockPointerType(QualType T);
|
||||
|
||||
/// This gets the struct used to keep track of the descriptor for pointer to
|
||||
/// blocks.
|
||||
QualType getBlockDescriptorType();
|
||||
|
||||
// Set the type for a Block descriptor type.
|
||||
void setBlockDescriptorType(QualType T);
|
||||
/// Get the BlockDescriptorType type, or NULL if it hasn't yet been built.
|
||||
QualType getRawBlockdescriptorType() {
|
||||
if (BlockDescriptorType)
|
||||
return getTagDeclType(BlockDescriptorType);
|
||||
return QualType();
|
||||
}
|
||||
|
||||
/// This gets the struct used to keep track of the extended descriptor for
|
||||
/// pointer to blocks.
|
||||
QualType getBlockDescriptorExtendedType();
|
||||
|
||||
// Set the type for a Block descriptor extended type.
|
||||
void setBlockDescriptorExtendedType(QualType T);
|
||||
/// Get the BlockDescriptorExtendedType type, or NULL if it hasn't yet been
|
||||
/// built.
|
||||
QualType getRawBlockdescriptorExtendedType() {
|
||||
if (BlockDescriptorExtendedType)
|
||||
return getTagDeclType(BlockDescriptorExtendedType);
|
||||
return QualType();
|
||||
}
|
||||
|
||||
/// This gets the struct used to keep track of pointer to blocks, complete
|
||||
/// with captured variables.
|
||||
QualType getBlockParmType(bool BlockHasCopyDispose,
|
||||
llvm::SmallVector<const Expr *, 8> &BDRDs);
|
||||
|
||||
/// This builds the struct used for __block variables.
|
||||
QualType BuildByRefType(const char *DeclName, QualType Ty);
|
||||
|
||||
/// Returns true iff we need copy/dispose helpers for the given type.
|
||||
bool BlockRequiresCopying(QualType Ty);
|
||||
|
||||
/// getLValueReferenceType - Return the uniqued reference to the type for an
|
||||
/// lvalue reference to the specified type.
|
||||
QualType getLValueReferenceType(QualType T);
|
||||
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue = true);
|
||||
|
||||
/// getRValueReferenceType - Return the uniqued reference to the type for an
|
||||
/// rvalue reference to the specified type.
|
||||
@ -431,22 +475,6 @@ class ASTContext {
|
||||
ArrayType::ArraySizeModifier ASM,
|
||||
unsigned EltTypeQuals);
|
||||
|
||||
/// getConstantArrayWithExprType - Return a reference to the type for a
|
||||
/// constant array of the specified element type.
|
||||
QualType getConstantArrayWithExprType(QualType EltTy,
|
||||
const llvm::APInt &ArySize,
|
||||
Expr *ArySizeExpr,
|
||||
ArrayType::ArraySizeModifier ASM,
|
||||
unsigned EltTypeQuals,
|
||||
SourceRange Brackets);
|
||||
|
||||
/// getConstantArrayWithoutExprType - Return a reference to the type
|
||||
/// for a constant array of the specified element type.
|
||||
QualType getConstantArrayWithoutExprType(QualType EltTy,
|
||||
const llvm::APInt &ArySize,
|
||||
ArrayType::ArraySizeModifier ASM,
|
||||
unsigned EltTypeQuals);
|
||||
|
||||
/// getVectorType - Return the unique reference to a vector type of
|
||||
/// the specified element type and size. VectorType must be a built-in type.
|
||||
QualType getVectorType(QualType VectorType, unsigned NumElts);
|
||||
@ -485,6 +513,9 @@ class ASTContext {
|
||||
/// specified typename decl.
|
||||
QualType getTypedefType(TypedefDecl *Decl);
|
||||
|
||||
QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced,
|
||||
QualType Replacement);
|
||||
|
||||
QualType getTemplateTypeParmType(unsigned Depth, unsigned Index,
|
||||
bool ParameterPack,
|
||||
IdentifierInfo *Name = 0);
|
||||
@ -515,10 +546,6 @@ class ASTContext {
|
||||
ObjCProtocolDecl **ProtocolList = 0,
|
||||
unsigned NumProtocols = 0);
|
||||
|
||||
QualType getObjCProtocolListType(QualType T,
|
||||
ObjCProtocolDecl **Protocols,
|
||||
unsigned NumProtocols);
|
||||
|
||||
/// getTypeOfType - GCC extension.
|
||||
QualType getTypeOfExprType(Expr *e);
|
||||
QualType getTypeOfType(QualType t);
|
||||
@ -815,6 +842,12 @@ class ASTContext {
|
||||
return T->getCanonicalTypeInternal().getTypePtr();
|
||||
}
|
||||
|
||||
/// getCanonicalParamType - Return the canonical parameter type
|
||||
/// corresponding to the specific potentially non-canonical one.
|
||||
/// Qualifiers are stripped off, functions are turned into function
|
||||
/// pointers, and arrays decay one level into pointers.
|
||||
CanQualType getCanonicalParamType(QualType T);
|
||||
|
||||
/// \brief Determine whether the given types are equivalent.
|
||||
bool hasSameType(QualType T1, QualType T2) {
|
||||
return getCanonicalType(T1) == getCanonicalType(T2);
|
||||
@ -1047,7 +1080,10 @@ class ASTContext {
|
||||
/// \param T the type that will be the basis for type source info. This type
|
||||
/// should refer to how the declarator was written in source code, not to
|
||||
/// what type semantic analysis resolved the declarator to.
|
||||
DeclaratorInfo *CreateDeclaratorInfo(QualType T);
|
||||
///
|
||||
/// \param Size the size of the type info to create, or 0 if the size
|
||||
/// should be calculated based on the type.
|
||||
DeclaratorInfo *CreateDeclaratorInfo(QualType T, unsigned Size = 0);
|
||||
|
||||
private:
|
||||
ASTContext(const ASTContext&); // DO NOT IMPLEMENT
|
||||
|
@ -185,7 +185,6 @@ class AlignedAttr : public Attr {
|
||||
public:
|
||||
AlignedAttr(unsigned alignment) : Attr(Aligned), Alignment(alignment) {}
|
||||
|
||||
// FIXME: Should use addressable units, not bits, to match llvm
|
||||
/// getAlignment - The specified alignment in bits.
|
||||
unsigned getAlignment() const { return Alignment; }
|
||||
|
||||
|
@ -63,7 +63,8 @@ struct CXXBasePathElement {
|
||||
/// structure, which captures both the link from a derived class to one of its
|
||||
/// direct bases and identification describing which base class
|
||||
/// subobject is being used.
|
||||
struct CXXBasePath : public llvm::SmallVector<CXXBasePathElement, 4> {
|
||||
class CXXBasePath : public llvm::SmallVector<CXXBasePathElement, 4> {
|
||||
public:
|
||||
/// \brief The set of declarations found inside this base class
|
||||
/// subobject.
|
||||
DeclContext::lookup_result Decls;
|
||||
|
@ -486,30 +486,6 @@ struct CanProxyAdaptor<ConstantArrayType>
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<ConstantArrayWithExprType>
|
||||
: public CanProxyBase<ConstantArrayWithExprType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
|
||||
getSizeModifier)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getSizeExpr)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceRange, getBracketsRange)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getLBracketLoc)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getRBracketLoc)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<ConstantArrayWithoutExprType>
|
||||
: public CanProxyBase<ConstantArrayWithoutExprType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
|
||||
getSizeModifier)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<IncompleteArrayType>
|
||||
: public CanProxyBase<IncompleteArrayType> {
|
||||
@ -684,7 +660,7 @@ CanQual<T> CanQual<T>::getFromOpaquePtr(void *Ptr) {
|
||||
|
||||
template<typename T>
|
||||
CanQual<T> CanQual<T>::CreateUnsafe(QualType Other) {
|
||||
assert((Other.isNull() || Other->isCanonical()) && "Type is not canonical!");
|
||||
assert((Other.isNull() || Other.isCanonical()) && "Type is not canonical!");
|
||||
assert((Other.isNull() || isa<T>(Other.getTypePtr())) &&
|
||||
"Dynamic type does not meet the static type's requires");
|
||||
CanQual<T> Result;
|
||||
|
@ -47,6 +47,9 @@ class DeclaratorInfo {
|
||||
friend class ASTContext;
|
||||
DeclaratorInfo(QualType ty) : Ty(ty) { }
|
||||
public:
|
||||
/// \brief Return the type wrapped by this type source info.
|
||||
QualType getType() const { return Ty; }
|
||||
|
||||
/// \brief Return the TypeLoc wrapper for the type source info.
|
||||
TypeLoc getTypeLoc() const;
|
||||
};
|
||||
@ -93,14 +96,36 @@ class NamedDecl : public Decl {
|
||||
/// name (C++ constructor, Objective-C selector, etc.).
|
||||
IdentifierInfo *getIdentifier() const { return Name.getAsIdentifierInfo(); }
|
||||
|
||||
/// getName - Get the name of identifier for this declaration as a StringRef.
|
||||
/// This requires that the declaration have a name and that it be a simple
|
||||
/// identifier.
|
||||
llvm::StringRef getName() const {
|
||||
assert(Name.isIdentifier() && "Name is not a simple identifier");
|
||||
return getIdentifier() ? getIdentifier()->getName() : "";
|
||||
}
|
||||
|
||||
/// getNameAsCString - Get the name of identifier for this declaration as a
|
||||
/// C string (const char*). This requires that the declaration have a name
|
||||
/// and that it be a simple identifier.
|
||||
//
|
||||
// FIXME: Deprecated, move clients to getName().
|
||||
const char *getNameAsCString() const {
|
||||
assert(getIdentifier() && "Name is not a simple identifier");
|
||||
return getIdentifier()->getName();
|
||||
assert(Name.isIdentifier() && "Name is not a simple identifier");
|
||||
return getIdentifier() ? getIdentifier()->getNameStart() : "";
|
||||
}
|
||||
|
||||
/// getNameAsString - Get a human-readable name for the declaration, even if
|
||||
/// it is one of the special kinds of names (C++ constructor, Objective-C
|
||||
/// selector, etc). Creating this name requires expensive string
|
||||
/// manipulation, so it should be called only when performance doesn't matter.
|
||||
/// For simple declarations, getNameAsCString() should suffice.
|
||||
//
|
||||
// FIXME: This function should be renamed to indicate that it is not just an
|
||||
// alternate form of getName(), and clients should move as appropriate.
|
||||
//
|
||||
// FIXME: Deprecated, move clients to getName().
|
||||
std::string getNameAsString() const { return Name.getAsString(); }
|
||||
|
||||
/// getDeclName - Get the actual, stored name of the declaration,
|
||||
/// which may be a special name.
|
||||
DeclarationName getDeclName() const { return Name; }
|
||||
@ -108,13 +133,6 @@ class NamedDecl : public Decl {
|
||||
/// \brief Set the name of this declaration.
|
||||
void setDeclName(DeclarationName N) { Name = N; }
|
||||
|
||||
/// getNameAsString - Get a human-readable name for the declaration, even if
|
||||
/// it is one of the special kinds of names (C++ constructor, Objective-C
|
||||
/// selector, etc). Creating this name requires expensive string
|
||||
/// manipulation, so it should be called only when performance doesn't matter.
|
||||
/// For simple declarations, getNameAsCString() should suffice.
|
||||
std::string getNameAsString() const { return Name.getAsString(); }
|
||||
|
||||
/// getQualifiedNameAsString - Returns human-readable qualified name for
|
||||
/// declaration, like A::B::i, for i being member of namespace A::B.
|
||||
/// If declaration is not member of context which can be named (record,
|
||||
@ -604,7 +622,8 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
|
||||
|
||||
/// \brief For a static data member that was instantiated from a static
|
||||
/// data member of a class template, set the template specialiation kind.
|
||||
void setTemplateSpecializationKind(TemplateSpecializationKind TSK);
|
||||
void setTemplateSpecializationKind(TemplateSpecializationKind TSK,
|
||||
SourceLocation PointOfInstantiation = SourceLocation());
|
||||
|
||||
/// isFileVarDecl - Returns true for file scoped variable declaration.
|
||||
bool isFileVarDecl() const {
|
||||
@ -1170,7 +1189,16 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
|
||||
|
||||
/// \brief Determine what kind of template instantiation this function
|
||||
/// represents.
|
||||
void setTemplateSpecializationKind(TemplateSpecializationKind TSK);
|
||||
void setTemplateSpecializationKind(TemplateSpecializationKind TSK,
|
||||
SourceLocation PointOfInstantiation = SourceLocation());
|
||||
|
||||
/// \brief Retrieve the (first) point of instantiation of a function template
|
||||
/// specialization or a member of a class template specialization.
|
||||
///
|
||||
/// \returns the first point of instantiation, if this function was
|
||||
/// instantiated from a template; otherwie, returns an invalid source
|
||||
/// location.
|
||||
SourceLocation getPointOfInstantiation() const;
|
||||
|
||||
/// \brief Determine whether this is or was instantiated from an out-of-line
|
||||
/// definition of a member function.
|
||||
|
@ -166,6 +166,15 @@ class Decl {
|
||||
bool Used : 1;
|
||||
|
||||
protected:
|
||||
/// Access - Used by C++ decls for the access specifier.
|
||||
// NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum
|
||||
unsigned Access : 2;
|
||||
friend class CXXClassMemberWrapper;
|
||||
|
||||
// PCHLevel - the "level" of precompiled header/AST file from which this
|
||||
// declaration was built.
|
||||
unsigned PCHLevel : 2;
|
||||
|
||||
/// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
|
||||
unsigned IdentifierNamespace : 16;
|
||||
|
||||
@ -177,16 +186,13 @@ class Decl {
|
||||
#endif
|
||||
|
||||
protected:
|
||||
/// Access - Used by C++ decls for the access specifier.
|
||||
// NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum
|
||||
unsigned Access : 2;
|
||||
friend class CXXClassMemberWrapper;
|
||||
|
||||
Decl(Kind DK, DeclContext *DC, SourceLocation L)
|
||||
: NextDeclInContext(0), DeclCtx(DC),
|
||||
Loc(L), DeclKind(DK), InvalidDecl(0),
|
||||
HasAttrs(false), Implicit(false), Used(false),
|
||||
IdentifierNamespace(getIdentifierNamespaceForKind(DK)), Access(AS_none) {
|
||||
Access(AS_none), PCHLevel(0),
|
||||
IdentifierNamespace(getIdentifierNamespaceForKind(DK)) {
|
||||
if (Decl::CollectingStats()) addDeclKind(DK);
|
||||
}
|
||||
|
||||
@ -274,6 +280,26 @@ class Decl {
|
||||
bool isUsed() const { return Used; }
|
||||
void setUsed(bool U = true) { Used = U; }
|
||||
|
||||
/// \brief Retrieve the level of precompiled header from which this
|
||||
/// declaration was generated.
|
||||
///
|
||||
/// The PCH level of a declaration describes where the declaration originated
|
||||
/// from. A PCH level of 0 indicates that the declaration was not from a
|
||||
/// precompiled header. A PCH level of 1 indicates that the declaration was
|
||||
/// from a top-level precompiled header; 2 indicates that the declaration
|
||||
/// comes from a precompiled header on which the top-level precompiled header
|
||||
/// depends, and so on.
|
||||
unsigned getPCHLevel() const { return PCHLevel; }
|
||||
|
||||
/// \brief The maximum PCH level that any declaration may have.
|
||||
static const unsigned MaxPCHLevel = 3;
|
||||
|
||||
/// \brief Set the PCH level of this declaration.
|
||||
void setPCHLevel(unsigned Level) {
|
||||
assert(Level < MaxPCHLevel && "PCH level exceeds the maximum");
|
||||
PCHLevel = Level;
|
||||
}
|
||||
|
||||
unsigned getIdentifierNamespace() const {
|
||||
return IdentifierNamespace;
|
||||
}
|
||||
|
@ -944,16 +944,29 @@ class ObjCCategoryImplDecl : public ObjCImplDecl {
|
||||
|
||||
ObjCCategoryDecl *getCategoryClass() const;
|
||||
|
||||
/// getName - Get the name of identifier for the class interface associated
|
||||
/// with this implementation as a StringRef.
|
||||
//
|
||||
// FIXME: This is a bad API, we are overriding the NamedDecl::getName, to mean
|
||||
// something different.
|
||||
llvm::StringRef getName() const {
|
||||
return Id ? Id->getNameStart() : "";
|
||||
}
|
||||
|
||||
/// getNameAsCString - Get the name of identifier for the class
|
||||
/// interface associated with this implementation as a C string
|
||||
/// (const char*).
|
||||
//
|
||||
// FIXME: Deprecated, move clients to getName().
|
||||
const char *getNameAsCString() const {
|
||||
return Id ? Id->getName() : "";
|
||||
return Id ? Id->getNameStart() : "";
|
||||
}
|
||||
|
||||
/// @brief Get the name of the class associated with this interface.
|
||||
//
|
||||
// FIXME: Deprecated, move clients to getName().
|
||||
std::string getNameAsString() const {
|
||||
return Id ? Id->getName() : "";
|
||||
return getName();
|
||||
}
|
||||
|
||||
static bool classof(const Decl *D) { return D->getKind() == ObjCCategoryImpl;}
|
||||
@ -995,17 +1008,30 @@ class ObjCImplementationDecl : public ObjCImplDecl {
|
||||
return getClassInterface()->getIdentifier();
|
||||
}
|
||||
|
||||
/// getNameAsCString - Get the name of identifier for the class
|
||||
/// interface associated with this implementation as a C string
|
||||
/// (const char*).
|
||||
const char *getNameAsCString() const {
|
||||
/// getName - Get the name of identifier for the class interface associated
|
||||
/// with this implementation as a StringRef.
|
||||
//
|
||||
// FIXME: This is a bad API, we are overriding the NamedDecl::getName, to mean
|
||||
// something different.
|
||||
llvm::StringRef getName() const {
|
||||
assert(getIdentifier() && "Name is not a simple identifier");
|
||||
return getIdentifier()->getName();
|
||||
}
|
||||
|
||||
/// getNameAsCString - Get the name of identifier for the class
|
||||
/// interface associated with this implementation as a C string
|
||||
/// (const char*).
|
||||
//
|
||||
// FIXME: Move to StringRef API.
|
||||
const char *getNameAsCString() const {
|
||||
return getName().data();
|
||||
}
|
||||
|
||||
/// @brief Get the name of the class associated with this interface.
|
||||
//
|
||||
// FIXME: Move to StringRef API.
|
||||
std::string getNameAsString() const {
|
||||
return getClassInterface()->getNameAsString();
|
||||
return getName();
|
||||
}
|
||||
|
||||
const ObjCInterfaceDecl *getSuperClass() const { return SuperClass; }
|
||||
|
@ -1399,7 +1399,27 @@ class CastExpr : public Expr {
|
||||
CK_IntegralToPointer,
|
||||
|
||||
/// CK_PointerToIntegral - Pointer to integral
|
||||
CK_PointerToIntegral
|
||||
CK_PointerToIntegral,
|
||||
|
||||
/// CK_ToVoid - Cast to void.
|
||||
CK_ToVoid,
|
||||
|
||||
/// CK_VectorSplat - Casting from an integer/floating type to an extended
|
||||
/// vector type with the same element type as the src type. Splats the
|
||||
/// src expression into the destination expression.
|
||||
CK_VectorSplat,
|
||||
|
||||
/// CK_IntegralCast - Casting between integral types of different size.
|
||||
CK_IntegralCast,
|
||||
|
||||
/// CK_IntegralToFloating - Integral to floating point.
|
||||
CK_IntegralToFloating,
|
||||
|
||||
/// CK_FloatingToIntegral - Floating point to integral.
|
||||
CK_FloatingToIntegral,
|
||||
|
||||
/// CK_FloatingCast - Casting between floating types of different size.
|
||||
CK_FloatingCast
|
||||
};
|
||||
|
||||
private:
|
||||
@ -1665,7 +1685,8 @@ class BinaryOperator : public Expr {
|
||||
/// predicates to categorize the respective opcodes.
|
||||
bool isMultiplicativeOp() const { return Opc >= Mul && Opc <= Rem; }
|
||||
bool isAdditiveOp() const { return Opc == Add || Opc == Sub; }
|
||||
bool isShiftOp() const { return Opc == Shl || Opc == Shr; }
|
||||
static bool isShiftOp(Opcode Opc) { return Opc == Shl || Opc == Shr; }
|
||||
bool isShiftOp() const { return isShiftOp(Opc); }
|
||||
bool isBitwiseOp() const { return Opc >= And && Opc <= Or; }
|
||||
|
||||
static bool isRelationalOp(Opcode Opc) { return Opc >= LT && Opc <= GE; }
|
||||
|
@ -443,6 +443,9 @@ class QualType {
|
||||
return getTypePtr();
|
||||
}
|
||||
|
||||
bool isCanonical() const;
|
||||
bool isCanonicalAsParam() const;
|
||||
|
||||
/// isNull - Return true if this QualType doesn't point to a type yet.
|
||||
bool isNull() const {
|
||||
return Value.getPointer().isNull();
|
||||
@ -702,7 +705,9 @@ class Type {
|
||||
public:
|
||||
TypeClass getTypeClass() const { return static_cast<TypeClass>(TC); }
|
||||
|
||||
bool isCanonical() const { return CanonicalType.getTypePtr() == this; }
|
||||
bool isCanonicalUnqualified() const {
|
||||
return CanonicalType.getTypePtr() == this;
|
||||
}
|
||||
|
||||
/// Types are partitioned into 3 broad categories (C99 6.2.5p1):
|
||||
/// object types, function types, and incomplete types.
|
||||
@ -1089,19 +1094,50 @@ class BlockPointerType : public Type, public llvm::FoldingSetNode {
|
||||
class ReferenceType : public Type, public llvm::FoldingSetNode {
|
||||
QualType PointeeType;
|
||||
|
||||
/// True if the type was originally spelled with an lvalue sigil.
|
||||
/// This is never true of rvalue references but can also be false
|
||||
/// on lvalue references because of C++0x [dcl.typedef]p9,
|
||||
/// as follows:
|
||||
///
|
||||
/// typedef int &ref; // lvalue, spelled lvalue
|
||||
/// typedef int &&rvref; // rvalue
|
||||
/// ref &a; // lvalue, inner ref, spelled lvalue
|
||||
/// ref &&a; // lvalue, inner ref
|
||||
/// rvref &a; // lvalue, inner ref, spelled lvalue
|
||||
/// rvref &&a; // rvalue, inner ref
|
||||
bool SpelledAsLValue;
|
||||
|
||||
/// True if the inner type is a reference type. This only happens
|
||||
/// in non-canonical forms.
|
||||
bool InnerRef;
|
||||
|
||||
protected:
|
||||
ReferenceType(TypeClass tc, QualType Referencee, QualType CanonicalRef) :
|
||||
ReferenceType(TypeClass tc, QualType Referencee, QualType CanonicalRef,
|
||||
bool SpelledAsLValue) :
|
||||
Type(tc, CanonicalRef, Referencee->isDependentType()),
|
||||
PointeeType(Referencee) {
|
||||
PointeeType(Referencee), SpelledAsLValue(SpelledAsLValue),
|
||||
InnerRef(Referencee->isReferenceType()) {
|
||||
}
|
||||
public:
|
||||
QualType getPointeeType() const { return PointeeType; }
|
||||
bool isSpelledAsLValue() const { return SpelledAsLValue; }
|
||||
|
||||
QualType getPointeeTypeAsWritten() const { return PointeeType; }
|
||||
QualType getPointeeType() const {
|
||||
// FIXME: this might strip inner qualifiers; okay?
|
||||
const ReferenceType *T = this;
|
||||
while (T->InnerRef)
|
||||
T = T->PointeeType->getAs<ReferenceType>();
|
||||
return T->PointeeType;
|
||||
}
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getPointeeType());
|
||||
Profile(ID, PointeeType, SpelledAsLValue);
|
||||
}
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, QualType Referencee) {
|
||||
static void Profile(llvm::FoldingSetNodeID &ID,
|
||||
QualType Referencee,
|
||||
bool SpelledAsLValue) {
|
||||
ID.AddPointer(Referencee.getAsOpaquePtr());
|
||||
ID.AddBoolean(SpelledAsLValue);
|
||||
}
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
@ -1114,9 +1150,10 @@ class ReferenceType : public Type, public llvm::FoldingSetNode {
|
||||
/// LValueReferenceType - C++ [dcl.ref] - Lvalue reference
|
||||
///
|
||||
class LValueReferenceType : public ReferenceType {
|
||||
LValueReferenceType(QualType Referencee, QualType CanonicalRef) :
|
||||
ReferenceType(LValueReference, Referencee, CanonicalRef) {
|
||||
}
|
||||
LValueReferenceType(QualType Referencee, QualType CanonicalRef,
|
||||
bool SpelledAsLValue) :
|
||||
ReferenceType(LValueReference, Referencee, CanonicalRef, SpelledAsLValue)
|
||||
{}
|
||||
friend class ASTContext; // ASTContext creates these
|
||||
public:
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
@ -1135,7 +1172,7 @@ class LValueReferenceType : public ReferenceType {
|
||||
///
|
||||
class RValueReferenceType : public ReferenceType {
|
||||
RValueReferenceType(QualType Referencee, QualType CanonicalRef) :
|
||||
ReferenceType(RValueReference, Referencee, CanonicalRef) {
|
||||
ReferenceType(RValueReference, Referencee, CanonicalRef, false) {
|
||||
}
|
||||
friend class ASTContext; // ASTContext creates these
|
||||
public:
|
||||
@ -1239,8 +1276,6 @@ class ArrayType : public Type, public llvm::FoldingSetNode {
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == ConstantArray ||
|
||||
T->getTypeClass() == ConstantArrayWithExpr ||
|
||||
T->getTypeClass() == ConstantArrayWithoutExpr ||
|
||||
T->getTypeClass() == VariableArray ||
|
||||
T->getTypeClass() == IncompleteArray ||
|
||||
T->getTypeClass() == DependentSizedArray;
|
||||
@ -1285,86 +1320,11 @@ class ConstantArrayType : public ArrayType {
|
||||
ID.AddInteger(TypeQuals);
|
||||
}
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == ConstantArray ||
|
||||
T->getTypeClass() == ConstantArrayWithExpr ||
|
||||
T->getTypeClass() == ConstantArrayWithoutExpr;
|
||||
return T->getTypeClass() == ConstantArray;
|
||||
}
|
||||
static bool classof(const ConstantArrayType *) { return true; }
|
||||
};
|
||||
|
||||
/// ConstantArrayWithExprType - This class represents C arrays with a
|
||||
/// constant size specified by means of an integer constant expression.
|
||||
/// For example 'int A[sizeof(int)]' has ConstantArrayWithExprType where
|
||||
/// the element type is 'int' and the size expression is 'sizeof(int)'.
|
||||
/// These types are non-canonical.
|
||||
class ConstantArrayWithExprType : public ConstantArrayType {
|
||||
/// SizeExpr - The ICE occurring in the concrete syntax.
|
||||
Expr *SizeExpr;
|
||||
/// Brackets - The left and right array brackets.
|
||||
SourceRange Brackets;
|
||||
|
||||
ConstantArrayWithExprType(QualType et, QualType can,
|
||||
const llvm::APInt &size, Expr *e,
|
||||
ArraySizeModifier sm, unsigned tq,
|
||||
SourceRange brackets)
|
||||
: ConstantArrayType(ConstantArrayWithExpr, et, can, size, sm, tq),
|
||||
SizeExpr(e), Brackets(brackets) {}
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
virtual void Destroy(ASTContext& C);
|
||||
|
||||
public:
|
||||
Expr *getSizeExpr() const { return SizeExpr; }
|
||||
SourceRange getBracketsRange() const { return Brackets; }
|
||||
SourceLocation getLBracketLoc() const { return Brackets.getBegin(); }
|
||||
SourceLocation getRBracketLoc() const { return Brackets.getEnd(); }
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == ConstantArrayWithExpr;
|
||||
}
|
||||
static bool classof(const ConstantArrayWithExprType *) { return true; }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
assert(0 && "Cannot unique ConstantArrayWithExprTypes.");
|
||||
}
|
||||
};
|
||||
|
||||
/// ConstantArrayWithoutExprType - This class represents C arrays with a
|
||||
/// constant size that was not specified by an integer constant expression,
|
||||
/// but inferred by static semantics.
|
||||
/// For example 'int A[] = { 0, 1, 2 }' has ConstantArrayWithoutExprType.
|
||||
/// These types are non-canonical: the corresponding canonical type,
|
||||
/// having the size specified in an APInt object, is a ConstantArrayType.
|
||||
class ConstantArrayWithoutExprType : public ConstantArrayType {
|
||||
|
||||
ConstantArrayWithoutExprType(QualType et, QualType can,
|
||||
const llvm::APInt &size,
|
||||
ArraySizeModifier sm, unsigned tq)
|
||||
: ConstantArrayType(ConstantArrayWithoutExpr, et, can, size, sm, tq) {}
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
|
||||
public:
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == ConstantArrayWithoutExpr;
|
||||
}
|
||||
static bool classof(const ConstantArrayWithoutExprType *) { return true; }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
assert(0 && "Cannot unique ConstantArrayWithoutExprTypes.");
|
||||
}
|
||||
};
|
||||
|
||||
/// IncompleteArrayType - This class represents C arrays with an unspecified
|
||||
/// size. For example 'int A[]' has an IncompleteArrayType where the element
|
||||
/// type is 'int' and the size is unspecified.
|
||||
@ -2219,6 +2179,59 @@ class TemplateTypeParmType : public Type, public llvm::FoldingSetNode {
|
||||
static bool classof(const TemplateTypeParmType *T) { return true; }
|
||||
};
|
||||
|
||||
/// \brief Represents the result of substituting a type for a template
|
||||
/// type parameter.
|
||||
///
|
||||
/// Within an instantiated template, all template type parameters have
|
||||
/// been replaced with these. They are used solely to record that a
|
||||
/// type was originally written as a template type parameter;
|
||||
/// therefore they are never canonical.
|
||||
class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode {
|
||||
// The original type parameter.
|
||||
const TemplateTypeParmType *Replaced;
|
||||
|
||||
SubstTemplateTypeParmType(const TemplateTypeParmType *Param, QualType Canon)
|
||||
: Type(SubstTemplateTypeParm, Canon, Canon->isDependentType()),
|
||||
Replaced(Param) { }
|
||||
|
||||
friend class ASTContext;
|
||||
|
||||
public:
|
||||
IdentifierInfo *getName() const { return Replaced->getName(); }
|
||||
|
||||
/// Gets the template parameter that was substituted for.
|
||||
const TemplateTypeParmType *getReplacedParameter() const {
|
||||
return Replaced;
|
||||
}
|
||||
|
||||
/// Gets the type that was substituted for the template
|
||||
/// parameter.
|
||||
QualType getReplacementType() const {
|
||||
return getCanonicalTypeInternal();
|
||||
}
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
bool isSugared() const { return true; }
|
||||
QualType desugar() const { return getReplacementType(); }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getReplacedParameter(), getReplacementType());
|
||||
}
|
||||
static void Profile(llvm::FoldingSetNodeID &ID,
|
||||
const TemplateTypeParmType *Replaced,
|
||||
QualType Replacement) {
|
||||
ID.AddPointer(Replaced);
|
||||
ID.AddPointer(Replacement.getAsOpaquePtr());
|
||||
}
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == SubstTemplateTypeParm;
|
||||
}
|
||||
static bool classof(const SubstTemplateTypeParmType *T) { return true; }
|
||||
};
|
||||
|
||||
/// \brief Represents the type of a template specialization as written
|
||||
/// in the source code.
|
||||
///
|
||||
@ -2453,9 +2466,9 @@ class ObjCInterfaceType : public Type, public llvm::FoldingSetNode {
|
||||
// List is sorted on protocol name. No protocol is enterred more than once.
|
||||
llvm::SmallVector<ObjCProtocolDecl*, 4> Protocols;
|
||||
|
||||
ObjCInterfaceType(ObjCInterfaceDecl *D,
|
||||
ObjCInterfaceType(QualType Canonical, ObjCInterfaceDecl *D,
|
||||
ObjCProtocolDecl **Protos, unsigned NumP) :
|
||||
Type(ObjCInterface, QualType(), /*Dependent=*/false),
|
||||
Type(ObjCInterface, Canonical, /*Dependent=*/false),
|
||||
Decl(D), Protocols(Protos, Protos+NumP) { }
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
public:
|
||||
@ -2501,8 +2514,9 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
|
||||
// List is sorted on protocol name. No protocol is entered more than once.
|
||||
llvm::SmallVector<ObjCProtocolDecl*, 8> Protocols;
|
||||
|
||||
ObjCObjectPointerType(QualType T, ObjCProtocolDecl **Protos, unsigned NumP) :
|
||||
Type(ObjCObjectPointer, QualType(), /*Dependent=*/false),
|
||||
ObjCObjectPointerType(QualType Canonical, QualType T,
|
||||
ObjCProtocolDecl **Protos, unsigned NumP) :
|
||||
Type(ObjCObjectPointer, Canonical, /*Dependent=*/false),
|
||||
PointeeType(T), Protocols(Protos, Protos+NumP) { }
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
|
||||
@ -2567,49 +2581,6 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
|
||||
static bool classof(const ObjCObjectPointerType *) { return true; }
|
||||
};
|
||||
|
||||
/// \brief An ObjC Protocol list that qualifies a type.
|
||||
///
|
||||
/// This is used only for keeping detailed type source information, it should
|
||||
/// not participate in the semantics of the type system.
|
||||
/// The protocol list is not canonicalized.
|
||||
class ObjCProtocolListType : public Type, public llvm::FoldingSetNode {
|
||||
QualType BaseType;
|
||||
|
||||
// List of protocols for this protocol conforming object type.
|
||||
llvm::SmallVector<ObjCProtocolDecl*, 4> Protocols;
|
||||
|
||||
ObjCProtocolListType(QualType T, ObjCProtocolDecl **Protos, unsigned NumP) :
|
||||
Type(ObjCProtocolList, QualType(), /*Dependent=*/false),
|
||||
BaseType(T), Protocols(Protos, Protos+NumP) { }
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
|
||||
public:
|
||||
QualType getBaseType() const { return BaseType; }
|
||||
|
||||
/// \brief Provides access to the list of protocols qualifying the base type.
|
||||
typedef llvm::SmallVector<ObjCProtocolDecl*, 4>::const_iterator qual_iterator;
|
||||
|
||||
qual_iterator qual_begin() const { return Protocols.begin(); }
|
||||
qual_iterator qual_end() const { return Protocols.end(); }
|
||||
bool qual_empty() const { return Protocols.size() == 0; }
|
||||
|
||||
/// \brief Return the number of qualifying protocols.
|
||||
unsigned getNumProtocols() const { return Protocols.size(); }
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID);
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, QualType T,
|
||||
ObjCProtocolDecl **protocols, unsigned NumProtocols);
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == ObjCProtocolList;
|
||||
}
|
||||
static bool classof(const ObjCProtocolListType *) { return true; }
|
||||
};
|
||||
|
||||
/// A qualifier set is used to build a set of qualifiers.
|
||||
class QualifierCollector : public Qualifiers {
|
||||
ASTContext *Context;
|
||||
@ -2646,6 +2617,20 @@ class QualifierCollector : public Qualifiers {
|
||||
|
||||
// Inline function definitions.
|
||||
|
||||
inline bool QualType::isCanonical() const {
|
||||
const Type *T = getTypePtr();
|
||||
if (hasQualifiers())
|
||||
return T->isCanonicalUnqualified() && !isa<ArrayType>(T);
|
||||
return T->isCanonicalUnqualified();
|
||||
}
|
||||
|
||||
inline bool QualType::isCanonicalAsParam() const {
|
||||
if (hasQualifiers()) return false;
|
||||
const Type *T = getTypePtr();
|
||||
return T->isCanonicalUnqualified() &&
|
||||
!isa<FunctionType>(T) && !isa<ArrayType>(T);
|
||||
}
|
||||
|
||||
inline void QualType::removeConst() {
|
||||
removeFastQualifiers(Qualifiers::Const);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
122
include/clang/AST/TypeLocBuilder.h
Normal file
122
include/clang/AST/TypeLocBuilder.h
Normal file
@ -0,0 +1,122 @@
|
||||
//===--- TypeLocBuilder.h - Type Source Info collector ----------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This files defines TypeLocBuilder, a class for building TypeLocs
|
||||
// bottom-up.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_AST_TYPELOCBUILDER_H
|
||||
#define LLVM_CLANG_AST_TYPELOCBUILDER_H
|
||||
|
||||
#include "clang/AST/TypeLoc.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
class TypeLocBuilder {
|
||||
enum { InlineCapacity = 8 * sizeof(SourceLocation) };
|
||||
|
||||
/// The underlying location-data buffer. Data grows from the end
|
||||
/// of the buffer backwards.
|
||||
char *Buffer;
|
||||
|
||||
/// The capacity of the current buffer.
|
||||
size_t Capacity;
|
||||
|
||||
/// The index of the first occupied byte in the buffer.
|
||||
size_t Index;
|
||||
|
||||
#ifndef NDEBUG
|
||||
/// The last type pushed on this builder.
|
||||
QualType LastTy;
|
||||
#endif
|
||||
|
||||
/// The inline buffer.
|
||||
char InlineBuffer[InlineCapacity];
|
||||
|
||||
public:
|
||||
TypeLocBuilder()
|
||||
: Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity)
|
||||
{}
|
||||
|
||||
~TypeLocBuilder() {
|
||||
if (Buffer != InlineBuffer)
|
||||
delete[] Buffer;
|
||||
}
|
||||
|
||||
/// Ensures that this buffer has at least as much capacity as described.
|
||||
void reserve(size_t Requested) {
|
||||
if (Requested > Capacity)
|
||||
// For now, match the request exactly.
|
||||
grow(Requested);
|
||||
}
|
||||
|
||||
/// Pushes space for a new TypeLoc onto the given type. Invalidates
|
||||
/// any TypeLocs previously retrieved from this builder.
|
||||
template <class TyLocType> TyLocType push(QualType T) {
|
||||
#ifndef NDEBUG
|
||||
QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType();
|
||||
assert(TLast == LastTy &&
|
||||
"mismatch between last type and new type's inner type");
|
||||
LastTy = T;
|
||||
#endif
|
||||
|
||||
size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize();
|
||||
|
||||
// If we need to grow, grow by a factor of 2.
|
||||
if (LocalSize > Index) {
|
||||
size_t RequiredCapacity = Capacity + (LocalSize - Index);
|
||||
size_t NewCapacity = Capacity * 2;
|
||||
while (RequiredCapacity > NewCapacity)
|
||||
NewCapacity *= 2;
|
||||
grow(NewCapacity);
|
||||
}
|
||||
|
||||
Index -= LocalSize;
|
||||
|
||||
return cast<TyLocType>(TypeLoc(T, &Buffer[Index]));
|
||||
}
|
||||
|
||||
/// Creates a DeclaratorInfo for the given type.
|
||||
DeclaratorInfo *getDeclaratorInfo(ASTContext& Context, QualType T) {
|
||||
#ifndef NDEBUG
|
||||
assert(T == LastTy && "type doesn't match last type pushed!");
|
||||
#endif
|
||||
|
||||
size_t FullDataSize = Capacity - Index;
|
||||
DeclaratorInfo *DI = Context.CreateDeclaratorInfo(T, FullDataSize);
|
||||
memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize);
|
||||
return DI;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Grow to the given capacity.
|
||||
void grow(size_t NewCapacity) {
|
||||
assert(NewCapacity > Capacity);
|
||||
|
||||
// Allocate the new buffer and copy the old data into it.
|
||||
char *NewBuffer = new char[NewCapacity];
|
||||
unsigned NewIndex = Index + NewCapacity - Capacity;
|
||||
memcpy(&NewBuffer[NewIndex],
|
||||
&Buffer[Index],
|
||||
Capacity - Index);
|
||||
|
||||
if (Buffer != InlineBuffer)
|
||||
delete[] Buffer;
|
||||
|
||||
Buffer = NewBuffer;
|
||||
Capacity = NewCapacity;
|
||||
Index = NewIndex;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -7,54 +7,32 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the TypeLoc info database. Each node is
|
||||
// enumerated by providing its name (e.g., "PointerLoc" or "ArrayLoc"),
|
||||
// base class (e.g., "TypeSpecLoc" or "DeclaratorLoc"), and the Type subclass
|
||||
// that the TypeLoc is associated with.
|
||||
// This file defines the TypeLoc info database. Each node is
|
||||
// enumerated by providing its core name (e.g., "Pointer" for "PointerTypeLoc")
|
||||
// and base class (e.g., "DeclaratorLoc"). All nodes except QualifiedTypeLoc
|
||||
// are associated
|
||||
//
|
||||
// TYPELOC(Class, Base) - A TypeLoc subclass.
|
||||
// TYPELOC(Class, Base) - A TypeLoc subclass. If UNQUAL_TYPELOC is
|
||||
// provided, there will be exactly one of these, Qualified.
|
||||
//
|
||||
// UNQUAL_TYPELOC(Class, Base, Type) - An UnqualTypeLoc subclass.
|
||||
//
|
||||
// ABSTRACT_TYPELOC(Class) - Refers to TypeSpecLoc and DeclaratorLoc.
|
||||
//
|
||||
// TYPESPEC_TYPELOC(Class, Type) - A TypeLoc referring to a type-spec type.
|
||||
//
|
||||
// DECLARATOR_TYPELOC(Class, Type) - A TypeLoc referring to a type part of
|
||||
// a declarator, excluding type-spec types.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef UNQUAL_TYPELOC
|
||||
# define UNQUAL_TYPELOC(Class, Base, Type) TYPELOC(Class, Base)
|
||||
# define UNQUAL_TYPELOC(Class, Base) TYPELOC(Class, Base)
|
||||
#endif
|
||||
|
||||
#ifndef ABSTRACT_TYPELOC
|
||||
# define ABSTRACT_TYPELOC(Class) TYPELOC(Class, TypeLoc)
|
||||
# define ABSTRACT_TYPELOC(Class, Base) UNQUAL_TYPELOC(Class, Base)
|
||||
#endif
|
||||
|
||||
#ifndef TYPESPEC_TYPELOC
|
||||
# define TYPESPEC_TYPELOC(Class, Type) UNQUAL_TYPELOC(Class, TypeSpecLoc, Type)
|
||||
#endif
|
||||
|
||||
#ifndef DECLARATOR_TYPELOC
|
||||
# define DECLARATOR_TYPELOC(Class, Type) UNQUAL_TYPELOC(Class, DeclaratorLoc, Type)
|
||||
#endif
|
||||
|
||||
TYPESPEC_TYPELOC(DefaultTypeSpecLoc, Type)
|
||||
TYPESPEC_TYPELOC(TypedefLoc, TypedefType)
|
||||
TYPESPEC_TYPELOC(ObjCInterfaceLoc, ObjCInterfaceType)
|
||||
TYPESPEC_TYPELOC(ObjCProtocolListLoc, ObjCProtocolListType)
|
||||
DECLARATOR_TYPELOC(PointerLoc, PointerType)
|
||||
DECLARATOR_TYPELOC(BlockPointerLoc, BlockPointerType)
|
||||
DECLARATOR_TYPELOC(MemberPointerLoc, MemberPointerType)
|
||||
DECLARATOR_TYPELOC(ReferenceLoc, ReferenceType)
|
||||
DECLARATOR_TYPELOC(FunctionLoc, FunctionType)
|
||||
DECLARATOR_TYPELOC(ArrayLoc, ArrayType)
|
||||
ABSTRACT_TYPELOC(DeclaratorLoc)
|
||||
ABSTRACT_TYPELOC(TypeSpecLoc)
|
||||
TYPELOC(QualifiedLoc, TypeLoc)
|
||||
|
||||
TYPELOC(Qualified, TypeLoc)
|
||||
#define TYPE(Class, Base) UNQUAL_TYPELOC(Class, Base##Loc)
|
||||
#define ABSTRACT_TYPE(Class, Base) ABSTRACT_TYPELOC(Class, Base##Loc)
|
||||
#include "clang/AST/TypeNodes.def"
|
||||
|
||||
#undef DECLARATOR_TYPELOC
|
||||
#undef TYPESPEC_TYPELOC
|
||||
|
@ -15,46 +15,38 @@
|
||||
|
||||
#include "clang/AST/TypeLoc.h"
|
||||
#include "clang/AST/TypeVisitor.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
#define DISPATCH(CLASS) \
|
||||
return static_cast<ImplClass*>(this)->Visit ## CLASS(cast<CLASS>(TyLoc))
|
||||
#define DISPATCH(CLASSNAME) \
|
||||
return static_cast<ImplClass*>(this)-> \
|
||||
Visit##CLASSNAME(cast<CLASSNAME>(TyLoc))
|
||||
|
||||
template<typename ImplClass, typename RetTy=void>
|
||||
class TypeLocVisitor {
|
||||
class TypeDispatch : public TypeVisitor<TypeDispatch, RetTy> {
|
||||
ImplClass *Impl;
|
||||
UnqualTypeLoc TyLoc;
|
||||
|
||||
public:
|
||||
TypeDispatch(ImplClass *impl, UnqualTypeLoc &tyLoc)
|
||||
: Impl(impl), TyLoc(tyLoc) { }
|
||||
#define TYPELOC(CLASS, BASE)
|
||||
#define ABSTRACT_TYPELOC(CLASS)
|
||||
#define UNQUAL_TYPELOC(CLASS, PARENT, TYPE) \
|
||||
RetTy Visit##TYPE(TYPE *) { \
|
||||
return Impl->Visit##CLASS(reinterpret_cast<CLASS&>(TyLoc)); \
|
||||
}
|
||||
#include "clang/AST/TypeLocNodes.def"
|
||||
};
|
||||
|
||||
public:
|
||||
RetTy Visit(TypeLoc TyLoc) {
|
||||
if (isa<QualifiedLoc>(TyLoc))
|
||||
return static_cast<ImplClass*>(this)->
|
||||
VisitQualifiedLoc(cast<QualifiedLoc>(TyLoc));
|
||||
|
||||
return Visit(cast<UnqualTypeLoc>(TyLoc));
|
||||
switch (TyLoc.getTypeLocClass()) {
|
||||
#define ABSTRACT_TYPELOC(CLASS, PARENT)
|
||||
#define TYPELOC(CLASS, PARENT) \
|
||||
case TypeLoc::CLASS: DISPATCH(CLASS##TypeLoc);
|
||||
#include "clang/AST/TypeLocNodes.def"
|
||||
}
|
||||
llvm::llvm_unreachable("unexpected type loc class!");
|
||||
}
|
||||
|
||||
RetTy Visit(UnqualTypeLoc TyLoc) {
|
||||
TypeDispatch TD(static_cast<ImplClass*>(this), TyLoc);
|
||||
return TD.Visit(TyLoc.getSourceTypePtr());
|
||||
switch (TyLoc.getTypeLocClass()) {
|
||||
#define ABSTRACT_TYPELOC(CLASS, PARENT)
|
||||
#define TYPELOC(CLASS, PARENT) \
|
||||
case TypeLoc::CLASS: DISPATCH(CLASS##TypeLoc);
|
||||
#include "clang/AST/TypeLocNodes.def"
|
||||
}
|
||||
}
|
||||
|
||||
#define TYPELOC(CLASS, PARENT) \
|
||||
RetTy Visit##CLASS(CLASS TyLoc) { \
|
||||
RetTy Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
|
||||
DISPATCH(PARENT); \
|
||||
}
|
||||
#include "clang/AST/TypeLocNodes.def"
|
||||
|
@ -62,8 +62,6 @@ TYPE(RValueReference, ReferenceType)
|
||||
TYPE(MemberPointer, Type)
|
||||
ABSTRACT_TYPE(Array, Type)
|
||||
TYPE(ConstantArray, ArrayType)
|
||||
NON_CANONICAL_TYPE(ConstantArrayWithExpr, ConstantArrayType)
|
||||
NON_CANONICAL_TYPE(ConstantArrayWithoutExpr, ConstantArrayType)
|
||||
TYPE(IncompleteArray, ArrayType)
|
||||
TYPE(VariableArray, ArrayType)
|
||||
DEPENDENT_TYPE(DependentSizedArray, ArrayType)
|
||||
@ -82,12 +80,12 @@ TYPE(Record, TagType)
|
||||
TYPE(Enum, TagType)
|
||||
NON_CANONICAL_TYPE(Elaborated, Type)
|
||||
DEPENDENT_TYPE(TemplateTypeParm, Type)
|
||||
NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type)
|
||||
TYPE(TemplateSpecialization, Type)
|
||||
NON_CANONICAL_TYPE(QualifiedName, Type)
|
||||
DEPENDENT_TYPE(Typename, Type)
|
||||
TYPE(ObjCInterface, Type)
|
||||
TYPE(ObjCObjectPointer, Type)
|
||||
NON_CANONICAL_TYPE(ObjCProtocolList, Type)
|
||||
|
||||
// These types are always leaves in the type hierarchy.
|
||||
#ifdef LEAF_TYPE
|
||||
@ -95,7 +93,6 @@ LEAF_TYPE(Enum)
|
||||
LEAF_TYPE(Builtin)
|
||||
LEAF_TYPE(FixedWidthInt)
|
||||
LEAF_TYPE(ObjCInterface)
|
||||
LEAF_TYPE(ObjCObjectPointer)
|
||||
LEAF_TYPE(TemplateTypeParm)
|
||||
#undef LEAF_TYPE
|
||||
#endif
|
||||
|
@ -60,6 +60,9 @@ class AnalysisContextManager {
|
||||
~AnalysisContextManager();
|
||||
|
||||
AnalysisContext *getContext(const Decl *D);
|
||||
|
||||
// Discard all previously created AnalysisContexts.
|
||||
void clear();
|
||||
};
|
||||
|
||||
class LocationContext : public llvm::FoldingSetNode {
|
||||
@ -155,12 +158,17 @@ class LocationContextManager {
|
||||
llvm::FoldingSet<LocationContext> Contexts;
|
||||
|
||||
public:
|
||||
~LocationContextManager();
|
||||
|
||||
StackFrameContext *getStackFrame(AnalysisContext *ctx,
|
||||
const LocationContext *parent,
|
||||
const Stmt *s);
|
||||
|
||||
ScopeContext *getScope(AnalysisContext *ctx, const LocationContext *parent,
|
||||
const Stmt *s);
|
||||
|
||||
/// Discard all previously created LocationContext objects.
|
||||
void clear();
|
||||
};
|
||||
|
||||
} // end clang namespace
|
||||
|
@ -65,6 +65,11 @@ class AnalysisManager : public BugReporterData {
|
||||
AScope(ScopeDecl), DisplayedFunction(!displayProgress),
|
||||
VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge),
|
||||
EagerlyAssume(eager), TrimGraph(trim) {}
|
||||
|
||||
void ClearContexts() {
|
||||
LocCtxMgr.clear();
|
||||
AnaCtxMgr.clear();
|
||||
}
|
||||
|
||||
StoreManagerCreator getStoreManagerCreator() {
|
||||
return CreateStoreMgr;
|
||||
|
@ -141,9 +141,12 @@ class StoreManager {
|
||||
const VarDecl *VD,
|
||||
const LocationContext *LC) = 0;
|
||||
|
||||
typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols;
|
||||
|
||||
virtual const GRState *InvalidateRegion(const GRState *state,
|
||||
const MemRegion *R,
|
||||
const Expr *E, unsigned Count) = 0;
|
||||
const Expr *E, unsigned Count,
|
||||
InvalidatedSymbols *IS) = 0;
|
||||
|
||||
// FIXME: Make out-of-line.
|
||||
virtual const GRState *setExtent(const GRState *state,
|
||||
|
@ -27,16 +27,16 @@
|
||||
namespace clang {
|
||||
|
||||
class BumpVectorContext {
|
||||
llvm::PointerIntPair<llvm::BumpPtrAllocator*, 1, bool> Alloc;
|
||||
llvm::PointerIntPair<llvm::BumpPtrAllocator*, 1> Alloc;
|
||||
public:
|
||||
/// Construct a new BumpVectorContext that creates a new BumpPtrAllocator
|
||||
/// and destroys it when the BumpVectorContext object is destroyed.
|
||||
BumpVectorContext() : Alloc(new llvm::BumpPtrAllocator(), true) {}
|
||||
BumpVectorContext() : Alloc(new llvm::BumpPtrAllocator(), 1) {}
|
||||
|
||||
/// Construct a new BumpVectorContext that reuses an existing
|
||||
/// BumpPtrAllocator. This BumpPtrAllocator is not destroyed when the
|
||||
/// BumpVectorContext object is destroyed.
|
||||
BumpVectorContext(llvm::BumpPtrAllocator &A) : Alloc(&A, false) {}
|
||||
BumpVectorContext(llvm::BumpPtrAllocator &A) : Alloc(&A, 0) {}
|
||||
|
||||
~BumpVectorContext() {
|
||||
if (Alloc.getInt())
|
||||
|
@ -15,6 +15,7 @@
|
||||
#define LLVM_CLANG_DIAGNOSTIC_H
|
||||
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/type_traits.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -43,7 +44,7 @@ namespace clang {
|
||||
DIAG_START_PARSE = DIAG_START_LEX + 300,
|
||||
DIAG_START_AST = DIAG_START_PARSE + 300,
|
||||
DIAG_START_SEMA = DIAG_START_AST + 100,
|
||||
DIAG_START_ANALYSIS = DIAG_START_SEMA + 1000,
|
||||
DIAG_START_ANALYSIS = DIAG_START_SEMA + 1100,
|
||||
DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100
|
||||
};
|
||||
|
||||
@ -107,7 +108,7 @@ class CodeModificationHint {
|
||||
/// \brief Create a code modification hint that inserts the given
|
||||
/// code string at a specific location.
|
||||
static CodeModificationHint CreateInsertion(SourceLocation InsertionLoc,
|
||||
const std::string &Code) {
|
||||
llvm::StringRef Code) {
|
||||
CodeModificationHint Hint;
|
||||
Hint.InsertionLoc = InsertionLoc;
|
||||
Hint.CodeToInsert = Code;
|
||||
@ -125,7 +126,7 @@ class CodeModificationHint {
|
||||
/// \brief Create a code modification hint that replaces the given
|
||||
/// source range with the given code string.
|
||||
static CodeModificationHint CreateReplacement(SourceRange RemoveRange,
|
||||
const std::string &Code) {
|
||||
llvm::StringRef Code) {
|
||||
CodeModificationHint Hint;
|
||||
Hint.RemoveRange = RemoveRange;
|
||||
Hint.InsertionLoc = RemoveRange.getBegin();
|
||||
@ -163,6 +164,10 @@ class Diagnostic {
|
||||
ak_nestednamespec, // NestedNameSpecifier *
|
||||
ak_declcontext // DeclContext *
|
||||
};
|
||||
|
||||
/// ArgumentValue - This typedef represents on argument value, which is a
|
||||
/// union discriminated by ArgumentKind, with a value.
|
||||
typedef std::pair<ArgumentKind, intptr_t> ArgumentValue;
|
||||
|
||||
private:
|
||||
unsigned char AllExtensionsSilenced; // Used by __extension__
|
||||
@ -202,10 +207,17 @@ class Diagnostic {
|
||||
/// ArgToStringFn - A function pointer that converts an opaque diagnostic
|
||||
/// argument to a strings. This takes the modifiers and argument that was
|
||||
/// present in the diagnostic.
|
||||
///
|
||||
/// The PrevArgs array (whose length is NumPrevArgs) indicates the previous
|
||||
/// arguments formatted for this diagnostic. Implementations of this function
|
||||
/// can use this information to avoid redundancy across arguments.
|
||||
///
|
||||
/// This is a hack to avoid a layering violation between libbasic and libsema.
|
||||
typedef void (*ArgToStringFnTy)(ArgumentKind Kind, intptr_t Val,
|
||||
const char *Modifier, unsigned ModifierLen,
|
||||
const char *Argument, unsigned ArgumentLen,
|
||||
const ArgumentValue *PrevArgs,
|
||||
unsigned NumPrevArgs,
|
||||
llvm::SmallVectorImpl<char> &Output,
|
||||
void *Cookie);
|
||||
void *ArgToStringCookie;
|
||||
@ -310,9 +322,10 @@ class Diagnostic {
|
||||
void ConvertArgToString(ArgumentKind Kind, intptr_t Val,
|
||||
const char *Modifier, unsigned ModLen,
|
||||
const char *Argument, unsigned ArgLen,
|
||||
const ArgumentValue *PrevArgs, unsigned NumPrevArgs,
|
||||
llvm::SmallVectorImpl<char> &Output) const {
|
||||
ArgToStringFn(Kind, Val, Modifier, ModLen, Argument, ArgLen, Output,
|
||||
ArgToStringCookie);
|
||||
ArgToStringFn(Kind, Val, Modifier, ModLen, Argument, ArgLen,
|
||||
PrevArgs, NumPrevArgs, Output, ArgToStringCookie);
|
||||
}
|
||||
|
||||
void SetArgToStringFn(ArgToStringFnTy Fn, void *Cookie) {
|
||||
@ -546,7 +559,7 @@ class DiagnosticBuilder {
|
||||
/// return Diag(...);
|
||||
operator bool() const { return true; }
|
||||
|
||||
void AddString(const std::string &S) const {
|
||||
void AddString(llvm::StringRef S) const {
|
||||
assert(NumArgs < Diagnostic::MaxArguments &&
|
||||
"Too many arguments to diagnostic!");
|
||||
if (DiagObj) {
|
||||
@ -581,7 +594,7 @@ class DiagnosticBuilder {
|
||||
};
|
||||
|
||||
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
|
||||
const std::string &S) {
|
||||
llvm::StringRef S) {
|
||||
DB.AddString(S);
|
||||
return DB;
|
||||
}
|
||||
|
@ -201,6 +201,9 @@ def warn_expected_implementation : Warning<
|
||||
"@end must appear in an @implementation context">;
|
||||
def error_property_ivar_decl : Error<
|
||||
"property synthesize requires specification of an ivar">;
|
||||
def warn_semicolon_before_method_nody : Warning<
|
||||
"semicolon before method body is ignored">,
|
||||
InGroup<DiagGroup<"semicolon-before-method-body">>;
|
||||
|
||||
def err_expected_field_designator : Error<
|
||||
"expected a field designator, such as '.field = 4'">;
|
||||
|
@ -383,6 +383,8 @@ def note_ambig_member_ref_object_type : Note<
|
||||
"lookup in the object type %0 refers here">;
|
||||
def note_ambig_member_ref_scope : Note<
|
||||
"lookup from the current scope refers here">;
|
||||
def err_qualified_member_nonclass : Error<
|
||||
"qualified member access refers to a member in %0">;
|
||||
|
||||
// C++ class members
|
||||
def err_storageclass_invalid_for_member : Error<
|
||||
@ -785,9 +787,9 @@ def err_ovl_template_candidate : Note<
|
||||
def err_ovl_candidate_deleted : Note<
|
||||
"candidate function has been explicitly %select{made unavailable|deleted}0">;
|
||||
def err_ovl_builtin_binary_candidate : Note<
|
||||
"built-in candidate operator %0 (%1, %2)">;
|
||||
"built-in candidate %0">;
|
||||
def err_ovl_builtin_unary_candidate : Note<
|
||||
"built-in candidate operator %0 (%1)">;
|
||||
"built-in candidate %0">;
|
||||
def err_ovl_no_viable_function_in_init : Error<
|
||||
"no matching constructor for initialization of %0">;
|
||||
def err_ovl_ambiguous_init : Error<"call to constructor of %0 is ambiguous">;
|
||||
@ -1112,7 +1114,17 @@ def err_explicit_instantiation_without_qualified_id_quals : Error<
|
||||
"qualifier in explicit instantiation of '%0%1' requires a template-id">;
|
||||
def err_explicit_instantiation_unqualified_wrong_namespace : Error<
|
||||
"explicit instantiation of %q0 must occur in %1">;
|
||||
|
||||
def err_explicit_instantiation_undefined_member : Error<
|
||||
"explicit instantiation of undefined %select{member class|member function|"
|
||||
"static data member}0 %1 of class template %2">;
|
||||
def err_explicit_instantiation_undefined_func_template : Error<
|
||||
"explicit instantiation of undefined function template %0">;
|
||||
def err_explicit_instantiation_declaration_after_definition : Error<
|
||||
"explicit instantiation declaration (with 'extern') follows explicit "
|
||||
"instantiation definition (without 'extern')">;
|
||||
def note_explicit_instantiation_definition_here : Note<
|
||||
"explicit instantiation definition is here">;
|
||||
|
||||
// C++ typename-specifiers
|
||||
def err_typename_nested_not_found : Error<"no type named %0 in %1">;
|
||||
def err_typename_nested_not_type : Error<
|
||||
@ -1734,7 +1746,9 @@ def err_not_tag_in_scope : Error<
|
||||
|
||||
def err_cannot_form_pointer_to_member_of_reference_type : Error<
|
||||
"cannot form a pointer-to-member to member %0 of reference type %1">;
|
||||
|
||||
def err_incomplete_object_call : Error<
|
||||
"incomplete type in call to object of type %0">;
|
||||
|
||||
def warn_condition_is_assignment : Warning<"using the result of an "
|
||||
"assignment as a condition without parentheses">,
|
||||
InGroup<Parentheses>;
|
||||
@ -2156,6 +2170,8 @@ def err_break_not_in_loop_or_switch : Error<
|
||||
def err_default_not_in_switch : Error<
|
||||
"'default' statement not in switch statement">;
|
||||
def err_case_not_in_switch : Error<"'case' statement not in switch statement">;
|
||||
def warn_bool_switch_condition : Warning<
|
||||
"switch condition is a bool">;
|
||||
def warn_case_value_overflow : Warning<
|
||||
"overflow converting case value to switch condition type (%0 to %1)">;
|
||||
def err_duplicate_case : Error<"duplicate case value '%0'">;
|
||||
@ -2187,7 +2203,7 @@ def ext_return_has_expr : ExtWarn<
|
||||
def ext_return_has_void_expr : Extension<
|
||||
"void %select{function|method}1 %0 should not return void expression">;
|
||||
def warn_noreturn_function_has_return_expr : Warning<
|
||||
"function %0 declared 'noreturn' should not return">, DefaultError,
|
||||
"function %0 declared 'noreturn' should not return">,
|
||||
InGroup<DiagGroup<"invalid-noreturn">>;
|
||||
def warn_falloff_noreturn_function : Warning<
|
||||
"function declared 'noreturn' should not return">,
|
||||
|
@ -71,16 +71,38 @@ class FileEntry {
|
||||
}
|
||||
};
|
||||
|
||||
// FIXME: This is a lightweight shim that is used by FileManager to cache
|
||||
// 'stat' system calls. We will use it with PTH to identify if caching
|
||||
// stat calls in PTH files is a performance win.
|
||||
/// \brief Abstract interface for introducing a FileManager cache for 'stat'
|
||||
/// system calls, which is used by precompiled and pretokenized headers to
|
||||
/// improve performance.
|
||||
class StatSysCallCache {
|
||||
protected:
|
||||
llvm::OwningPtr<StatSysCallCache> NextStatCache;
|
||||
|
||||
public:
|
||||
virtual ~StatSysCallCache() {}
|
||||
virtual int stat(const char *path, struct stat *buf) = 0;
|
||||
virtual int stat(const char *path, struct stat *buf) {
|
||||
if (getNextStatCache())
|
||||
return getNextStatCache()->stat(path, buf);
|
||||
|
||||
return ::stat(path, buf);
|
||||
}
|
||||
|
||||
/// \brief Sets the next stat call cache in the chain of stat caches.
|
||||
/// Takes ownership of the given stat cache.
|
||||
void setNextStatCache(StatSysCallCache *Cache) {
|
||||
NextStatCache.reset(Cache);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the next stat call cache in the chain.
|
||||
StatSysCallCache *getNextStatCache() { return NextStatCache.get(); }
|
||||
|
||||
/// \brief Retrieve the next stat call cache in the chain, transferring
|
||||
/// ownership of this cache (and, transitively, all of the remaining caches)
|
||||
/// to the caller.
|
||||
StatSysCallCache *takeNextStatCache() { return NextStatCache.take(); }
|
||||
};
|
||||
|
||||
/// \brief A stat listener that can be used by FileManager to keep
|
||||
/// \brief A stat "cache" that can be used by FileManager to keep
|
||||
/// track of the results of stat() calls that occur throughout the
|
||||
/// execution of the front end.
|
||||
class MemorizeStatCalls : public StatSysCallCache {
|
||||
@ -144,13 +166,22 @@ class FileManager {
|
||||
FileManager();
|
||||
~FileManager();
|
||||
|
||||
/// setStatCache - Installs the provided StatSysCallCache object within
|
||||
/// the FileManager. Ownership of this object is transferred to the
|
||||
/// FileManager.
|
||||
void setStatCache(StatSysCallCache *statCache) {
|
||||
StatCache.reset(statCache);
|
||||
}
|
||||
/// \brief Installs the provided StatSysCallCache object within
|
||||
/// the FileManager.
|
||||
///
|
||||
/// Ownership of this object is transferred to the FileManager.
|
||||
///
|
||||
/// \param statCache the new stat cache to install. Ownership of this
|
||||
/// object is transferred to the FileManager.
|
||||
///
|
||||
/// \param AtBeginning whether this new stat cache must be installed at the
|
||||
/// beginning of the chain of stat caches. Otherwise, it will be added to
|
||||
/// the end of the chain.
|
||||
void addStatCache(StatSysCallCache *statCache, bool AtBeginning = false);
|
||||
|
||||
/// \brief Removes the provided StatSysCallCache object from the file manager.
|
||||
void removeStatCache(StatSysCallCache *statCache);
|
||||
|
||||
/// getDirectory - Lookup, cache, and verify the specified directory. This
|
||||
/// returns null if the directory doesn't exist.
|
||||
///
|
||||
|
@ -75,13 +75,13 @@ class IdentifierInfo {
|
||||
/// This is intended to be used for string literals only: II->isStr("foo").
|
||||
template <std::size_t StrLen>
|
||||
bool isStr(const char (&Str)[StrLen]) const {
|
||||
return getLength() == StrLen-1 && !memcmp(getName(), Str, StrLen-1);
|
||||
return getLength() == StrLen-1 && !memcmp(getNameStart(), Str, StrLen-1);
|
||||
}
|
||||
|
||||
/// getName - Return the actual string for this identifier. The returned
|
||||
/// string is properly null terminated.
|
||||
/// getNameStart - Return the beginning of the actual string for this
|
||||
/// identifier. The returned string is properly null terminated.
|
||||
///
|
||||
const char *getName() const {
|
||||
const char *getNameStart() const {
|
||||
if (Entry) return Entry->getKeyData();
|
||||
// FIXME: This is gross. It would be best not to embed specific details
|
||||
// of the PTH file format here.
|
||||
@ -101,8 +101,12 @@ class IdentifierInfo {
|
||||
// std::pair<IdentifierInfo, const char*>, where internal pointer
|
||||
// points to the external string data.
|
||||
const char* p = ((std::pair<IdentifierInfo, const char*>*) this)->second-2;
|
||||
return (((unsigned) p[0])
|
||||
| (((unsigned) p[1]) << 8)) - 1;
|
||||
return (((unsigned) p[0]) | (((unsigned) p[1]) << 8)) - 1;
|
||||
}
|
||||
|
||||
/// getName - Return the actual identifier string.
|
||||
llvm::StringRef getName() const {
|
||||
return llvm::StringRef(getNameStart(), getLength());
|
||||
}
|
||||
|
||||
/// hasMacroDefinition - Return true if this identifier is #defined to some
|
||||
@ -232,6 +236,8 @@ class IdentifierInfoLookup {
|
||||
/// Unlike the version in IdentifierTable, this returns a pointer instead
|
||||
/// of a reference. If the pointer is NULL then the IdentifierInfo cannot
|
||||
/// be found.
|
||||
//
|
||||
// FIXME: Move to StringRef API.
|
||||
virtual IdentifierInfo* get(const char *NameStart, const char *NameEnd) = 0;
|
||||
};
|
||||
|
||||
@ -333,8 +339,11 @@ class IdentifierTable {
|
||||
|
||||
return *II;
|
||||
}
|
||||
IdentifierInfo &CreateIdentifierInfo(llvm::StringRef Name) {
|
||||
return CreateIdentifierInfo(Name.begin(), Name.end());
|
||||
}
|
||||
|
||||
IdentifierInfo &get(const llvm::StringRef& Name) {
|
||||
IdentifierInfo &get(llvm::StringRef Name) {
|
||||
return get(Name.begin(), Name.end());
|
||||
}
|
||||
|
||||
@ -463,7 +472,7 @@ class SelectorTable {
|
||||
const IdentifierInfo *Name) {
|
||||
llvm::SmallString<100> SelectorName;
|
||||
SelectorName = "set";
|
||||
SelectorName.append(Name->getName(), Name->getName()+Name->getLength());
|
||||
SelectorName += Name->getName();
|
||||
SelectorName[3] = toupper(SelectorName[3]);
|
||||
IdentifierInfo *SetterName =
|
||||
&Idents.get(SelectorName.data(),
|
||||
|
@ -25,27 +25,6 @@
|
||||
|
||||
namespace clang {
|
||||
|
||||
// Bernstein hash function:
|
||||
// This is basically copy-and-paste from StringMap. This likely won't
|
||||
// stay here, which is why I didn't both to expose this function from
|
||||
// String Map.
|
||||
inline unsigned BernsteinHash(const char* x) {
|
||||
unsigned int R = 0;
|
||||
for ( ; *x != '\0' ; ++x) R = R * 33 + *x;
|
||||
return R + (R >> 5);
|
||||
}
|
||||
|
||||
inline unsigned BernsteinHash(const char* x, unsigned n) {
|
||||
unsigned int R = 0;
|
||||
for (unsigned i = 0 ; i < n ; ++i, ++x) R = R * 33 + *x;
|
||||
return R + (R >> 5);
|
||||
}
|
||||
|
||||
inline unsigned BernsteinHashPartial(const char* x, unsigned n, unsigned R) {
|
||||
for (unsigned i = 0 ; i < n ; ++i, ++x) R = R * 33 + *x;
|
||||
return R + (R >> 5);
|
||||
}
|
||||
|
||||
namespace io {
|
||||
|
||||
typedef uint32_t Offset;
|
||||
|
@ -685,26 +685,19 @@ class SourceManager {
|
||||
///
|
||||
void PrintStats() const;
|
||||
|
||||
// Iteration over the source location entry table.
|
||||
typedef std::vector<SrcMgr::SLocEntry>::const_iterator sloc_entry_iterator;
|
||||
|
||||
sloc_entry_iterator sloc_entry_begin() const {
|
||||
return SLocEntryTable.begin();
|
||||
}
|
||||
|
||||
sloc_entry_iterator sloc_entry_end() const {
|
||||
return SLocEntryTable.end();
|
||||
}
|
||||
|
||||
unsigned sloc_entry_size() const { return SLocEntryTable.size(); }
|
||||
|
||||
const SrcMgr::SLocEntry &getSLocEntry(FileID FID) const {
|
||||
assert(FID.ID < SLocEntryTable.size() && "Invalid id");
|
||||
const SrcMgr::SLocEntry &getSLocEntry(unsigned ID) const {
|
||||
assert(ID < SLocEntryTable.size() && "Invalid id");
|
||||
if (ExternalSLocEntries &&
|
||||
FID.ID < SLocEntryLoaded.size() &&
|
||||
!SLocEntryLoaded[FID.ID])
|
||||
ExternalSLocEntries->ReadSLocEntry(FID.ID);
|
||||
return SLocEntryTable[FID.ID];
|
||||
ID < SLocEntryLoaded.size() &&
|
||||
!SLocEntryLoaded[ID])
|
||||
ExternalSLocEntries->ReadSLocEntry(ID);
|
||||
return SLocEntryTable[ID];
|
||||
}
|
||||
|
||||
const SrcMgr::SLocEntry &getSLocEntry(FileID FID) const {
|
||||
return getSLocEntry(FID.ID);
|
||||
}
|
||||
|
||||
unsigned getNextOffset() const { return NextOffset; }
|
||||
|
@ -83,7 +83,7 @@ class TargetInfo {
|
||||
};
|
||||
protected:
|
||||
IntType SizeType, IntMaxType, UIntMaxType, PtrDiffType, IntPtrType, WCharType,
|
||||
Char16Type, Char32Type, Int64Type;
|
||||
WIntType, Char16Type, Char32Type, Int64Type;
|
||||
public:
|
||||
IntType getSizeType() const { return SizeType; }
|
||||
IntType getIntMaxType() const { return IntMaxType; }
|
||||
@ -93,10 +93,20 @@ class TargetInfo {
|
||||
}
|
||||
IntType getIntPtrType() const { return IntPtrType; }
|
||||
IntType getWCharType() const { return WCharType; }
|
||||
IntType getWIntType() const { return WIntType; }
|
||||
IntType getChar16Type() const { return Char16Type; }
|
||||
IntType getChar32Type() const { return Char32Type; }
|
||||
IntType getInt64Type() const { return Int64Type; }
|
||||
|
||||
|
||||
/// getTypeWidth - Return the width (in bits) of the specified integer type
|
||||
/// enum. For example, SignedInt -> getIntWidth().
|
||||
unsigned getTypeWidth(IntType T) const;
|
||||
|
||||
/// getTypeSigned - Return whether an integer types is signed. Returns true if
|
||||
/// the type is signed; false otherwise.
|
||||
bool getTypeSigned(IntType T) const;
|
||||
|
||||
/// getPointerWidth - Return the width of pointers on this target, for the
|
||||
/// specified address space.
|
||||
uint64_t getPointerWidth(unsigned AddrSpace) const {
|
||||
@ -185,6 +195,10 @@ class TargetInfo {
|
||||
/// For example, SignedShort -> "short".
|
||||
static const char *getTypeName(IntType T);
|
||||
|
||||
/// getTypeConstantSuffix - Return the constant suffix for the specified
|
||||
/// integer type enum. For example, SignedLong -> "L".
|
||||
static const char *getTypeConstantSuffix(IntType T);
|
||||
|
||||
///===---- Other target property query methods --------------------------===//
|
||||
|
||||
/// getTargetDefines - Appends the target-specific #define values for this
|
||||
@ -192,6 +206,7 @@ class TargetInfo {
|
||||
virtual void getTargetDefines(const LangOptions &Opts,
|
||||
std::vector<char> &DefineBuffer) const = 0;
|
||||
|
||||
|
||||
/// getTargetBuiltins - Return information about target-specific builtins for
|
||||
/// the current primary target, and info about which builtins are non-portable
|
||||
/// across the current set of primary and secondary targets.
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "clang/Frontend/TextDiagnosticBuffer.h"
|
||||
#include "clang/Basic/FileManager.h"
|
||||
#include <string>
|
||||
|
||||
namespace clang {
|
||||
@ -23,6 +25,7 @@ namespace clang {
|
||||
class FileEntry;
|
||||
class SourceManager;
|
||||
class Diagnostic;
|
||||
class TextDiagnosticBuffer;
|
||||
class HeaderSearch;
|
||||
class TargetInfo;
|
||||
class Preprocessor;
|
||||
@ -32,18 +35,27 @@ namespace clang {
|
||||
/// \brief Utility class for loading a ASTContext from a PCH file.
|
||||
///
|
||||
class ASTUnit {
|
||||
Diagnostic &Diags;
|
||||
Diagnostic Diags;
|
||||
FileManager FileMgr;
|
||||
|
||||
SourceManager SourceMgr;
|
||||
llvm::OwningPtr<HeaderSearch> HeaderInfo;
|
||||
llvm::OwningPtr<TargetInfo> Target;
|
||||
llvm::OwningPtr<Preprocessor> PP;
|
||||
llvm::OwningPtr<ASTContext> Ctx;
|
||||
|
||||
bool tempFile;
|
||||
|
||||
// OnlyLocalDecls - when true, walking this AST should only visit declarations
|
||||
// that come from the AST itself, not from included precompiled headers.
|
||||
// FIXME: This is temporary; eventually, CIndex will always do this.
|
||||
bool OnlyLocalDecls;
|
||||
|
||||
ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT
|
||||
ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT
|
||||
ASTUnit(Diagnostic &_Diag);
|
||||
ASTUnit();
|
||||
|
||||
public:
|
||||
ASTUnit(DiagnosticClient *diagClient = NULL);
|
||||
~ASTUnit();
|
||||
|
||||
const SourceManager &getSourceManager() const { return SourceMgr; }
|
||||
@ -58,14 +70,23 @@ class ASTUnit {
|
||||
const Diagnostic &getDiagnostic() const { return Diags; }
|
||||
Diagnostic &getDiagnostic() { return Diags; }
|
||||
|
||||
FileManager &getFileManager();
|
||||
const FileManager &getFileManager() const { return FileMgr; }
|
||||
FileManager &getFileManager() { return FileMgr; }
|
||||
|
||||
const std::string &getOriginalSourceFileName();
|
||||
const std::string &getPCHFileName();
|
||||
|
||||
void unlinkTemporaryFile() { tempFile = true; }
|
||||
|
||||
bool getOnlyLocalDecls() const { return OnlyLocalDecls; }
|
||||
|
||||
/// \brief Create a ASTUnit from a PCH file.
|
||||
///
|
||||
/// \param Filename - The PCH file to load.
|
||||
///
|
||||
/// \param Diags - The Diagnostic implementation to use.
|
||||
/// \param diagClient - The diagnostics client to use. Specify NULL
|
||||
/// to use a default client that emits warnings/errors to standard error.
|
||||
/// The ASTUnit objects takes ownership of this object.
|
||||
///
|
||||
/// \param FileMgr - The FileManager to use.
|
||||
///
|
||||
@ -74,9 +95,10 @@ class ASTUnit {
|
||||
///
|
||||
/// \returns - The initialized ASTUnit or null if the PCH failed to load.
|
||||
static ASTUnit *LoadFromPCHFile(const std::string &Filename,
|
||||
Diagnostic &Diags,
|
||||
FileManager &FileMgr,
|
||||
std::string *ErrMsg = 0);
|
||||
std::string *ErrMsg = 0,
|
||||
DiagnosticClient *diagClient = NULL,
|
||||
bool OnlyLocalDecls = false,
|
||||
bool UseBumpAllocator = false);
|
||||
};
|
||||
|
||||
} // namespace clang
|
||||
|
@ -86,38 +86,33 @@ namespace clang {
|
||||
PREPROCESSOR_BLOCK_ID,
|
||||
|
||||
/// \brief The block containing the definitions of all of the
|
||||
/// types used within the PCH file.
|
||||
TYPES_BLOCK_ID,
|
||||
|
||||
/// \brief The block containing the definitions of all of the
|
||||
/// declarations stored in the PCH file.
|
||||
DECLS_BLOCK_ID
|
||||
/// types and decls used within the PCH file.
|
||||
DECLTYPES_BLOCK_ID
|
||||
};
|
||||
|
||||
/// \brief Record types that occur within the PCH block itself.
|
||||
enum PCHRecordTypes {
|
||||
/// \brief Offset of each type within the types block.
|
||||
/// \brief Record code for the offsets of each type.
|
||||
///
|
||||
/// The TYPE_OFFSET constant describes the record that occurs
|
||||
/// within the block identified by TYPE_OFFSETS_BLOCK_ID within
|
||||
/// the PCH file. The record itself is an array of offsets that
|
||||
/// point into the types block (identified by TYPES_BLOCK_ID in
|
||||
/// the PCH file). The index into the array is based on the ID
|
||||
/// within the PCH block. The record itself is an array of offsets that
|
||||
/// point into the declarations and types block (identified by
|
||||
/// DECLTYPES_BLOCK_ID). The index into the array is based on the ID
|
||||
/// of a type. For a given type ID @c T, the lower three bits of
|
||||
/// @c T are its qualifiers (const, volatile, restrict), as in
|
||||
/// the QualType class. The upper bits, after being shifted and
|
||||
/// subtracting NUM_PREDEF_TYPE_IDS, are used to index into the
|
||||
/// TYPE_OFFSET block to determine the offset of that type's
|
||||
/// corresponding record within the TYPES_BLOCK_ID block.
|
||||
/// corresponding record within the DECLTYPES_BLOCK_ID block.
|
||||
TYPE_OFFSET = 1,
|
||||
|
||||
/// \brief Record code for the offsets of each decl.
|
||||
///
|
||||
/// The DECL_OFFSET constant describes the record that occurs
|
||||
/// within the block identifier by DECL_OFFSETS_BLOCK_ID within
|
||||
/// the PCH file. The record itself is an array of offsets that
|
||||
/// point into the declarations block (identified by
|
||||
/// DECLS_BLOCK_ID). The declaration ID is an index into this
|
||||
/// within the block identified by DECL_OFFSETS_BLOCK_ID within
|
||||
/// the PCH block. The record itself is an array of offsets that
|
||||
/// point into the declarations and types block (identified by
|
||||
/// DECLTYPES_BLOCK_ID). The declaration ID is an index into this
|
||||
/// record, after subtracting one to account for the use of
|
||||
/// declaration ID 0 for a NULL declaration pointer. Index 0 is
|
||||
/// reserved for the translation unit declaration.
|
||||
@ -353,8 +348,8 @@ namespace clang {
|
||||
|
||||
/// \brief Record codes for each kind of type.
|
||||
///
|
||||
/// These constants describe the records that can occur within a
|
||||
/// block identified by TYPES_BLOCK_ID in the PCH file. Each
|
||||
/// These constants describe the type records that can occur within a
|
||||
/// block identified by DECLTYPES_BLOCK_ID in the PCH file. Each
|
||||
/// constant describes a record for a specific type class in the
|
||||
/// AST.
|
||||
enum TypeCode {
|
||||
@ -402,16 +397,12 @@ namespace clang {
|
||||
TYPE_OBJC_INTERFACE = 21,
|
||||
/// \brief An ObjCObjectPointerType record.
|
||||
TYPE_OBJC_OBJECT_POINTER = 22,
|
||||
/// \brief An ObjCProtocolListType record.
|
||||
TYPE_OBJC_PROTOCOL_LIST = 23,
|
||||
/// \brief a DecltypeType record.
|
||||
TYPE_DECLTYPE = 24,
|
||||
/// \brief A ConstantArrayWithExprType record.
|
||||
TYPE_CONSTANT_ARRAY_WITH_EXPR = 25,
|
||||
/// \brief A ConstantArrayWithoutExprType record.
|
||||
TYPE_CONSTANT_ARRAY_WITHOUT_EXPR = 26,
|
||||
TYPE_DECLTYPE = 23,
|
||||
/// \brief An ElaboratedType record.
|
||||
TYPE_ELABORATED = 27
|
||||
TYPE_ELABORATED = 24,
|
||||
/// \brief A SubstTemplateTypeParmType record.
|
||||
TYPE_SUBST_TEMPLATE_TYPE_PARM = 25
|
||||
};
|
||||
|
||||
/// \brief The type IDs for special types constructed by semantic
|
||||
@ -443,18 +434,22 @@ namespace clang {
|
||||
/// \brief Objective-C "id" redefinition type
|
||||
SPECIAL_TYPE_OBJC_ID_REDEFINITION = 10,
|
||||
/// \brief Objective-C "Class" redefinition type
|
||||
SPECIAL_TYPE_OBJC_CLASS_REDEFINITION = 11
|
||||
SPECIAL_TYPE_OBJC_CLASS_REDEFINITION = 11,
|
||||
/// \brief Block descriptor type for Blocks CodeGen
|
||||
SPECIAL_TYPE_BLOCK_DESCRIPTOR = 12,
|
||||
/// \brief Block extedned descriptor type for Blocks CodeGen
|
||||
SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR = 13
|
||||
};
|
||||
|
||||
/// \brief Record codes for each kind of declaration.
|
||||
///
|
||||
/// These constants describe the records that can occur within a
|
||||
/// declarations block (identified by DECLS_BLOCK_ID). Each
|
||||
/// These constants describe the declaration records that can occur within
|
||||
/// a declarations block (identified by DECLS_BLOCK_ID). Each
|
||||
/// constant describes a record for a specific declaration class
|
||||
/// in the AST.
|
||||
enum DeclCode {
|
||||
/// \brief Attributes attached to a declaration.
|
||||
DECL_ATTR = 1,
|
||||
DECL_ATTR = 50,
|
||||
/// \brief A TranslationUnitDecl record.
|
||||
DECL_TRANSLATION_UNIT,
|
||||
/// \brief A TypedefDecl record.
|
||||
@ -529,14 +524,14 @@ namespace clang {
|
||||
/// \brief Record codes for each kind of statement or expression.
|
||||
///
|
||||
/// These constants describe the records that describe statements
|
||||
/// or expressions. These records can occur within either the type
|
||||
/// or declaration blocks, so they begin with record values of
|
||||
/// 50. Each constant describes a record for a specific
|
||||
/// statement or expression class in the AST.
|
||||
/// or expressions. These records occur within type and declarations
|
||||
/// block, so they begin with record values of 100. Each constant
|
||||
/// describes a record for a specific statement or expression class in the
|
||||
/// AST.
|
||||
enum StmtCode {
|
||||
/// \brief A marker record that indicates that we are at the end
|
||||
/// of an expression.
|
||||
STMT_STOP = 50,
|
||||
STMT_STOP = 100,
|
||||
/// \brief A NULL expression.
|
||||
STMT_NULL_PTR,
|
||||
/// \brief A NullStmt record.
|
||||
|
@ -169,6 +169,11 @@ class PCHReader
|
||||
/// \brief The AST context into which we'll read the PCH file.
|
||||
ASTContext *Context;
|
||||
|
||||
/// \brief The PCH stat cache installed by this PCHReader, if any.
|
||||
///
|
||||
/// The dynamic type of this stat cache is always PCHStatCache
|
||||
void *StatCache;
|
||||
|
||||
/// \brief The AST consumer.
|
||||
ASTConsumer *Consumer;
|
||||
|
||||
@ -492,8 +497,8 @@ class PCHReader
|
||||
/// \param isysroot If non-NULL, the system include path specified by the
|
||||
/// user. This is only used with relocatable PCH files. If non-NULL,
|
||||
/// a relocatable PCH file will use the default path "/".
|
||||
PCHReader(SourceManager &SourceMgr, FileManager &FileMgr,
|
||||
Diagnostic &Diags, const char *isysroot = 0);
|
||||
PCHReader(SourceManager &SourceMgr, FileManager &FileMgr,
|
||||
Diagnostic &Diags, const char *isysroot = 0);
|
||||
~PCHReader();
|
||||
|
||||
/// \brief Load the precompiled header designated by the given file
|
||||
@ -513,6 +518,9 @@ class PCHReader
|
||||
/// \brief Sets and initializes the given Context.
|
||||
void InitializeContext(ASTContext &Context);
|
||||
|
||||
/// \brief Retrieve the name of the PCH file
|
||||
const std::string &getFileName() { return FileName; }
|
||||
|
||||
/// \brief Retrieve the name of the original source file name
|
||||
const std::string &getOriginalSourceFile() { return OriginalFileName; }
|
||||
|
||||
@ -534,6 +542,10 @@ class PCHReader
|
||||
/// comments in the source code.
|
||||
virtual void ReadComments(std::vector<SourceRange> &Comments);
|
||||
|
||||
/// \brief Reads a declarator info from the given record.
|
||||
virtual DeclaratorInfo *GetDeclaratorInfo(const RecordData &Record,
|
||||
unsigned &Idx);
|
||||
|
||||
/// \brief Resolve a type ID into a type, potentially building a new
|
||||
/// type.
|
||||
virtual QualType GetType(pch::TypeID ID);
|
||||
|
@ -73,6 +73,33 @@ class PCHWriter {
|
||||
/// \brief The bitstream writer used to emit this precompiled header.
|
||||
llvm::BitstreamWriter &Stream;
|
||||
|
||||
/// \brief Stores a declaration or a type to be written to the PCH file.
|
||||
class DeclOrType {
|
||||
public:
|
||||
DeclOrType(Decl *D) : Stored(D), IsType(false) { }
|
||||
DeclOrType(QualType T) : Stored(T.getAsOpaquePtr()), IsType(true) { }
|
||||
|
||||
bool isType() const { return IsType; }
|
||||
bool isDecl() const { return !IsType; }
|
||||
|
||||
QualType getType() const {
|
||||
assert(isType() && "Not a type!");
|
||||
return QualType::getFromOpaquePtr(Stored);
|
||||
}
|
||||
|
||||
Decl *getDecl() const {
|
||||
assert(isDecl() && "Not a decl!");
|
||||
return static_cast<Decl *>(Stored);
|
||||
}
|
||||
|
||||
private:
|
||||
void *Stored;
|
||||
bool IsType;
|
||||
};
|
||||
|
||||
/// \brief The declarations and types to emit.
|
||||
std::queue<DeclOrType> DeclTypesToEmit;
|
||||
|
||||
/// \brief Map that provides the ID numbers of each declaration within
|
||||
/// the output stream.
|
||||
///
|
||||
@ -85,10 +112,6 @@ class PCHWriter {
|
||||
/// the declaration's ID.
|
||||
std::vector<uint32_t> DeclOffsets;
|
||||
|
||||
/// \brief Queue containing the declarations that we still need to
|
||||
/// emit.
|
||||
std::queue<Decl *> DeclsToEmit;
|
||||
|
||||
/// \brief Map that provides the ID numbers of each type within the
|
||||
/// output stream.
|
||||
///
|
||||
@ -107,10 +130,6 @@ class PCHWriter {
|
||||
/// \brief The type ID that will be assigned to the next new type.
|
||||
pch::TypeID NextTypeID;
|
||||
|
||||
/// \brief Queue containing the types that we still need to
|
||||
/// emit.
|
||||
std::queue<QualType> TypesToEmit;
|
||||
|
||||
/// \brief Map that provides the ID numbers of each identifier in
|
||||
/// the output stream.
|
||||
///
|
||||
@ -189,18 +208,17 @@ class PCHWriter {
|
||||
void WritePreprocessor(const Preprocessor &PP);
|
||||
void WriteComments(ASTContext &Context);
|
||||
void WriteType(QualType T);
|
||||
void WriteTypesBlock(ASTContext &Context);
|
||||
uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC);
|
||||
uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC);
|
||||
|
||||
void WriteDeclsBlock(ASTContext &Context);
|
||||
void WriteMethodPool(Sema &SemaRef);
|
||||
void WriteIdentifierTable(Preprocessor &PP);
|
||||
void WriteAttributeRecord(const Attr *Attr);
|
||||
|
||||
unsigned ParmVarDeclAbbrev;
|
||||
void WriteDeclsBlockAbbrevs();
|
||||
|
||||
void WriteDecl(ASTContext &Context, Decl *D);
|
||||
|
||||
public:
|
||||
/// \brief Create a new precompiled header writer that outputs to
|
||||
/// the given bitstream.
|
||||
@ -254,6 +272,9 @@ class PCHWriter {
|
||||
/// \brief Emit a reference to a type.
|
||||
void AddTypeRef(QualType T, RecordData &Record);
|
||||
|
||||
/// \brief Emits a reference to a declarator info.
|
||||
void AddDeclaratorInfo(DeclaratorInfo *DInfo, RecordData &Record);
|
||||
|
||||
/// \brief Emit a reference to a declaration.
|
||||
void AddDeclRef(const Decl *D, RecordData &Record);
|
||||
|
||||
|
@ -91,7 +91,7 @@ class ASTLocation {
|
||||
ASTLocation(const Decl *parentDecl, TypeLoc tyLoc)
|
||||
: ParentDecl(const_cast<Decl*>(parentDecl), N_Type) {
|
||||
if (tyLoc) {
|
||||
Ty.TyPtr = tyLoc.getSourceType().getAsOpaquePtr();
|
||||
Ty.TyPtr = tyLoc.getType().getAsOpaquePtr();
|
||||
Ty.Data = tyLoc.getOpaqueData();
|
||||
} else
|
||||
ParentDecl.setPointer(0);
|
||||
@ -124,8 +124,8 @@ class ASTLocation {
|
||||
return TypeLoc(QualType::getFromOpaquePtr(Ty.TyPtr), Ty.Data);
|
||||
}
|
||||
|
||||
Decl *dyn_AsDecl() const { return getKind() == N_Decl ? D : 0; }
|
||||
Stmt *dyn_AsStmt() const { return getKind() == N_Stmt ? Stm : 0; }
|
||||
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();
|
||||
}
|
||||
|
@ -14,13 +14,11 @@
|
||||
#ifndef LLVM_CLANG_INDEX_INDEXER_H
|
||||
#define LLVM_CLANG_INDEX_INDEXER_H
|
||||
|
||||
#include "clang/Frontend/TextDiagnosticBuffer.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 "clang/Basic/FileManager.h"
|
||||
#include <map>
|
||||
|
||||
namespace clang {
|
||||
@ -39,16 +37,10 @@ class Indexer : public IndexProvider {
|
||||
typedef std::map<GlobalSelector, TUSetTy> SelMapTy;
|
||||
|
||||
explicit Indexer(Program &prog) :
|
||||
Prog(prog), Diags(&DiagClient) { }
|
||||
Prog(prog) { }
|
||||
|
||||
Program &getProgram() const { return Prog; }
|
||||
|
||||
Diagnostic &getDiagnostics() { return Diags; }
|
||||
const Diagnostic &getDiagnostics() const { return Diags; }
|
||||
|
||||
FileManager &getFileManager() { return FileMgr; }
|
||||
const FileManager &getFileManager() const { return FileMgr; }
|
||||
|
||||
/// \brief Find all Entities and map them to the given translation unit.
|
||||
void IndexAST(TranslationUnit *TU);
|
||||
|
||||
@ -59,9 +51,6 @@ class Indexer : public IndexProvider {
|
||||
|
||||
private:
|
||||
Program &Prog;
|
||||
TextDiagnosticBuffer DiagClient;
|
||||
Diagnostic Diags;
|
||||
FileManager FileMgr;
|
||||
|
||||
MapTy Map;
|
||||
CtxTUMapTy CtxTUMap;
|
||||
|
@ -18,7 +18,8 @@
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class SourceLocation;
|
||||
|
||||
class Decl;
|
||||
|
||||
namespace idx {
|
||||
class ASTLocation;
|
||||
|
||||
@ -26,7 +27,8 @@ namespace idx {
|
||||
///
|
||||
/// \returns the resolved ASTLocation or an invalid ASTLocation if the source
|
||||
/// location could not be resolved.
|
||||
ASTLocation ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc);
|
||||
ASTLocation ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc,
|
||||
Decl *RelativeToDecl = 0);
|
||||
|
||||
} // end namespace idx
|
||||
|
||||
|
@ -1390,6 +1390,34 @@ class Action : public ActionBase {
|
||||
return ExprEmpty();
|
||||
}
|
||||
|
||||
/// \brief Parsed a C++ destructor reference that refers to a type.
|
||||
///
|
||||
/// This action is used when parsing a destructor reference that uses a
|
||||
/// template-id, e.g.,
|
||||
///
|
||||
/// \code
|
||||
/// t->~Tmpl<T1, T2>
|
||||
/// \endcode
|
||||
///
|
||||
/// \param S the scope in which the destructor reference occurs.
|
||||
/// \param Base the base object of the destructor reference expression.
|
||||
/// \param OpLoc the location of the operator ('.' or '->').
|
||||
/// \param OpKind the kind of the destructor reference operator ('.' or '->').
|
||||
/// \param TypeRange the source range that covers the destructor type.
|
||||
/// \param Type the type that is being destroyed.
|
||||
/// \param SS the scope specifier that precedes the destructor name.
|
||||
/// \param HasTrailingLParen whether the destructor name is followed by a '('.
|
||||
virtual OwningExprResult
|
||||
ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
SourceRange TypeRange,
|
||||
TypeTy *Type,
|
||||
const CXXScopeSpec &SS,
|
||||
bool HasTrailingLParen) {
|
||||
return ExprEmpty();
|
||||
}
|
||||
|
||||
/// ActOnOverloadedOperatorReferenceExpr - Parsed an overloaded operator
|
||||
/// reference, for example:
|
||||
///
|
||||
@ -1691,9 +1719,25 @@ class Action : public ActionBase {
|
||||
/// possibly checking well-formedness of the template arguments. It does not
|
||||
/// imply the declaration of any entity.
|
||||
///
|
||||
/// \param SS The scope specifier that may precede the template name.
|
||||
///
|
||||
/// \param Template A template whose specialization results in a
|
||||
/// function or a dependent template.
|
||||
virtual OwningExprResult ActOnTemplateIdExpr(TemplateTy Template,
|
||||
///
|
||||
/// \param TemplateNameLoc The location of the template name.
|
||||
///
|
||||
/// \param LAngleLoc The location of the left angle bracket ('<') that starts
|
||||
/// the template argument list.
|
||||
///
|
||||
/// \param TemplateArgs The template arguments in the template argument list,
|
||||
/// which may be empty.
|
||||
///
|
||||
/// \param TemplateArgLocs The locations of the template arguments.
|
||||
///
|
||||
/// \param RAngleLoc The location of the right angle bracket ('>') that
|
||||
/// closes the template argument list.
|
||||
virtual OwningExprResult ActOnTemplateIdExpr(const CXXScopeSpec &SS,
|
||||
TemplateTy Template,
|
||||
SourceLocation TemplateNameLoc,
|
||||
SourceLocation LAngleLoc,
|
||||
ASTTemplateArgsPtr TemplateArgs,
|
||||
|
@ -40,7 +40,8 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
|
||||
bool FreeMem, unsigned size_reserve) :
|
||||
GlobalNestedNameSpecifier(0), CFConstantStringTypeDecl(0),
|
||||
ObjCFastEnumerationStateTypeDecl(0), FILEDecl(0), jmp_bufDecl(0),
|
||||
sigjmp_bufDecl(0), SourceMgr(SM), LangOpts(LOpts),
|
||||
sigjmp_bufDecl(0), BlockDescriptorType(0), BlockDescriptorExtendedType(0),
|
||||
SourceMgr(SM), LangOpts(LOpts),
|
||||
LoadedExternalComments(false), FreeMemory(FreeMem), Target(t),
|
||||
Idents(idents), Selectors(sels),
|
||||
BuiltinInfo(builtins), ExternalSource(0), PrintingPolicy(LOpts) {
|
||||
@ -554,10 +555,6 @@ ASTContext::getTypeInfo(const Type *T) {
|
||||
assert(false && "Should not see dependent types");
|
||||
break;
|
||||
|
||||
case Type::ObjCProtocolList:
|
||||
assert(false && "Should not see protocol list types");
|
||||
break;
|
||||
|
||||
case Type::FunctionNoProto:
|
||||
case Type::FunctionProto:
|
||||
// GCC extension: alignof(function) = 32 bits
|
||||
@ -571,8 +568,6 @@ ASTContext::getTypeInfo(const Type *T) {
|
||||
Align = getTypeAlign(cast<ArrayType>(T)->getElementType());
|
||||
break;
|
||||
|
||||
case Type::ConstantArrayWithExpr:
|
||||
case Type::ConstantArrayWithoutExpr:
|
||||
case Type::ConstantArray: {
|
||||
const ConstantArrayType *CAT = cast<ConstantArrayType>(T);
|
||||
|
||||
@ -583,14 +578,16 @@ ASTContext::getTypeInfo(const Type *T) {
|
||||
}
|
||||
case Type::ExtVector:
|
||||
case Type::Vector: {
|
||||
std::pair<uint64_t, unsigned> EltInfo =
|
||||
getTypeInfo(cast<VectorType>(T)->getElementType());
|
||||
Width = EltInfo.first*cast<VectorType>(T)->getNumElements();
|
||||
const VectorType *VT = cast<VectorType>(T);
|
||||
std::pair<uint64_t, unsigned> EltInfo = getTypeInfo(VT->getElementType());
|
||||
Width = EltInfo.first*VT->getNumElements();
|
||||
Align = Width;
|
||||
// If the alignment is not a power of 2, round up to the next power of 2.
|
||||
// This happens for non-power-of-2 length vectors.
|
||||
// FIXME: this should probably be a target property.
|
||||
Align = 1 << llvm::Log2_32_Ceil(Align);
|
||||
if (VT->getNumElements() & (VT->getNumElements()-1)) {
|
||||
Align = llvm::NextPowerOf2(Align);
|
||||
Width = llvm::RoundUpToAlignment(Width, Align);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -749,9 +746,13 @@ ASTContext::getTypeInfo(const Type *T) {
|
||||
break;
|
||||
}
|
||||
|
||||
case Type::Elaborated: {
|
||||
return getTypeInfo(cast<ElaboratedType>(T)->getUnderlyingType().getTypePtr());
|
||||
}
|
||||
case Type::SubstTemplateTypeParm:
|
||||
return getTypeInfo(cast<SubstTemplateTypeParmType>(T)->
|
||||
getReplacementType().getTypePtr());
|
||||
|
||||
case Type::Elaborated:
|
||||
return getTypeInfo(cast<ElaboratedType>(T)->getUnderlyingType()
|
||||
.getTypePtr());
|
||||
|
||||
case Type::Typedef: {
|
||||
const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl();
|
||||
@ -940,8 +941,14 @@ void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD,
|
||||
/// \param T the type that will be the basis for type source info. This type
|
||||
/// should refer to how the declarator was written in source code, not to
|
||||
/// what type semantic analysis resolved the declarator to.
|
||||
DeclaratorInfo *ASTContext::CreateDeclaratorInfo(QualType T) {
|
||||
unsigned DataSize = TypeLoc::getFullDataSizeForType(T);
|
||||
DeclaratorInfo *ASTContext::CreateDeclaratorInfo(QualType T,
|
||||
unsigned DataSize) {
|
||||
if (!DataSize)
|
||||
DataSize = TypeLoc::getFullDataSizeForType(T);
|
||||
else
|
||||
assert(DataSize == TypeLoc::getFullDataSizeForType(T) &&
|
||||
"incorrect data size provided to CreateDeclaratorInfo!");
|
||||
|
||||
DeclaratorInfo *DInfo =
|
||||
(DeclaratorInfo*)BumpAlloc.Allocate(sizeof(DeclaratorInfo) + DataSize, 8);
|
||||
new (DInfo) DeclaratorInfo(T);
|
||||
@ -1140,7 +1147,7 @@ QualType ASTContext::getComplexType(QualType T) {
|
||||
// If the pointee type isn't canonical, this won't be a canonical type either,
|
||||
// so fill in the canonical type field.
|
||||
QualType Canonical;
|
||||
if (!T->isCanonical()) {
|
||||
if (!T.isCanonical()) {
|
||||
Canonical = getComplexType(getCanonicalType(T));
|
||||
|
||||
// Get the new insert position for the node we care about.
|
||||
@ -1177,7 +1184,7 @@ QualType ASTContext::getPointerType(QualType T) {
|
||||
// If the pointee type isn't canonical, this won't be a canonical type either,
|
||||
// so fill in the canonical type field.
|
||||
QualType Canonical;
|
||||
if (!T->isCanonical()) {
|
||||
if (!T.isCanonical()) {
|
||||
Canonical = getPointerType(getCanonicalType(T));
|
||||
|
||||
// Get the new insert position for the node we care about.
|
||||
@ -1207,7 +1214,7 @@ QualType ASTContext::getBlockPointerType(QualType T) {
|
||||
// If the block pointee type isn't canonical, this won't be a canonical
|
||||
// type either so fill in the canonical type field.
|
||||
QualType Canonical;
|
||||
if (!T->isCanonical()) {
|
||||
if (!T.isCanonical()) {
|
||||
Canonical = getBlockPointerType(getCanonicalType(T));
|
||||
|
||||
// Get the new insert position for the node we care about.
|
||||
@ -1224,22 +1231,25 @@ QualType ASTContext::getBlockPointerType(QualType T) {
|
||||
|
||||
/// getLValueReferenceType - Return the uniqued reference to the type for an
|
||||
/// lvalue reference to the specified type.
|
||||
QualType ASTContext::getLValueReferenceType(QualType T) {
|
||||
QualType ASTContext::getLValueReferenceType(QualType T, bool SpelledAsLValue) {
|
||||
// Unique pointers, to guarantee there is only one pointer of a particular
|
||||
// structure.
|
||||
llvm::FoldingSetNodeID ID;
|
||||
ReferenceType::Profile(ID, T);
|
||||
ReferenceType::Profile(ID, T, SpelledAsLValue);
|
||||
|
||||
void *InsertPos = 0;
|
||||
if (LValueReferenceType *RT =
|
||||
LValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos))
|
||||
return QualType(RT, 0);
|
||||
|
||||
const ReferenceType *InnerRef = T->getAs<ReferenceType>();
|
||||
|
||||
// If the referencee type isn't canonical, this won't be a canonical type
|
||||
// either, so fill in the canonical type field.
|
||||
QualType Canonical;
|
||||
if (!T->isCanonical()) {
|
||||
Canonical = getLValueReferenceType(getCanonicalType(T));
|
||||
if (!SpelledAsLValue || InnerRef || !T.isCanonical()) {
|
||||
QualType PointeeType = (InnerRef ? InnerRef->getPointeeType() : T);
|
||||
Canonical = getLValueReferenceType(getCanonicalType(PointeeType));
|
||||
|
||||
// Get the new insert position for the node we care about.
|
||||
LValueReferenceType *NewIP =
|
||||
@ -1248,9 +1258,11 @@ QualType ASTContext::getLValueReferenceType(QualType T) {
|
||||
}
|
||||
|
||||
LValueReferenceType *New
|
||||
= new (*this, TypeAlignment) LValueReferenceType(T, Canonical);
|
||||
= new (*this, TypeAlignment) LValueReferenceType(T, Canonical,
|
||||
SpelledAsLValue);
|
||||
Types.push_back(New);
|
||||
LValueReferenceTypes.InsertNode(New, InsertPos);
|
||||
|
||||
return QualType(New, 0);
|
||||
}
|
||||
|
||||
@ -1260,18 +1272,21 @@ QualType ASTContext::getRValueReferenceType(QualType T) {
|
||||
// Unique pointers, to guarantee there is only one pointer of a particular
|
||||
// structure.
|
||||
llvm::FoldingSetNodeID ID;
|
||||
ReferenceType::Profile(ID, T);
|
||||
ReferenceType::Profile(ID, T, false);
|
||||
|
||||
void *InsertPos = 0;
|
||||
if (RValueReferenceType *RT =
|
||||
RValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos))
|
||||
return QualType(RT, 0);
|
||||
|
||||
const ReferenceType *InnerRef = T->getAs<ReferenceType>();
|
||||
|
||||
// If the referencee type isn't canonical, this won't be a canonical type
|
||||
// either, so fill in the canonical type field.
|
||||
QualType Canonical;
|
||||
if (!T->isCanonical()) {
|
||||
Canonical = getRValueReferenceType(getCanonicalType(T));
|
||||
if (InnerRef || !T.isCanonical()) {
|
||||
QualType PointeeType = (InnerRef ? InnerRef->getPointeeType() : T);
|
||||
Canonical = getRValueReferenceType(getCanonicalType(PointeeType));
|
||||
|
||||
// Get the new insert position for the node we care about.
|
||||
RValueReferenceType *NewIP =
|
||||
@ -1302,7 +1317,7 @@ QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) {
|
||||
// If the pointee or class type isn't canonical, this won't be a canonical
|
||||
// type either, so fill in the canonical type field.
|
||||
QualType Canonical;
|
||||
if (!T->isCanonical()) {
|
||||
if (!T.isCanonical()) {
|
||||
Canonical = getMemberPointerType(getCanonicalType(T),getCanonicalType(Cls));
|
||||
|
||||
// Get the new insert position for the node we care about.
|
||||
@ -1342,7 +1357,7 @@ QualType ASTContext::getConstantArrayType(QualType EltTy,
|
||||
// If the element type isn't canonical, this won't be a canonical type either,
|
||||
// so fill in the canonical type field.
|
||||
QualType Canonical;
|
||||
if (!EltTy->isCanonical()) {
|
||||
if (!EltTy.isCanonical()) {
|
||||
Canonical = getConstantArrayType(getCanonicalType(EltTy), ArySize,
|
||||
ASM, EltTypeQuals);
|
||||
// Get the new insert position for the node we care about.
|
||||
@ -1358,53 +1373,6 @@ QualType ASTContext::getConstantArrayType(QualType EltTy,
|
||||
return QualType(New, 0);
|
||||
}
|
||||
|
||||
/// getConstantArrayWithExprType - Return a reference to the type for
|
||||
/// an array of the specified element type.
|
||||
QualType
|
||||
ASTContext::getConstantArrayWithExprType(QualType EltTy,
|
||||
const llvm::APInt &ArySizeIn,
|
||||
Expr *ArySizeExpr,
|
||||
ArrayType::ArraySizeModifier ASM,
|
||||
unsigned EltTypeQuals,
|
||||
SourceRange Brackets) {
|
||||
// Convert the array size into a canonical width matching the pointer
|
||||
// size for the target.
|
||||
llvm::APInt ArySize(ArySizeIn);
|
||||
ArySize.zextOrTrunc(Target.getPointerWidth(EltTy.getAddressSpace()));
|
||||
|
||||
// Compute the canonical ConstantArrayType.
|
||||
QualType Canonical = getConstantArrayType(getCanonicalType(EltTy),
|
||||
ArySize, ASM, EltTypeQuals);
|
||||
// Since we don't unique expressions, it isn't possible to unique VLA's
|
||||
// that have an expression provided for their size.
|
||||
ConstantArrayWithExprType *New = new(*this, TypeAlignment)
|
||||
ConstantArrayWithExprType(EltTy, Canonical, ArySize, ArySizeExpr,
|
||||
ASM, EltTypeQuals, Brackets);
|
||||
Types.push_back(New);
|
||||
return QualType(New, 0);
|
||||
}
|
||||
|
||||
/// getConstantArrayWithoutExprType - Return a reference to the type for
|
||||
/// an array of the specified element type.
|
||||
QualType
|
||||
ASTContext::getConstantArrayWithoutExprType(QualType EltTy,
|
||||
const llvm::APInt &ArySizeIn,
|
||||
ArrayType::ArraySizeModifier ASM,
|
||||
unsigned EltTypeQuals) {
|
||||
// Convert the array size into a canonical width matching the pointer
|
||||
// size for the target.
|
||||
llvm::APInt ArySize(ArySizeIn);
|
||||
ArySize.zextOrTrunc(Target.getPointerWidth(EltTy.getAddressSpace()));
|
||||
|
||||
// Compute the canonical ConstantArrayType.
|
||||
QualType Canonical = getConstantArrayType(getCanonicalType(EltTy),
|
||||
ArySize, ASM, EltTypeQuals);
|
||||
ConstantArrayWithoutExprType *New = new(*this, TypeAlignment)
|
||||
ConstantArrayWithoutExprType(EltTy, Canonical, ArySize, ASM, EltTypeQuals);
|
||||
Types.push_back(New);
|
||||
return QualType(New, 0);
|
||||
}
|
||||
|
||||
/// getVariableArrayType - Returns a non-unique reference to the type for a
|
||||
/// variable array of the specified element type.
|
||||
QualType ASTContext::getVariableArrayType(QualType EltTy,
|
||||
@ -1484,7 +1452,7 @@ QualType ASTContext::getIncompleteArrayType(QualType EltTy,
|
||||
// either, so fill in the canonical type field.
|
||||
QualType Canonical;
|
||||
|
||||
if (!EltTy->isCanonical()) {
|
||||
if (!EltTy.isCanonical()) {
|
||||
Canonical = getIncompleteArrayType(getCanonicalType(EltTy),
|
||||
ASM, EltTypeQuals);
|
||||
|
||||
@ -1520,7 +1488,7 @@ QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts) {
|
||||
// If the element type isn't canonical, this won't be a canonical type either,
|
||||
// so fill in the canonical type field.
|
||||
QualType Canonical;
|
||||
if (!vecType->isCanonical()) {
|
||||
if (!vecType.isCanonical()) {
|
||||
Canonical = getVectorType(getCanonicalType(vecType), NumElts);
|
||||
|
||||
// Get the new insert position for the node we care about.
|
||||
@ -1552,7 +1520,7 @@ QualType ASTContext::getExtVectorType(QualType vecType, unsigned NumElts) {
|
||||
// If the element type isn't canonical, this won't be a canonical type either,
|
||||
// so fill in the canonical type field.
|
||||
QualType Canonical;
|
||||
if (!vecType->isCanonical()) {
|
||||
if (!vecType.isCanonical()) {
|
||||
Canonical = getExtVectorType(getCanonicalType(vecType), NumElts);
|
||||
|
||||
// Get the new insert position for the node we care about.
|
||||
@ -1616,7 +1584,7 @@ QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, bool NoReturn) {
|
||||
return QualType(FT, 0);
|
||||
|
||||
QualType Canonical;
|
||||
if (!ResultTy->isCanonical()) {
|
||||
if (!ResultTy.isCanonical()) {
|
||||
Canonical = getFunctionNoProtoType(getCanonicalType(ResultTy), NoReturn);
|
||||
|
||||
// Get the new insert position for the node we care about.
|
||||
@ -1639,12 +1607,6 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,
|
||||
unsigned TypeQuals, bool hasExceptionSpec,
|
||||
bool hasAnyExceptionSpec, unsigned NumExs,
|
||||
const QualType *ExArray, bool NoReturn) {
|
||||
if (LangOpts.CPlusPlus) {
|
||||
for (unsigned i = 0; i != NumArgs; ++i)
|
||||
assert(!ArgArray[i].hasQualifiers() &&
|
||||
"C++ arguments can't have toplevel qualifiers!");
|
||||
}
|
||||
|
||||
// Unique functions, to guarantee there is only one function of a particular
|
||||
// structure.
|
||||
llvm::FoldingSetNodeID ID;
|
||||
@ -1658,11 +1620,9 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,
|
||||
return QualType(FTP, 0);
|
||||
|
||||
// Determine whether the type being created is already canonical or not.
|
||||
bool isCanonical = ResultTy->isCanonical();
|
||||
if (hasExceptionSpec)
|
||||
isCanonical = false;
|
||||
bool isCanonical = !hasExceptionSpec && ResultTy.isCanonical();
|
||||
for (unsigned i = 0; i != NumArgs && isCanonical; ++i)
|
||||
if (!ArgArray[i]->isCanonical())
|
||||
if (!ArgArray[i].isCanonicalAsParam())
|
||||
isCanonical = false;
|
||||
|
||||
// If this type isn't canonical, get the canonical version of it.
|
||||
@ -1672,7 +1632,7 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,
|
||||
llvm::SmallVector<QualType, 16> CanonicalArgs;
|
||||
CanonicalArgs.reserve(NumArgs);
|
||||
for (unsigned i = 0; i != NumArgs; ++i)
|
||||
CanonicalArgs.push_back(getCanonicalType(ArgArray[i]));
|
||||
CanonicalArgs.push_back(getCanonicalParamType(ArgArray[i]));
|
||||
|
||||
Canonical = getFunctionType(getCanonicalType(ResultTy),
|
||||
CanonicalArgs.data(), NumArgs,
|
||||
@ -1743,6 +1703,29 @@ QualType ASTContext::getTypedefType(TypedefDecl *Decl) {
|
||||
return QualType(Decl->TypeForDecl, 0);
|
||||
}
|
||||
|
||||
/// \brief Retrieve a substitution-result type.
|
||||
QualType
|
||||
ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm,
|
||||
QualType Replacement) {
|
||||
assert(Replacement.isCanonical()
|
||||
&& "replacement types must always be canonical");
|
||||
|
||||
llvm::FoldingSetNodeID ID;
|
||||
SubstTemplateTypeParmType::Profile(ID, Parm, Replacement);
|
||||
void *InsertPos = 0;
|
||||
SubstTemplateTypeParmType *SubstParm
|
||||
= SubstTemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos);
|
||||
|
||||
if (!SubstParm) {
|
||||
SubstParm = new (*this, TypeAlignment)
|
||||
SubstTemplateTypeParmType(Parm, Replacement);
|
||||
Types.push_back(SubstParm);
|
||||
SubstTemplateTypeParmTypes.InsertNode(SubstParm, InsertPos);
|
||||
}
|
||||
|
||||
return QualType(SubstParm, 0);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the template type parameter type for a template
|
||||
/// parameter or parameter pack with the given depth, index, and (optionally)
|
||||
/// name.
|
||||
@ -1933,7 +1916,17 @@ static bool CmpProtocolNames(const ObjCProtocolDecl *LHS,
|
||||
return LHS->getDeclName() < RHS->getDeclName();
|
||||
}
|
||||
|
||||
static void SortAndUniqueProtocols(ObjCProtocolDecl **&Protocols,
|
||||
static bool areSortedAndUniqued(ObjCProtocolDecl **Protocols,
|
||||
unsigned NumProtocols) {
|
||||
if (NumProtocols == 0) return true;
|
||||
|
||||
for (unsigned i = 1; i != NumProtocols; ++i)
|
||||
if (!CmpProtocolNames(Protocols[i-1], Protocols[i]))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void SortAndUniqueProtocols(ObjCProtocolDecl **Protocols,
|
||||
unsigned &NumProtocols) {
|
||||
ObjCProtocolDecl **ProtocolsEnd = Protocols+NumProtocols;
|
||||
|
||||
@ -1950,10 +1943,6 @@ static void SortAndUniqueProtocols(ObjCProtocolDecl **&Protocols,
|
||||
QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT,
|
||||
ObjCProtocolDecl **Protocols,
|
||||
unsigned NumProtocols) {
|
||||
// Sort the protocol list alphabetically to canonicalize it.
|
||||
if (NumProtocols)
|
||||
SortAndUniqueProtocols(Protocols, NumProtocols);
|
||||
|
||||
llvm::FoldingSetNodeID ID;
|
||||
ObjCObjectPointerType::Profile(ID, InterfaceT, Protocols, NumProtocols);
|
||||
|
||||
@ -1962,9 +1951,31 @@ QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT,
|
||||
ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
|
||||
return QualType(QT, 0);
|
||||
|
||||
// Sort the protocol list alphabetically to canonicalize it.
|
||||
QualType Canonical;
|
||||
if (!InterfaceT.isCanonical() ||
|
||||
!areSortedAndUniqued(Protocols, NumProtocols)) {
|
||||
if (!areSortedAndUniqued(Protocols, NumProtocols)) {
|
||||
llvm::SmallVector<ObjCProtocolDecl*, 8> Sorted(NumProtocols);
|
||||
unsigned UniqueCount = NumProtocols;
|
||||
|
||||
std::copy(Protocols, Protocols + NumProtocols, Sorted.begin());
|
||||
SortAndUniqueProtocols(&Sorted[0], UniqueCount);
|
||||
|
||||
Canonical = getObjCObjectPointerType(getCanonicalType(InterfaceT),
|
||||
&Sorted[0], UniqueCount);
|
||||
} else {
|
||||
Canonical = getObjCObjectPointerType(getCanonicalType(InterfaceT),
|
||||
Protocols, NumProtocols);
|
||||
}
|
||||
|
||||
// Regenerate InsertPos.
|
||||
ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
|
||||
}
|
||||
|
||||
// No Match;
|
||||
ObjCObjectPointerType *QType = new (*this, TypeAlignment)
|
||||
ObjCObjectPointerType(InterfaceT, Protocols, NumProtocols);
|
||||
ObjCObjectPointerType(Canonical, InterfaceT, Protocols, NumProtocols);
|
||||
|
||||
Types.push_back(QType);
|
||||
ObjCObjectPointerTypes.InsertNode(QType, InsertPos);
|
||||
@ -1975,10 +1986,6 @@ QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT,
|
||||
/// specified ObjC interface decl. The list of protocols is optional.
|
||||
QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
|
||||
ObjCProtocolDecl **Protocols, unsigned NumProtocols) {
|
||||
if (NumProtocols)
|
||||
// Sort the protocol list alphabetically to canonicalize it.
|
||||
SortAndUniqueProtocols(Protocols, NumProtocols);
|
||||
|
||||
llvm::FoldingSetNodeID ID;
|
||||
ObjCInterfaceType::Profile(ID, Decl, Protocols, NumProtocols);
|
||||
|
||||
@ -1987,34 +1994,29 @@ QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
|
||||
ObjCInterfaceTypes.FindNodeOrInsertPos(ID, InsertPos))
|
||||
return QualType(QT, 0);
|
||||
|
||||
// No Match;
|
||||
// Sort the protocol list alphabetically to canonicalize it.
|
||||
QualType Canonical;
|
||||
if (NumProtocols && !areSortedAndUniqued(Protocols, NumProtocols)) {
|
||||
llvm::SmallVector<ObjCProtocolDecl*, 8> Sorted(NumProtocols);
|
||||
std::copy(Protocols, Protocols + NumProtocols, Sorted.begin());
|
||||
|
||||
unsigned UniqueCount = NumProtocols;
|
||||
SortAndUniqueProtocols(&Sorted[0], UniqueCount);
|
||||
|
||||
Canonical = getObjCInterfaceType(Decl, &Sorted[0], UniqueCount);
|
||||
|
||||
ObjCInterfaceTypes.FindNodeOrInsertPos(ID, InsertPos);
|
||||
}
|
||||
|
||||
ObjCInterfaceType *QType = new (*this, TypeAlignment)
|
||||
ObjCInterfaceType(const_cast<ObjCInterfaceDecl*>(Decl),
|
||||
ObjCInterfaceType(Canonical, const_cast<ObjCInterfaceDecl*>(Decl),
|
||||
Protocols, NumProtocols);
|
||||
|
||||
Types.push_back(QType);
|
||||
ObjCInterfaceTypes.InsertNode(QType, InsertPos);
|
||||
return QualType(QType, 0);
|
||||
}
|
||||
|
||||
QualType ASTContext::getObjCProtocolListType(QualType T,
|
||||
ObjCProtocolDecl **Protocols,
|
||||
unsigned NumProtocols) {
|
||||
llvm::FoldingSetNodeID ID;
|
||||
ObjCProtocolListType::Profile(ID, T, Protocols, NumProtocols);
|
||||
|
||||
void *InsertPos = 0;
|
||||
if (ObjCProtocolListType *QT =
|
||||
ObjCProtocolListTypes.FindNodeOrInsertPos(ID, InsertPos))
|
||||
return QualType(QT, 0);
|
||||
|
||||
// No Match;
|
||||
ObjCProtocolListType *QType = new (*this, TypeAlignment)
|
||||
ObjCProtocolListType(T, Protocols, NumProtocols);
|
||||
Types.push_back(QType);
|
||||
ObjCProtocolListTypes.InsertNode(QType, InsertPos);
|
||||
return QualType(QType, 0);
|
||||
}
|
||||
|
||||
/// getTypeOfExprType - Unlike many "get<Type>" functions, we can't unique
|
||||
/// TypeOfExprType AST's (since expression's are never shared). For example,
|
||||
/// multiple declarations that refer to "typeof(x)" all contain different
|
||||
@ -2168,6 +2170,24 @@ QualType ASTContext::getPointerDiffType() const {
|
||||
// Type Operators
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
CanQualType ASTContext::getCanonicalParamType(QualType T) {
|
||||
// Push qualifiers into arrays, and then discard any remaining
|
||||
// qualifiers.
|
||||
T = getCanonicalType(T);
|
||||
const Type *Ty = T.getTypePtr();
|
||||
|
||||
QualType Result;
|
||||
if (isa<ArrayType>(Ty)) {
|
||||
Result = getArrayDecayedType(QualType(Ty,0));
|
||||
} else if (isa<FunctionType>(Ty)) {
|
||||
Result = getPointerType(QualType(Ty, 0));
|
||||
} else {
|
||||
Result = QualType(Ty, 0);
|
||||
}
|
||||
|
||||
return CanQualType::CreateUnsafe(Result);
|
||||
}
|
||||
|
||||
/// getCanonicalType - Return the canonical (structural) type corresponding to
|
||||
/// the specified potentially non-canonical type. The non-canonical version
|
||||
/// of a type may have many "decorated" versions of types. Decorators can
|
||||
@ -2512,7 +2532,7 @@ int ASTContext::getFloatingTypeOrder(QualType LHS, QualType RHS) {
|
||||
/// routine will assert if passed a built-in type that isn't an integer or enum,
|
||||
/// or if it is not canonicalized.
|
||||
unsigned ASTContext::getIntegerRank(Type *T) {
|
||||
assert(T->isCanonical() && "T should be canonicalized");
|
||||
assert(T->isCanonicalUnqualified() && "T should be canonicalized");
|
||||
if (EnumType* ET = dyn_cast<EnumType>(T))
|
||||
T = ET->getDecl()->getIntegerType().getTypePtr();
|
||||
|
||||
@ -2713,6 +2733,226 @@ QualType ASTContext::getObjCFastEnumerationStateType() {
|
||||
return getTagDeclType(ObjCFastEnumerationStateTypeDecl);
|
||||
}
|
||||
|
||||
QualType ASTContext::getBlockDescriptorType() {
|
||||
if (BlockDescriptorType)
|
||||
return getTagDeclType(BlockDescriptorType);
|
||||
|
||||
RecordDecl *T;
|
||||
// FIXME: Needs the FlagAppleBlock bit.
|
||||
T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
|
||||
&Idents.get("__block_descriptor"));
|
||||
|
||||
QualType FieldTypes[] = {
|
||||
UnsignedLongTy,
|
||||
UnsignedLongTy,
|
||||
};
|
||||
|
||||
const char *FieldNames[] = {
|
||||
"reserved",
|
||||
"Size"
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < 2; ++i) {
|
||||
FieldDecl *Field = FieldDecl::Create(*this,
|
||||
T,
|
||||
SourceLocation(),
|
||||
&Idents.get(FieldNames[i]),
|
||||
FieldTypes[i], /*DInfo=*/0,
|
||||
/*BitWidth=*/0,
|
||||
/*Mutable=*/false);
|
||||
T->addDecl(Field);
|
||||
}
|
||||
|
||||
T->completeDefinition(*this);
|
||||
|
||||
BlockDescriptorType = T;
|
||||
|
||||
return getTagDeclType(BlockDescriptorType);
|
||||
}
|
||||
|
||||
void ASTContext::setBlockDescriptorType(QualType T) {
|
||||
const RecordType *Rec = T->getAs<RecordType>();
|
||||
assert(Rec && "Invalid BlockDescriptorType");
|
||||
BlockDescriptorType = Rec->getDecl();
|
||||
}
|
||||
|
||||
QualType ASTContext::getBlockDescriptorExtendedType() {
|
||||
if (BlockDescriptorExtendedType)
|
||||
return getTagDeclType(BlockDescriptorExtendedType);
|
||||
|
||||
RecordDecl *T;
|
||||
// FIXME: Needs the FlagAppleBlock bit.
|
||||
T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
|
||||
&Idents.get("__block_descriptor_withcopydispose"));
|
||||
|
||||
QualType FieldTypes[] = {
|
||||
UnsignedLongTy,
|
||||
UnsignedLongTy,
|
||||
getPointerType(VoidPtrTy),
|
||||
getPointerType(VoidPtrTy)
|
||||
};
|
||||
|
||||
const char *FieldNames[] = {
|
||||
"reserved",
|
||||
"Size",
|
||||
"CopyFuncPtr",
|
||||
"DestroyFuncPtr"
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
FieldDecl *Field = FieldDecl::Create(*this,
|
||||
T,
|
||||
SourceLocation(),
|
||||
&Idents.get(FieldNames[i]),
|
||||
FieldTypes[i], /*DInfo=*/0,
|
||||
/*BitWidth=*/0,
|
||||
/*Mutable=*/false);
|
||||
T->addDecl(Field);
|
||||
}
|
||||
|
||||
T->completeDefinition(*this);
|
||||
|
||||
BlockDescriptorExtendedType = T;
|
||||
|
||||
return getTagDeclType(BlockDescriptorExtendedType);
|
||||
}
|
||||
|
||||
void ASTContext::setBlockDescriptorExtendedType(QualType T) {
|
||||
const RecordType *Rec = T->getAs<RecordType>();
|
||||
assert(Rec && "Invalid BlockDescriptorType");
|
||||
BlockDescriptorExtendedType = Rec->getDecl();
|
||||
}
|
||||
|
||||
bool ASTContext::BlockRequiresCopying(QualType Ty) {
|
||||
if (Ty->isBlockPointerType())
|
||||
return true;
|
||||
if (isObjCNSObjectType(Ty))
|
||||
return true;
|
||||
if (Ty->isObjCObjectPointerType())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
QualType ASTContext::BuildByRefType(const char *DeclName, QualType Ty) {
|
||||
// type = struct __Block_byref_1_X {
|
||||
// void *__isa;
|
||||
// struct __Block_byref_1_X *__forwarding;
|
||||
// unsigned int __flags;
|
||||
// unsigned int __size;
|
||||
// void *__copy_helper; // as needed
|
||||
// void *__destroy_help // as needed
|
||||
// int X;
|
||||
// } *
|
||||
|
||||
bool HasCopyAndDispose = BlockRequiresCopying(Ty);
|
||||
|
||||
// FIXME: Move up
|
||||
static int UniqueBlockByRefTypeID = 0;
|
||||
char Name[36];
|
||||
sprintf(Name, "__Block_byref_%d_%s", ++UniqueBlockByRefTypeID, DeclName);
|
||||
RecordDecl *T;
|
||||
T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
|
||||
&Idents.get(Name));
|
||||
T->startDefinition();
|
||||
QualType Int32Ty = IntTy;
|
||||
assert(getIntWidth(IntTy) == 32 && "non-32bit int not supported");
|
||||
QualType FieldTypes[] = {
|
||||
getPointerType(VoidPtrTy),
|
||||
getPointerType(getTagDeclType(T)),
|
||||
Int32Ty,
|
||||
Int32Ty,
|
||||
getPointerType(VoidPtrTy),
|
||||
getPointerType(VoidPtrTy),
|
||||
Ty
|
||||
};
|
||||
|
||||
const char *FieldNames[] = {
|
||||
"__isa",
|
||||
"__forwarding",
|
||||
"__flags",
|
||||
"__size",
|
||||
"__copy_helper",
|
||||
"__destroy_helper",
|
||||
DeclName,
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < 7; ++i) {
|
||||
if (!HasCopyAndDispose && i >=4 && i <= 5)
|
||||
continue;
|
||||
FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(),
|
||||
&Idents.get(FieldNames[i]),
|
||||
FieldTypes[i], /*DInfo=*/0,
|
||||
/*BitWidth=*/0, /*Mutable=*/false);
|
||||
T->addDecl(Field);
|
||||
}
|
||||
|
||||
T->completeDefinition(*this);
|
||||
|
||||
return getPointerType(getTagDeclType(T));
|
||||
}
|
||||
|
||||
|
||||
QualType ASTContext::getBlockParmType(
|
||||
bool BlockHasCopyDispose,
|
||||
llvm::SmallVector<const Expr *, 8> &BlockDeclRefDecls) {
|
||||
// FIXME: Move up
|
||||
static int UniqueBlockParmTypeID = 0;
|
||||
char Name[36];
|
||||
sprintf(Name, "__block_literal_%u", ++UniqueBlockParmTypeID);
|
||||
RecordDecl *T;
|
||||
T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
|
||||
&Idents.get(Name));
|
||||
QualType FieldTypes[] = {
|
||||
getPointerType(VoidPtrTy),
|
||||
IntTy,
|
||||
IntTy,
|
||||
getPointerType(VoidPtrTy),
|
||||
(BlockHasCopyDispose ?
|
||||
getPointerType(getBlockDescriptorExtendedType()) :
|
||||
getPointerType(getBlockDescriptorType()))
|
||||
};
|
||||
|
||||
const char *FieldNames[] = {
|
||||
"__isa",
|
||||
"__flags",
|
||||
"__reserved",
|
||||
"__FuncPtr",
|
||||
"__descriptor"
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < 5; ++i) {
|
||||
FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(),
|
||||
&Idents.get(FieldNames[i]),
|
||||
FieldTypes[i], /*DInfo=*/0,
|
||||
/*BitWidth=*/0, /*Mutable=*/false);
|
||||
T->addDecl(Field);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < BlockDeclRefDecls.size(); ++i) {
|
||||
const Expr *E = BlockDeclRefDecls[i];
|
||||
const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E);
|
||||
clang::IdentifierInfo *Name = 0;
|
||||
if (BDRE) {
|
||||
const ValueDecl *D = BDRE->getDecl();
|
||||
Name = &Idents.get(D->getName());
|
||||
}
|
||||
QualType FieldType = E->getType();
|
||||
|
||||
if (BDRE && BDRE->isByRef())
|
||||
FieldType = BuildByRefType(BDRE->getDecl()->getNameAsCString(),
|
||||
FieldType);
|
||||
|
||||
FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(),
|
||||
Name, FieldType, /*DInfo=*/0,
|
||||
/*BitWidth=*/0, /*Mutable=*/false);
|
||||
T->addDecl(Field);
|
||||
}
|
||||
|
||||
T->completeDefinition(*this);
|
||||
|
||||
return getPointerType(getTagDeclType(T));
|
||||
}
|
||||
|
||||
void ASTContext::setObjCFastEnumerationStateType(QualType T) {
|
||||
const RecordType *Rec = T->getAs<RecordType>();
|
||||
assert(Rec && "Invalid ObjCFAstEnumerationStateType");
|
||||
@ -2945,6 +3185,7 @@ static void EncodeBitField(const ASTContext *Context, std::string& S,
|
||||
S += llvm::utostr(N);
|
||||
}
|
||||
|
||||
// FIXME: Use SmallString for accumulating string.
|
||||
void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
|
||||
bool ExpandPointedToStructures,
|
||||
bool ExpandStructures,
|
||||
@ -3420,7 +3661,7 @@ Qualifiers::GC ASTContext::getObjCGCAttrKind(const QualType &Ty) const {
|
||||
/// compatible.
|
||||
static bool areCompatVectorTypes(const VectorType *LHS,
|
||||
const VectorType *RHS) {
|
||||
assert(LHS->isCanonical() && RHS->isCanonical());
|
||||
assert(LHS->isCanonicalUnqualified() && RHS->isCanonicalUnqualified());
|
||||
return LHS->getElementType() == RHS->getElementType() &&
|
||||
LHS->getNumElements() == RHS->getNumElements();
|
||||
}
|
||||
@ -3979,7 +4220,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
|
||||
unsigned ASTContext::getIntWidth(QualType T) {
|
||||
if (T == BoolTy)
|
||||
return 1;
|
||||
if (FixedWidthIntType* FWIT = dyn_cast<FixedWidthIntType>(T)) {
|
||||
if (FixedWidthIntType *FWIT = dyn_cast<FixedWidthIntType>(T)) {
|
||||
return FWIT->getWidth();
|
||||
}
|
||||
// For builtin types, just use the standard type sizing method
|
||||
@ -3988,10 +4229,18 @@ unsigned ASTContext::getIntWidth(QualType T) {
|
||||
|
||||
QualType ASTContext::getCorrespondingUnsignedType(QualType T) {
|
||||
assert(T->isSignedIntegerType() && "Unexpected type");
|
||||
if (const EnumType* ETy = T->getAs<EnumType>())
|
||||
|
||||
// Turn <4 x signed int> -> <4 x unsigned int>
|
||||
if (const VectorType *VTy = T->getAs<VectorType>())
|
||||
return getVectorType(getCorrespondingUnsignedType(VTy->getElementType()),
|
||||
VTy->getNumElements());
|
||||
|
||||
// For enums, we return the unsigned version of the base type.
|
||||
if (const EnumType *ETy = T->getAs<EnumType>())
|
||||
T = ETy->getDecl()->getIntegerType();
|
||||
const BuiltinType* BTy = T->getAs<BuiltinType>();
|
||||
assert (BTy && "Unexpected signed integer type");
|
||||
|
||||
const BuiltinType *BTy = T->getAs<BuiltinType>();
|
||||
assert(BTy && "Unexpected signed integer type");
|
||||
switch (BTy->getKind()) {
|
||||
case BuiltinType::Char_S:
|
||||
case BuiltinType::SChar:
|
||||
|
@ -50,7 +50,7 @@ CXXBasePaths::decl_iterator CXXBasePaths::found_decls_end() {
|
||||
/// different base class subobjects of the same type. BaseType must be
|
||||
/// an unqualified, canonical class type.
|
||||
bool CXXBasePaths::isAmbiguous(QualType BaseType) {
|
||||
assert(BaseType->isCanonical() && "Base type must be the canonical type");
|
||||
assert(BaseType.isCanonical() && "Base type must be the canonical type");
|
||||
assert(BaseType.hasQualifiers() == 0 && "Base type must be unqualified");
|
||||
std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType];
|
||||
return Subobjects.second + (Subobjects.first? 1 : 0) > 1;
|
||||
|
@ -231,6 +231,8 @@ std::string NamedDecl::getQualifiedNameAsString() const {
|
||||
}
|
||||
|
||||
std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const {
|
||||
// FIXME: Collect contexts, then accumulate names to avoid unnecessary
|
||||
// std::string thrashing.
|
||||
std::vector<std::string> Names;
|
||||
std::string QualName;
|
||||
const DeclContext *Ctx = getDeclContext();
|
||||
@ -252,7 +254,7 @@ std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const {
|
||||
TemplateArgs.getFlatArgumentList(),
|
||||
TemplateArgs.flat_size(),
|
||||
P);
|
||||
Names.push_back(Spec->getIdentifier()->getName() + TemplateArgsStr);
|
||||
Names.push_back(Spec->getIdentifier()->getNameStart() + TemplateArgsStr);
|
||||
} else if (const NamedDecl *ND = dyn_cast<NamedDecl>(Ctx))
|
||||
Names.push_back(ND->getNameAsString());
|
||||
else
|
||||
@ -336,8 +338,15 @@ NamedDecl *NamedDecl::getUnderlyingDecl() {
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const {
|
||||
if (DeclInfo)
|
||||
return DeclInfo->getTypeLoc().getTypeSpecRange().getBegin();
|
||||
if (DeclInfo) {
|
||||
TypeLoc TL = DeclInfo->getTypeLoc();
|
||||
while (true) {
|
||||
TypeLoc NextTL = TL.getNextTypeLoc();
|
||||
if (!NextTL)
|
||||
return TL.getSourceRange().getBegin();
|
||||
TL = NextTL;
|
||||
}
|
||||
}
|
||||
return SourceLocation();
|
||||
}
|
||||
|
||||
@ -408,10 +417,15 @@ MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() const {
|
||||
return getASTContext().getInstantiatedFromStaticDataMember(this);
|
||||
}
|
||||
|
||||
void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
|
||||
void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
|
||||
SourceLocation PointOfInstantiation) {
|
||||
MemberSpecializationInfo *MSI = getMemberSpecializationInfo();
|
||||
assert(MSI && "Not an instantiated static data member?");
|
||||
MSI->setTemplateSpecializationKind(TSK);
|
||||
if (TSK != TSK_ExplicitSpecialization &&
|
||||
PointOfInstantiation.isValid() &&
|
||||
MSI->getPointOfInstantiation().isInvalid())
|
||||
MSI->setPointOfInstantiation(PointOfInstantiation);
|
||||
}
|
||||
|
||||
bool VarDecl::isTentativeDefinition(ASTContext &Context) const {
|
||||
@ -812,16 +826,37 @@ TemplateSpecializationKind FunctionDecl::getTemplateSpecializationKind() const {
|
||||
}
|
||||
|
||||
void
|
||||
FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
|
||||
FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
|
||||
SourceLocation PointOfInstantiation) {
|
||||
if (FunctionTemplateSpecializationInfo *FTSInfo
|
||||
= TemplateOrSpecialization.dyn_cast<
|
||||
FunctionTemplateSpecializationInfo*>()) {
|
||||
FTSInfo->setTemplateSpecializationKind(TSK);
|
||||
if (TSK != TSK_ExplicitSpecialization &&
|
||||
PointOfInstantiation.isValid() &&
|
||||
FTSInfo->getPointOfInstantiation().isInvalid())
|
||||
FTSInfo->setPointOfInstantiation(PointOfInstantiation);
|
||||
} else if (MemberSpecializationInfo *MSInfo
|
||||
= TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>()) {
|
||||
MSInfo->setTemplateSpecializationKind(TSK);
|
||||
if (TSK != TSK_ExplicitSpecialization &&
|
||||
PointOfInstantiation.isValid() &&
|
||||
MSInfo->getPointOfInstantiation().isInvalid())
|
||||
MSInfo->setPointOfInstantiation(PointOfInstantiation);
|
||||
} else
|
||||
assert(false && "Function cannot have a template specialization kind");
|
||||
}
|
||||
|
||||
SourceLocation FunctionDecl::getPointOfInstantiation() const {
|
||||
if (FunctionTemplateSpecializationInfo *FTSInfo
|
||||
= TemplateOrSpecialization.dyn_cast<
|
||||
FunctionTemplateSpecializationInfo*>())
|
||||
FTSInfo->setTemplateSpecializationKind(TSK);
|
||||
return FTSInfo->getPointOfInstantiation();
|
||||
else if (MemberSpecializationInfo *MSInfo
|
||||
= TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>())
|
||||
MSInfo->setTemplateSpecializationKind(TSK);
|
||||
else
|
||||
assert(false && "Function cannot have a template specialization kind");
|
||||
return MSInfo->getPointOfInstantiation();
|
||||
|
||||
return SourceLocation();
|
||||
}
|
||||
|
||||
bool FunctionDecl::isOutOfLine() const {
|
||||
|
@ -299,7 +299,7 @@ void TemplateArgumentListBuilder::Append(const TemplateArgument& Arg) {
|
||||
switch (Arg.getKind()) {
|
||||
default: break;
|
||||
case TemplateArgument::Type:
|
||||
assert(Arg.getAsType()->isCanonical() && "Type must be canonical!");
|
||||
assert(Arg.getAsType().isCanonical() && "Type must be canonical!");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ class CXXOperatorIdName : public DeclarationNameExtra {
|
||||
bool operator<(DeclarationName LHS, DeclarationName RHS) {
|
||||
if (IdentifierInfo *LhsId = LHS.getAsIdentifierInfo())
|
||||
if (IdentifierInfo *RhsId = RHS.getAsIdentifierInfo())
|
||||
return strcmp(LhsId->getName(), RhsId->getName()) < 0;
|
||||
return LhsId->getName() < RhsId->getName();
|
||||
|
||||
return LHS.getAsOpaqueInteger() < RHS.getAsOpaqueInteger();
|
||||
}
|
||||
@ -60,7 +60,7 @@ bool operator<(DeclarationName LHS, DeclarationName RHS) {
|
||||
|
||||
DeclarationName::DeclarationName(Selector Sel) {
|
||||
if (!Sel.getAsOpaquePtr()) {
|
||||
Ptr = StoredObjCZeroArgSelector;
|
||||
Ptr = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -426,6 +426,18 @@ const char *CastExpr::getCastKindName() const {
|
||||
return "IntegralToPointer";
|
||||
case CastExpr::CK_PointerToIntegral:
|
||||
return "PointerToIntegral";
|
||||
case CastExpr::CK_ToVoid:
|
||||
return "ToVoid";
|
||||
case CastExpr::CK_VectorSplat:
|
||||
return "VectorSplat";
|
||||
case CastExpr::CK_IntegralCast:
|
||||
return "IntegralCast";
|
||||
case CastExpr::CK_IntegralToFloating:
|
||||
return "IntegralToFloating";
|
||||
case CastExpr::CK_FloatingToIntegral:
|
||||
return "FloatingToIntegral";
|
||||
case CastExpr::CK_FloatingCast:
|
||||
return "FloatingCast";
|
||||
}
|
||||
|
||||
assert(0 && "Unhandled cast kind!");
|
||||
@ -1740,40 +1752,36 @@ unsigned ExtVectorElementExpr::getNumElements() const {
|
||||
|
||||
/// containsDuplicateElements - Return true if any element access is repeated.
|
||||
bool ExtVectorElementExpr::containsDuplicateElements() const {
|
||||
const char *compStr = Accessor->getName();
|
||||
unsigned length = Accessor->getLength();
|
||||
// FIXME: Refactor this code to an accessor on the AST node which returns the
|
||||
// "type" of component access, and share with code below and in Sema.
|
||||
llvm::StringRef Comp = Accessor->getName();
|
||||
|
||||
// Halving swizzles do not contain duplicate elements.
|
||||
if (!strcmp(compStr, "hi") || !strcmp(compStr, "lo") ||
|
||||
!strcmp(compStr, "even") || !strcmp(compStr, "odd"))
|
||||
if (Comp == "hi" || Comp == "lo" || Comp == "even" || Comp == "odd")
|
||||
return false;
|
||||
|
||||
// Advance past s-char prefix on hex swizzles.
|
||||
if (*compStr == 's' || *compStr == 'S') {
|
||||
compStr++;
|
||||
length--;
|
||||
}
|
||||
if (Comp[0] == 's' || Comp[0] == 'S')
|
||||
Comp = Comp.substr(1);
|
||||
|
||||
for (unsigned i = 0; i != length-1; i++) {
|
||||
const char *s = compStr+i;
|
||||
for (const char c = *s++; *s; s++)
|
||||
if (c == *s)
|
||||
for (unsigned i = 0, e = Comp.size(); i != e; ++i)
|
||||
if (Comp.substr(i + 1).find(Comp[i]) != llvm::StringRef::npos)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// getEncodedElementAccess - We encode the fields as a llvm ConstantArray.
|
||||
void ExtVectorElementExpr::getEncodedElementAccess(
|
||||
llvm::SmallVectorImpl<unsigned> &Elts) const {
|
||||
const char *compStr = Accessor->getName();
|
||||
if (*compStr == 's' || *compStr == 'S')
|
||||
compStr++;
|
||||
llvm::StringRef Comp = Accessor->getName();
|
||||
if (Comp[0] == 's' || Comp[0] == 'S')
|
||||
Comp = Comp.substr(1);
|
||||
|
||||
bool isHi = !strcmp(compStr, "hi");
|
||||
bool isLo = !strcmp(compStr, "lo");
|
||||
bool isEven = !strcmp(compStr, "even");
|
||||
bool isOdd = !strcmp(compStr, "odd");
|
||||
bool isHi = Comp == "hi";
|
||||
bool isLo = Comp == "lo";
|
||||
bool isEven = Comp == "even";
|
||||
bool isOdd = Comp == "odd";
|
||||
|
||||
for (unsigned i = 0, e = getNumElements(); i != e; ++i) {
|
||||
uint64_t Index;
|
||||
@ -1787,7 +1795,7 @@ void ExtVectorElementExpr::getEncodedElementAccess(
|
||||
else if (isOdd)
|
||||
Index = 2 * i + 1;
|
||||
else
|
||||
Index = ExtVectorType::getAccessorIdx(compStr[i]);
|
||||
Index = ExtVectorType::getAccessorIdx(Comp[i]);
|
||||
|
||||
Elts.push_back(Index);
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ void CompoundStmt::setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts) {
|
||||
}
|
||||
|
||||
const char *LabelStmt::getName() const {
|
||||
return getID()->getName();
|
||||
return getID()->getNameStart();
|
||||
}
|
||||
|
||||
// This is defined here to avoid polluting Stmt.h with importing Expr.h
|
||||
|
@ -244,7 +244,7 @@ void StmtDumper::DumpDeclarator(Decl *D) {
|
||||
// print a free standing tag decl (e.g. "struct x;").
|
||||
const char *tagname;
|
||||
if (const IdentifierInfo *II = TD->getIdentifier())
|
||||
tagname = II->getName();
|
||||
tagname = II->getNameStart();
|
||||
else
|
||||
tagname = "<anonymous>";
|
||||
fprintf(F, "\"%s %s;\"", TD->getKindName(), tagname);
|
||||
@ -253,7 +253,7 @@ void StmtDumper::DumpDeclarator(Decl *D) {
|
||||
// print using-directive decl (e.g. "using namespace x;")
|
||||
const char *ns;
|
||||
if (const IdentifierInfo *II = UD->getNominatedNamespace()->getIdentifier())
|
||||
ns = II->getName();
|
||||
ns = II->getNameStart();
|
||||
else
|
||||
ns = "<anonymous>";
|
||||
fprintf(F, "\"%s %s;\"",UD->getDeclKindName(), ns);
|
||||
@ -403,7 +403,7 @@ void StmtDumper::VisitMemberExpr(MemberExpr *Node) {
|
||||
}
|
||||
void StmtDumper::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) {
|
||||
DumpExpr(Node);
|
||||
fprintf(F, " %s", Node->getAccessor().getName());
|
||||
fprintf(F, " %s", Node->getAccessor().getNameStart());
|
||||
}
|
||||
void StmtDumper::VisitBinaryOperator(BinaryOperator *Node) {
|
||||
DumpExpr(Node);
|
||||
@ -495,7 +495,7 @@ void StmtDumper::VisitObjCMessageExpr(ObjCMessageExpr* Node) {
|
||||
DumpExpr(Node);
|
||||
fprintf(F, " selector=%s", Node->getSelector().getAsString().c_str());
|
||||
IdentifierInfo* clsName = Node->getClassName();
|
||||
if (clsName) fprintf(F, " class=%s", clsName->getName());
|
||||
if (clsName) fprintf(F, " class=%s", clsName->getNameStart());
|
||||
}
|
||||
|
||||
void StmtDumper::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) {
|
||||
|
@ -1289,7 +1289,7 @@ void Stmt::printPretty(llvm::raw_ostream &OS, ASTContext& Context,
|
||||
return;
|
||||
}
|
||||
|
||||
if (Policy.Dump) {
|
||||
if (Policy.Dump && &Context) {
|
||||
dump(Context.getSourceManager());
|
||||
return;
|
||||
}
|
||||
|
@ -37,18 +37,6 @@ void Type::Destroy(ASTContext& C) {
|
||||
C.Deallocate(this);
|
||||
}
|
||||
|
||||
void ConstantArrayWithExprType::Destroy(ASTContext& C) {
|
||||
// FIXME: destruction of SizeExpr commented out due to resource contention.
|
||||
// SizeExpr->Destroy(C);
|
||||
// See FIXME in SemaDecl.cpp:1536: if we were able to either steal
|
||||
// or clone the SizeExpr there, then here we could freely delete it.
|
||||
// Since we do not know how to steal or clone, we keep a pointer to
|
||||
// a shared resource, but we cannot free it.
|
||||
// (There probably is a trivial solution ... for people knowing clang!).
|
||||
this->~ConstantArrayWithExprType();
|
||||
C.Deallocate(this);
|
||||
}
|
||||
|
||||
void VariableArrayType::Destroy(ASTContext& C) {
|
||||
if (SizeExpr)
|
||||
SizeExpr->Destroy(C);
|
||||
@ -177,8 +165,6 @@ bool Type::isDerivedType() const {
|
||||
case Pointer:
|
||||
case VariableArray:
|
||||
case ConstantArray:
|
||||
case ConstantArrayWithExpr:
|
||||
case ConstantArrayWithoutExpr:
|
||||
case IncompleteArray:
|
||||
case FunctionProto:
|
||||
case FunctionNoProto:
|
||||
@ -642,6 +628,7 @@ bool Type::isSpecifierType() const {
|
||||
case TypeOfExpr:
|
||||
case TypeOf:
|
||||
case TemplateTypeParm:
|
||||
case SubstTemplateTypeParm:
|
||||
case TemplateSpecialization:
|
||||
case QualifiedName:
|
||||
case Typename:
|
||||
@ -737,18 +724,6 @@ void ObjCObjectPointerType::Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getPointeeType(), 0, 0);
|
||||
}
|
||||
|
||||
void ObjCProtocolListType::Profile(llvm::FoldingSetNodeID &ID,
|
||||
QualType OIT, ObjCProtocolDecl **protocols,
|
||||
unsigned NumProtocols) {
|
||||
ID.AddPointer(OIT.getAsOpaquePtr());
|
||||
for (unsigned i = 0; i != NumProtocols; i++)
|
||||
ID.AddPointer(protocols[i]);
|
||||
}
|
||||
|
||||
void ObjCProtocolListType::Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getBaseType(), &Protocols[0], getNumProtocols());
|
||||
}
|
||||
|
||||
/// LookThroughTypedefs - Return the ultimate type this typedef corresponds to
|
||||
/// potentially looking through *all* consequtive typedefs. This returns the
|
||||
/// sum of the type qualifiers, so if you have:
|
||||
@ -1072,10 +1047,10 @@ void LValueReferenceType::getAsStringInternal(std::string &S, const PrintingPoli
|
||||
|
||||
// Handle things like 'int (&A)[4];' correctly.
|
||||
// FIXME: this should include vectors, but vectors use attributes I guess.
|
||||
if (isa<ArrayType>(getPointeeType()))
|
||||
if (isa<ArrayType>(getPointeeTypeAsWritten()))
|
||||
S = '(' + S + ')';
|
||||
|
||||
getPointeeType().getAsStringInternal(S, Policy);
|
||||
getPointeeTypeAsWritten().getAsStringInternal(S, Policy);
|
||||
}
|
||||
|
||||
void RValueReferenceType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
|
||||
@ -1083,10 +1058,10 @@ void RValueReferenceType::getAsStringInternal(std::string &S, const PrintingPoli
|
||||
|
||||
// Handle things like 'int (&&A)[4];' correctly.
|
||||
// FIXME: this should include vectors, but vectors use attributes I guess.
|
||||
if (isa<ArrayType>(getPointeeType()))
|
||||
if (isa<ArrayType>(getPointeeTypeAsWritten()))
|
||||
S = '(' + S + ')';
|
||||
|
||||
getPointeeType().getAsStringInternal(S, Policy);
|
||||
getPointeeTypeAsWritten().getAsStringInternal(S, Policy);
|
||||
}
|
||||
|
||||
void MemberPointerType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
|
||||
@ -1111,29 +1086,6 @@ void ConstantArrayType::getAsStringInternal(std::string &S, const PrintingPolicy
|
||||
getElementType().getAsStringInternal(S, Policy);
|
||||
}
|
||||
|
||||
void ConstantArrayWithExprType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
|
||||
if (Policy.ConstantArraySizeAsWritten) {
|
||||
std::string SStr;
|
||||
llvm::raw_string_ostream s(SStr);
|
||||
getSizeExpr()->printPretty(s, 0, Policy);
|
||||
S += '[';
|
||||
S += s.str();
|
||||
S += ']';
|
||||
getElementType().getAsStringInternal(S, Policy);
|
||||
}
|
||||
else
|
||||
ConstantArrayType::getAsStringInternal(S, Policy);
|
||||
}
|
||||
|
||||
void ConstantArrayWithoutExprType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
|
||||
if (Policy.ConstantArraySizeAsWritten) {
|
||||
S += "[]";
|
||||
getElementType().getAsStringInternal(S, Policy);
|
||||
}
|
||||
else
|
||||
ConstantArrayType::getAsStringInternal(S, Policy);
|
||||
}
|
||||
|
||||
void IncompleteArrayType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
|
||||
S += "[]";
|
||||
|
||||
@ -1290,7 +1242,7 @@ void FunctionProtoType::getAsStringInternal(std::string &S, const PrintingPolicy
|
||||
void TypedefType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
|
||||
if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
|
||||
InnerString = ' ' + InnerString;
|
||||
InnerString = getDecl()->getIdentifier()->getName() + InnerString;
|
||||
InnerString = getDecl()->getIdentifier()->getName().str() + InnerString;
|
||||
}
|
||||
|
||||
void TemplateTypeParmType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
|
||||
@ -1301,7 +1253,11 @@ void TemplateTypeParmType::getAsStringInternal(std::string &InnerString, const P
|
||||
InnerString = "type-parameter-" + llvm::utostr_32(Depth) + '-' +
|
||||
llvm::utostr_32(Index) + InnerString;
|
||||
else
|
||||
InnerString = Name->getName() + InnerString;
|
||||
InnerString = Name->getName().str() + InnerString;
|
||||
}
|
||||
|
||||
void SubstTemplateTypeParmType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
|
||||
getReplacementType().getAsStringInternal(InnerString, Policy);
|
||||
}
|
||||
|
||||
std::string
|
||||
@ -1495,25 +1451,6 @@ void ObjCObjectPointerType::getAsStringInternal(std::string &InnerString,
|
||||
InnerString = ObjCQIString + InnerString;
|
||||
}
|
||||
|
||||
void ObjCProtocolListType::getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const {
|
||||
if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
|
||||
InnerString = ' ' + InnerString;
|
||||
|
||||
std::string ObjCQIString = getBaseType().getAsString(Policy);
|
||||
ObjCQIString += '<';
|
||||
bool isFirst = true;
|
||||
for (qual_iterator I = qual_begin(), E = qual_end(); I != E; ++I) {
|
||||
if (isFirst)
|
||||
isFirst = false;
|
||||
else
|
||||
ObjCQIString += ',';
|
||||
ObjCQIString += (*I)->getNameAsString();
|
||||
}
|
||||
ObjCQIString += '>';
|
||||
InnerString = ObjCQIString + InnerString;
|
||||
}
|
||||
|
||||
void ElaboratedType::getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const {
|
||||
std::string TypeStr;
|
||||
@ -1534,11 +1471,11 @@ void TagType::getAsStringInternal(std::string &InnerString, const PrintingPolicy
|
||||
const char *Kind = Policy.SuppressTagKind? 0 : getDecl()->getKindName();
|
||||
const char *ID;
|
||||
if (const IdentifierInfo *II = getDecl()->getIdentifier())
|
||||
ID = II->getName();
|
||||
ID = II->getNameStart();
|
||||
else if (TypedefDecl *Typedef = getDecl()->getTypedefForAnonDecl()) {
|
||||
Kind = 0;
|
||||
assert(Typedef->getIdentifier() && "Typedef without identifier?");
|
||||
ID = Typedef->getIdentifier()->getName();
|
||||
ID = Typedef->getIdentifier()->getNameStart();
|
||||
} else
|
||||
ID = "<anonymous>";
|
||||
|
||||
@ -1573,7 +1510,7 @@ void TagType::getAsStringInternal(std::string &InnerString, const PrintingPolicy
|
||||
TemplateArgs.getFlatArgumentList(),
|
||||
TemplateArgs.flat_size(),
|
||||
Policy);
|
||||
MyPart = Spec->getIdentifier()->getName() + TemplateArgsStr;
|
||||
MyPart = Spec->getIdentifier()->getName().str() + TemplateArgsStr;
|
||||
} else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
|
||||
if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl())
|
||||
MyPart = Typedef->getIdentifier()->getName();
|
||||
|
@ -20,55 +20,32 @@ using namespace clang;
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
|
||||
/// \brief Return the source range for the visited TypeSpecLoc.
|
||||
class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
|
||||
public:
|
||||
#define ABSTRACT_TYPELOC(CLASS)
|
||||
class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
|
||||
public:
|
||||
#define ABSTRACT_TYPELOC(CLASS, PARENT)
|
||||
#define TYPELOC(CLASS, PARENT) \
|
||||
SourceRange Visit##CLASS(CLASS TyLoc) { return TyLoc.getSourceRange(); }
|
||||
SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
|
||||
return TyLoc.getSourceRange(); \
|
||||
}
|
||||
#include "clang/AST/TypeLocNodes.def"
|
||||
|
||||
SourceRange VisitTypeLoc(TypeLoc TyLoc) {
|
||||
assert(0 && "A typeloc wrapper was not handled!");
|
||||
return SourceRange();
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
SourceRange TypeLoc::getSourceRange() const {
|
||||
if (isNull())
|
||||
return SourceRange();
|
||||
return TypeLocRanger().Visit(*this);
|
||||
}
|
||||
|
||||
/// \brief Find the TypeSpecLoc that is part of this TypeLoc.
|
||||
TypeSpecLoc TypeLoc::getTypeSpecLoc() const {
|
||||
if (isNull())
|
||||
return TypeSpecLoc();
|
||||
UnqualTypeLoc Cur = getUnqualifiedLoc();
|
||||
if (const DeclaratorLoc *DL = dyn_cast<DeclaratorLoc>(&Cur))
|
||||
return DL->getTypeSpecLoc();
|
||||
return cast<TypeSpecLoc>(Cur);
|
||||
SourceRange TypeLoc::getSourceRangeImpl(TypeLoc TL) {
|
||||
if (TL.isNull()) return SourceRange();
|
||||
return TypeLocRanger().Visit(TL);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/// \brief Report the full source info data size for the visited TypeLoc.
|
||||
class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
|
||||
public:
|
||||
#define ABSTRACT_TYPELOC(CLASS)
|
||||
class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
|
||||
public:
|
||||
#define ABSTRACT_TYPELOC(CLASS, PARENT)
|
||||
#define TYPELOC(CLASS, PARENT) \
|
||||
unsigned Visit##CLASS(CLASS TyLoc) { return TyLoc.getFullDataSize(); }
|
||||
unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
|
||||
return TyLoc.getFullDataSize(); \
|
||||
}
|
||||
#include "clang/AST/TypeLocNodes.def"
|
||||
|
||||
unsigned VisitTypeLoc(TypeLoc TyLoc) {
|
||||
assert(0 && "A type loc wrapper was not handled!");
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
/// \brief Returns the size of the type source info data block.
|
||||
@ -78,138 +55,42 @@ unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/// \brief Return the "next" TypeLoc for the visited TypeLoc, e.g for "int*" the
|
||||
/// TypeLoc is a PointerLoc and next TypeLoc is for "int".
|
||||
class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
|
||||
public:
|
||||
#define TYPELOC(CLASS, PARENT)
|
||||
#define DECLARATOR_TYPELOC(CLASS, TYPE) \
|
||||
TypeLoc Visit##CLASS(CLASS TyLoc);
|
||||
class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
|
||||
public:
|
||||
#define ABSTRACT_TYPELOC(CLASS, PARENT)
|
||||
#define TYPELOC(CLASS, PARENT) \
|
||||
TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
|
||||
return TyLoc.getNextTypeLoc(); \
|
||||
}
|
||||
#include "clang/AST/TypeLocNodes.def"
|
||||
|
||||
TypeLoc VisitTypeSpecLoc(TypeLoc TyLoc) { return TypeLoc(); }
|
||||
TypeLoc VisitObjCProtocolListLoc(ObjCProtocolListLoc TL);
|
||||
TypeLoc VisitQualifiedLoc(QualifiedLoc TyLoc) {
|
||||
return TyLoc.getUnqualifiedLoc();
|
||||
}
|
||||
|
||||
TypeLoc VisitTypeLoc(TypeLoc TyLoc) {
|
||||
assert(0 && "A declarator loc wrapper was not handled!");
|
||||
return TypeLoc();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
TypeLoc NextLoc::VisitObjCProtocolListLoc(ObjCProtocolListLoc TL) {
|
||||
return TL.getBaseTypeLoc();
|
||||
}
|
||||
|
||||
TypeLoc NextLoc::VisitPointerLoc(PointerLoc TL) {
|
||||
return TL.getPointeeLoc();
|
||||
}
|
||||
TypeLoc NextLoc::VisitMemberPointerLoc(MemberPointerLoc TL) {
|
||||
return TL.getPointeeLoc();
|
||||
}
|
||||
TypeLoc NextLoc::VisitBlockPointerLoc(BlockPointerLoc TL) {
|
||||
return TL.getPointeeLoc();
|
||||
}
|
||||
TypeLoc NextLoc::VisitReferenceLoc(ReferenceLoc TL) {
|
||||
return TL.getPointeeLoc();
|
||||
}
|
||||
TypeLoc NextLoc::VisitFunctionLoc(FunctionLoc TL) {
|
||||
return TL.getResultLoc();
|
||||
}
|
||||
TypeLoc NextLoc::VisitArrayLoc(ArrayLoc TL) {
|
||||
return TL.getElementLoc();
|
||||
};
|
||||
}
|
||||
|
||||
/// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
|
||||
/// TypeLoc is a PointerLoc and next TypeLoc is for "int".
|
||||
TypeLoc TypeLoc::getNextTypeLoc() const {
|
||||
//llvm::errs() << "getNextTypeLoc: Ty=" << Ty << ", Data=" << Data << "\n";
|
||||
TypeLoc Tmp = NextLoc().Visit(*this);
|
||||
//llvm::errs() << " result: Ty=" << Tmp.Ty << ", Data=" << Tmp.Data << "\n";
|
||||
return Tmp;
|
||||
TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
|
||||
return NextLoc().Visit(TL);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// TypeSpecLoc Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
class TypeSpecChecker : public TypeLocVisitor<TypeSpecChecker, bool> {
|
||||
public:
|
||||
bool VisitTypeSpecLoc(TypeSpecLoc TyLoc) { return true; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
bool TypeSpecLoc::classof(const UnqualTypeLoc *TL) {
|
||||
return TypeSpecChecker().Visit(*TL);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DeclaratorLoc Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
|
||||
/// \brief Return the TypeSpecLoc for the visited DeclaratorLoc.
|
||||
class TypeSpecGetter : public TypeLocVisitor<TypeSpecGetter, TypeSpecLoc> {
|
||||
public:
|
||||
#define TYPELOC(CLASS, PARENT)
|
||||
#define DECLARATOR_TYPELOC(CLASS, TYPE) \
|
||||
TypeSpecLoc Visit##CLASS(CLASS TyLoc) { return TyLoc.getTypeSpecLoc(); }
|
||||
struct TypeLocInitializer : public TypeLocVisitor<TypeLocInitializer> {
|
||||
SourceLocation Loc;
|
||||
TypeLocInitializer(SourceLocation Loc) : Loc(Loc) {}
|
||||
|
||||
#define ABSTRACT_TYPELOC(CLASS, PARENT)
|
||||
#define TYPELOC(CLASS, PARENT) \
|
||||
void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
|
||||
TyLoc.initializeLocal(Loc); \
|
||||
}
|
||||
#include "clang/AST/TypeLocNodes.def"
|
||||
|
||||
TypeSpecLoc VisitTypeLoc(TypeLoc TyLoc) {
|
||||
assert(0 && "A declarator loc wrapper was not handled!");
|
||||
return TypeSpecLoc();
|
||||
}
|
||||
|
||||
TypeSpecLoc VisitQualifiedLoc(QualifiedLoc TyLoc) {
|
||||
return Visit(TyLoc.getUnqualifiedLoc());
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
/// \brief Find the TypeSpecLoc that is part of this DeclaratorLoc.
|
||||
TypeSpecLoc DeclaratorLoc::getTypeSpecLoc() const {
|
||||
return TypeSpecGetter().Visit(*this);
|
||||
/// \brief Initializes a type location, and all of its children
|
||||
/// recursively, as if the entire tree had been written in the
|
||||
/// given location.
|
||||
void TypeLoc::initializeImpl(TypeLoc TL, SourceLocation Loc) {
|
||||
do {
|
||||
TypeLocInitializer(Loc).Visit(TL);
|
||||
} while ((TL = TL.getNextTypeLoc()));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class DeclaratorLocChecker : public TypeLocVisitor<DeclaratorLocChecker, bool> {
|
||||
public:
|
||||
bool VisitDeclaratorLoc(DeclaratorLoc TyLoc) { return true; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
bool DeclaratorLoc::classof(const UnqualTypeLoc *TL) {
|
||||
return DeclaratorLocChecker().Visit(*TL);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DefaultTypeSpecLoc Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
|
||||
class DefaultTypeSpecLocChecker :
|
||||
public TypeLocVisitor<DefaultTypeSpecLocChecker, bool> {
|
||||
public:
|
||||
bool VisitDefaultTypeSpecLoc(DefaultTypeSpecLoc TyLoc) { return true; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
bool DefaultTypeSpecLoc::classofType(const Type *Ty) {
|
||||
return
|
||||
DefaultTypeSpecLocChecker().Visit(UnqualTypeLoc(const_cast<Type*>(Ty), 0));
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,12 @@ AnalysisContextManager::~AnalysisContextManager() {
|
||||
delete I->second;
|
||||
}
|
||||
|
||||
void AnalysisContextManager::clear() {
|
||||
for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I)
|
||||
delete I->second;
|
||||
Contexts.clear();
|
||||
}
|
||||
|
||||
Stmt *AnalysisContext::getBody() {
|
||||
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
|
||||
return FD->getBody();
|
||||
@ -103,6 +109,21 @@ void ScopeContext::Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
|
||||
ID.AddPointer(s);
|
||||
}
|
||||
|
||||
LocationContextManager::~LocationContextManager() {
|
||||
clear();
|
||||
}
|
||||
|
||||
void LocationContextManager::clear() {
|
||||
for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(),
|
||||
E = Contexts.end(); I != E; ) {
|
||||
LocationContext *LC = &*I;
|
||||
++I;
|
||||
delete LC;
|
||||
}
|
||||
|
||||
Contexts.clear();
|
||||
}
|
||||
|
||||
StackFrameContext*
|
||||
LocationContextManager::getStackFrame(AnalysisContext *ctx,
|
||||
const LocationContext *parent,
|
||||
|
@ -45,9 +45,9 @@ static const ObjCInterfaceType* GetReceiverType(const ObjCMessageExpr* ME) {
|
||||
}
|
||||
|
||||
static const char* GetReceiverNameType(const ObjCMessageExpr* ME) {
|
||||
const ObjCInterfaceType *ReceiverType = GetReceiverType(ME);
|
||||
return ReceiverType ? ReceiverType->getDecl()->getIdentifier()->getName()
|
||||
: NULL;
|
||||
if (const ObjCInterfaceType *ReceiverType = GetReceiverType(ME))
|
||||
return ReceiverType->getDecl()->getIdentifier()->getNameStart();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
namespace {
|
||||
@ -62,7 +62,7 @@ class VISIBILITY_HIDDEN BasicObjCFoundationChecks : public GRSimpleAPICheck {
|
||||
BugReporter& BR;
|
||||
ASTContext &Ctx;
|
||||
|
||||
bool isNSString(const ObjCInterfaceType *T, const char* suffix);
|
||||
bool isNSString(const ObjCInterfaceType *T, llvm::StringRef suffix);
|
||||
bool AuditNSString(ExplodedNode* N, const ObjCMessageExpr* ME);
|
||||
|
||||
void Warn(ExplodedNode* N, const Expr* E, const std::string& s);
|
||||
@ -114,18 +114,8 @@ bool BasicObjCFoundationChecks::Audit(ExplodedNode* N,
|
||||
if (!ReceiverType)
|
||||
return false;
|
||||
|
||||
const char* name = ReceiverType->getDecl()->getIdentifier()->getName();
|
||||
|
||||
if (!name)
|
||||
return false;
|
||||
|
||||
if (name[0] != 'N' || name[1] != 'S')
|
||||
return false;
|
||||
|
||||
name += 2;
|
||||
|
||||
// FIXME: Make all of this faster.
|
||||
if (isNSString(ReceiverType, name))
|
||||
if (isNSString(ReceiverType,
|
||||
ReceiverType->getDecl()->getIdentifier()->getName()))
|
||||
return AuditNSString(N, ME);
|
||||
|
||||
return false;
|
||||
@ -158,8 +148,8 @@ bool BasicObjCFoundationChecks::CheckNilArg(ExplodedNode* N, unsigned Arg) {
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
bool BasicObjCFoundationChecks::isNSString(const ObjCInterfaceType *T,
|
||||
const char* suffix) {
|
||||
return !strcmp("String", suffix) || !strcmp("MutableString", suffix);
|
||||
llvm::StringRef ClassName) {
|
||||
return ClassName == "NSString" || ClassName == "NSMutableString";
|
||||
}
|
||||
|
||||
bool BasicObjCFoundationChecks::AuditNSString(ExplodedNode* N,
|
||||
|
@ -49,7 +49,8 @@ class VISIBILITY_HIDDEN BasicStoreManager : public StoreManager {
|
||||
QualType T = QualType());
|
||||
|
||||
const GRState *InvalidateRegion(const GRState *state, const MemRegion *R,
|
||||
const Expr *E, unsigned Count);
|
||||
const Expr *E, unsigned Count,
|
||||
InvalidatedSymbols *IS);
|
||||
|
||||
const GRState *Bind(const GRState *state, Loc L, SVal V) {
|
||||
return state->makeWithStore(BindInternal(state->getStore(), L, V));
|
||||
@ -623,12 +624,21 @@ StoreManager::BindingsHandler::~BindingsHandler() {}
|
||||
const GRState *BasicStoreManager::InvalidateRegion(const GRState *state,
|
||||
const MemRegion *R,
|
||||
const Expr *E,
|
||||
unsigned Count) {
|
||||
unsigned Count,
|
||||
InvalidatedSymbols *IS) {
|
||||
R = R->getBaseRegion();
|
||||
|
||||
if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R)))
|
||||
return state;
|
||||
|
||||
if (IS) {
|
||||
BindingsTy B = GetBindings(state->getStore());
|
||||
if (BindingsTy::data_type *Val = B.lookup(R)) {
|
||||
if (SymbolRef Sym = Val->getAsSymbol())
|
||||
IS->insert(Sym);
|
||||
}
|
||||
}
|
||||
|
||||
QualType T = cast<TypedRegion>(R)->getValueType(R->getContext());
|
||||
SVal V = ValMgr.getConjuredSymbolVal(R, E, T, Count);
|
||||
return Bind(state, loc::MemRegionVal(R), V);
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
|
||||
using namespace clang;
|
||||
|
||||
@ -51,7 +52,7 @@ static SourceLocation GetEndLoc(Decl* D) {
|
||||
///
|
||||
class VISIBILITY_HIDDEN CFGBuilder {
|
||||
ASTContext *Context;
|
||||
CFG* cfg;
|
||||
llvm::OwningPtr<CFG> cfg;
|
||||
|
||||
CFGBlock* Block;
|
||||
CFGBlock* Succ;
|
||||
@ -79,8 +80,6 @@ class VISIBILITY_HIDDEN CFGBuilder {
|
||||
ContinueTargetBlock(NULL), BreakTargetBlock(NULL),
|
||||
SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL) {}
|
||||
|
||||
~CFGBuilder() { delete cfg; }
|
||||
|
||||
// buildCFG - Used by external clients to construct the CFG.
|
||||
CFG* buildCFG(Stmt *Statement, ASTContext *C);
|
||||
|
||||
@ -195,7 +194,7 @@ static VariableArrayType* FindVA(Type* t) {
|
||||
/// NULL.
|
||||
CFG* CFGBuilder::buildCFG(Stmt* Statement, ASTContext* C) {
|
||||
Context = C;
|
||||
assert(cfg);
|
||||
assert(cfg.get());
|
||||
if (!Statement)
|
||||
return NULL;
|
||||
|
||||
@ -210,7 +209,8 @@ CFG* CFGBuilder::buildCFG(Stmt* Statement, ASTContext* C) {
|
||||
|
||||
// Visit the statements and create the CFG.
|
||||
CFGBlock* B = addStmt(Statement);
|
||||
if (!B) B = Succ;
|
||||
if (!B)
|
||||
B = Succ;
|
||||
|
||||
if (B) {
|
||||
// Finalize the last constructed block. This usually involves reversing the
|
||||
@ -254,17 +254,7 @@ CFG* CFGBuilder::buildCFG(Stmt* Statement, ASTContext* C) {
|
||||
// Create an empty entry block that has no predecessors.
|
||||
cfg->setEntry(createBlock());
|
||||
|
||||
if (badCFG) {
|
||||
delete cfg;
|
||||
cfg = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// NULL out cfg so that repeated calls to the builder will fail and that the
|
||||
// ownership of the constructed CFG is passed to the caller.
|
||||
CFG* t = cfg;
|
||||
cfg = NULL;
|
||||
return t;
|
||||
return badCFG ? NULL : cfg.take();
|
||||
}
|
||||
|
||||
/// createBlock - Used to lazily create blocks that are connected
|
||||
|
@ -81,7 +81,7 @@ static NamingConvention deriveNamingConvention(Selector S) {
|
||||
if (!II)
|
||||
return NoConvention;
|
||||
|
||||
const char *s = II->getName();
|
||||
const char *s = II->getNameStart();
|
||||
|
||||
// A method/function name may contain a prefix. We don't know it is there,
|
||||
// however, until we encounter the first '_'.
|
||||
@ -93,12 +93,14 @@ static NamingConvention deriveNamingConvention(Selector S) {
|
||||
// Skip '_'.
|
||||
if (*s == '_') {
|
||||
if (InPossiblePrefix) {
|
||||
// If we already have a convention, return it. Otherwise, skip
|
||||
// the prefix as if it wasn't there.
|
||||
if (C != NoConvention)
|
||||
break;
|
||||
|
||||
InPossiblePrefix = false;
|
||||
AtBeginning = true;
|
||||
// Discard whatever 'convention' we
|
||||
// had already derived since it occurs
|
||||
// in the prefix.
|
||||
C = NoConvention;
|
||||
assert(C == NoConvention);
|
||||
}
|
||||
++s;
|
||||
continue;
|
||||
@ -208,41 +210,16 @@ static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) {
|
||||
// Type querying functions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static bool hasPrefix(const char* s, const char* prefix) {
|
||||
if (!prefix)
|
||||
return true;
|
||||
|
||||
char c = *s;
|
||||
char cP = *prefix;
|
||||
|
||||
while (c != '\0' && cP != '\0') {
|
||||
if (c != cP) break;
|
||||
c = *(++s);
|
||||
cP = *(++prefix);
|
||||
}
|
||||
|
||||
return cP == '\0';
|
||||
}
|
||||
|
||||
static bool hasSuffix(const char* s, const char* suffix) {
|
||||
const char* loc = strstr(s, suffix);
|
||||
return loc && strcmp(suffix, loc) == 0;
|
||||
}
|
||||
|
||||
static bool isRefType(QualType RetTy, const char* prefix,
|
||||
ASTContext* Ctx = 0, const char* name = 0) {
|
||||
|
||||
// Recursively walk the typedef stack, allowing typedefs of reference types.
|
||||
while (1) {
|
||||
if (TypedefType* TD = dyn_cast<TypedefType>(RetTy.getTypePtr())) {
|
||||
const char* TDName = TD->getDecl()->getIdentifier()->getName();
|
||||
if (hasPrefix(TDName, prefix) && hasSuffix(TDName, "Ref"))
|
||||
return true;
|
||||
while (TypedefType* TD = dyn_cast<TypedefType>(RetTy.getTypePtr())) {
|
||||
llvm::StringRef TDName = TD->getDecl()->getIdentifier()->getName();
|
||||
if (TDName.startswith(prefix) && TDName.endswith("Ref"))
|
||||
return true;
|
||||
|
||||
RetTy = TD->getDecl()->getUnderlyingType();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
RetTy = TD->getDecl()->getUnderlyingType();
|
||||
}
|
||||
|
||||
if (!Ctx || !name)
|
||||
@ -254,7 +231,7 @@ static bool isRefType(QualType RetTy, const char* prefix,
|
||||
return false;
|
||||
|
||||
// Does the name start with the prefix?
|
||||
return hasPrefix(name, prefix);
|
||||
return llvm::StringRef(name).startswith(prefix);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -956,7 +933,7 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
|
||||
// [PR 3337] Use 'getAs<FunctionType>' to strip away any typedefs on the
|
||||
// function's type.
|
||||
const FunctionType* FT = FD->getType()->getAs<FunctionType>();
|
||||
const char* FName = FD->getIdentifier()->getName();
|
||||
const char* FName = FD->getIdentifier()->getNameStart();
|
||||
|
||||
// Strip away preceding '_'. Doing this here will effect all the checks
|
||||
// down below.
|
||||
@ -1009,7 +986,7 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
|
||||
// Part of <rdar://problem/6961230>. (IOKit)
|
||||
// This should be addressed using a API table.
|
||||
ScratchArgs = AF.Add(ScratchArgs, 2, DecRef);
|
||||
S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
|
||||
S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing,DoNothing);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1432,16 +1409,19 @@ void RetainSummaryManager::InitializeClassMethodSummaries() {
|
||||
addNSObjectClsMethSummary(GetUnarySelector("allocWithZone", Ctx), Summ);
|
||||
|
||||
// Create the [NSAssertionHandler currentHander] summary.
|
||||
addClsMethSummary(&Ctx.Idents.get("NSAssertionHandler"),
|
||||
GetNullarySelector("currentHandler", Ctx),
|
||||
addClassMethSummary("NSAssertionHandler", "currentHandler",
|
||||
getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::ObjC)));
|
||||
|
||||
// Create the [NSAutoreleasePool addObject:] summary.
|
||||
ScratchArgs = AF.Add(ScratchArgs, 0, Autorelease);
|
||||
addClsMethSummary(&Ctx.Idents.get("NSAutoreleasePool"),
|
||||
GetUnarySelector("addObject", Ctx),
|
||||
getPersistentSummary(RetEffect::MakeNoRet(),
|
||||
DoNothing, Autorelease));
|
||||
addClassMethSummary("NSAutoreleasePool", "addObject",
|
||||
getPersistentSummary(RetEffect::MakeNoRet(),
|
||||
DoNothing, Autorelease));
|
||||
|
||||
// Create a summary for [NSCursor dragCopyCursor].
|
||||
addClassMethSummary("NSCursor", "dragCopyCursor",
|
||||
getPersistentSummary(RetEffect::MakeNoRet(), DoNothing,
|
||||
DoNothing));
|
||||
|
||||
// Create the summaries for [NSObject performSelector...]. We treat
|
||||
// these as 'stop tracking' for the arguments because they are often
|
||||
@ -2856,14 +2836,13 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst,
|
||||
// FIXME: What about layers of ElementRegions?
|
||||
}
|
||||
|
||||
// Is the invalidated variable something that we were tracking?
|
||||
SymbolRef Sym = state->getSValAsScalarOrLoc(R).getAsLocSymbol();
|
||||
|
||||
// Remove any existing reference-count binding.
|
||||
if (Sym)
|
||||
state = state->remove<RefBindings>(Sym);
|
||||
|
||||
state = StoreMgr.InvalidateRegion(state, R, *I, Count);
|
||||
StoreManager::InvalidatedSymbols IS;
|
||||
state = StoreMgr.InvalidateRegion(state, R, *I, Count, &IS);
|
||||
for (StoreManager::InvalidatedSymbols::iterator I = IS.begin(),
|
||||
E = IS.end(); I!=E; ++I) {
|
||||
// Remove any existing reference-count binding.
|
||||
state = state->remove<RefBindings>(*I);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Nuke all other arguments passed by reference.
|
||||
|
@ -207,7 +207,7 @@ const GRState* GRExprEngine::getInitialState(const LocationContext *InitLoc) {
|
||||
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
||||
// Precondition: the first argument of 'main' is an integer guaranteed
|
||||
// to be > 0.
|
||||
if (strcmp(FD->getIdentifier()->getName(), "main") == 0 &&
|
||||
if (FD->getIdentifier()->getName() == "main" &&
|
||||
FD->getNumParams() > 0) {
|
||||
const ParmVarDecl *PD = FD->getParamDecl(0);
|
||||
QualType T = PD->getType();
|
||||
@ -1445,10 +1445,9 @@ static void MarkNoReturnFunction(const FunctionDecl *FD, CallExpr *CE,
|
||||
// HACK: Some functions are not marked noreturn, and don't return.
|
||||
// Here are a few hardwired ones. If this takes too long, we can
|
||||
// potentially cache these results.
|
||||
const char* s = FD->getIdentifier()->getName();
|
||||
unsigned n = strlen(s);
|
||||
const char* s = FD->getIdentifier()->getNameStart();
|
||||
|
||||
switch (n) {
|
||||
switch (FD->getIdentifier()->getLength()) {
|
||||
default:
|
||||
break;
|
||||
|
||||
@ -2788,66 +2787,55 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
|
||||
SVal RightV = state->getSVal(RHS);
|
||||
|
||||
BinaryOperator::Opcode Op = B->getOpcode();
|
||||
switch (Op) {
|
||||
case BinaryOperator::Assign: {
|
||||
|
||||
// EXPERIMENTAL: "Conjured" symbols.
|
||||
// FIXME: Handle structs.
|
||||
QualType T = RHS->getType();
|
||||
|
||||
if ((RightV.isUnknown() ||
|
||||
!getConstraintManager().canReasonAbout(RightV))
|
||||
&& (Loc::IsLocType(T) ||
|
||||
(T->isScalarType() && T->isIntegerType()))) {
|
||||
unsigned Count = Builder->getCurrentBlockCount();
|
||||
RightV = ValMgr.getConjuredSymbolVal(NULL, B->getRHS(), Count);
|
||||
if (Op == BinaryOperator::Assign) {
|
||||
// EXPERIMENTAL: "Conjured" symbols.
|
||||
// FIXME: Handle structs.
|
||||
QualType T = RHS->getType();
|
||||
|
||||
if ((RightV.isUnknown()||!getConstraintManager().canReasonAbout(RightV))
|
||||
&& (Loc::IsLocType(T) || (T->isScalarType()&&T->isIntegerType()))) {
|
||||
unsigned Count = Builder->getCurrentBlockCount();
|
||||
RightV = ValMgr.getConjuredSymbolVal(NULL, B->getRHS(), Count);
|
||||
}
|
||||
|
||||
// Simulate the effects of a "store": bind the value of the RHS
|
||||
// to the L-Value represented by the LHS.
|
||||
EvalStore(Dst, B, LHS, *I2, state->BindExpr(B, RightV), LeftV, RightV);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!B->isAssignmentOp()) {
|
||||
// Process non-assignments except commas or short-circuited
|
||||
// logical expressions (LAnd and LOr).
|
||||
SVal Result = EvalBinOp(state, Op, LeftV, RightV, B->getType());
|
||||
|
||||
if (Result.isUnknown()) {
|
||||
if (OldSt != state) {
|
||||
// Generate a new node if we have already created a new state.
|
||||
MakeNode(Dst, B, *I2, state);
|
||||
}
|
||||
|
||||
// Simulate the effects of a "store": bind the value of the RHS
|
||||
// to the L-Value represented by the LHS.
|
||||
EvalStore(Dst, B, LHS, *I2, state->BindExpr(B, RightV),
|
||||
LeftV, RightV);
|
||||
else
|
||||
Dst.Add(*I2);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// FALL-THROUGH.
|
||||
|
||||
default: {
|
||||
|
||||
if (B->isAssignmentOp())
|
||||
break;
|
||||
|
||||
// Process non-assignments except commas or short-circuited
|
||||
// logical expressions (LAnd and LOr).
|
||||
SVal Result = EvalBinOp(state, Op, LeftV, RightV, B->getType());
|
||||
|
||||
if (Result.isUnknown()) {
|
||||
if (OldSt != state) {
|
||||
// Generate a new node if we have already created a new state.
|
||||
MakeNode(Dst, B, *I2, state);
|
||||
}
|
||||
else
|
||||
Dst.Add(*I2);
|
||||
|
||||
continue;
|
||||
|
||||
state = state->BindExpr(B, Result);
|
||||
|
||||
if (Result.isUndef()) {
|
||||
// The operands were *not* undefined, but the result is undefined.
|
||||
// This is a special node that should be flagged as an error.
|
||||
if (ExplodedNode *UndefNode = Builder->generateNode(B, state, *I2)){
|
||||
UndefNode->markAsSink();
|
||||
UndefResults.insert(UndefNode);
|
||||
}
|
||||
|
||||
state = state->BindExpr(B, Result);
|
||||
|
||||
if (Result.isUndef()) {
|
||||
// The operands were *not* undefined, but the result is undefined.
|
||||
// This is a special node that should be flagged as an error.
|
||||
if (ExplodedNode *UndefNode = Builder->generateNode(B, state, *I2)){
|
||||
UndefNode->markAsSink();
|
||||
UndefResults.insert(UndefNode);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise, create a new node.
|
||||
MakeNode(Dst, B, *I2, state);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise, create a new node.
|
||||
MakeNode(Dst, B, *I2, state);
|
||||
continue;
|
||||
}
|
||||
|
||||
assert (B->isCompoundAssignmentOp());
|
||||
@ -2875,7 +2863,6 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
|
||||
|
||||
for (ExplodedNodeSet::iterator I3=Tmp3.begin(), E3=Tmp3.end(); I3!=E3;
|
||||
++I3) {
|
||||
|
||||
state = GetState(*I3);
|
||||
SVal V = state->getSVal(LHS);
|
||||
|
||||
|
@ -742,11 +742,11 @@ void CheckBadCall::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
|
||||
}
|
||||
}
|
||||
|
||||
class VISIBILITY_HIDDEN CheckBadDiv : public CheckerVisitor<CheckBadDiv> {
|
||||
class VISIBILITY_HIDDEN CheckDivZero : public CheckerVisitor<CheckDivZero> {
|
||||
DivZero *BT;
|
||||
public:
|
||||
CheckBadDiv() : BT(0) {}
|
||||
~CheckBadDiv() {}
|
||||
CheckDivZero() : BT(0) {}
|
||||
~CheckDivZero() {}
|
||||
|
||||
const void *getTag() {
|
||||
static int x;
|
||||
@ -756,8 +756,8 @@ class VISIBILITY_HIDDEN CheckBadDiv : public CheckerVisitor<CheckBadDiv> {
|
||||
void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
|
||||
};
|
||||
|
||||
void CheckBadDiv::PreVisitBinaryOperator(CheckerContext &C,
|
||||
const BinaryOperator *B) {
|
||||
void CheckDivZero::PreVisitBinaryOperator(CheckerContext &C,
|
||||
const BinaryOperator *B) {
|
||||
BinaryOperator::Opcode Op = B->getOpcode();
|
||||
if (Op != BinaryOperator::Div &&
|
||||
Op != BinaryOperator::Rem &&
|
||||
@ -792,7 +792,8 @@ void CheckBadDiv::PreVisitBinaryOperator(CheckerContext &C,
|
||||
return;
|
||||
}
|
||||
|
||||
// If we get here, then the denom should not be zero.
|
||||
// If we get here, then the denom should not be zero. We abandon the implicit
|
||||
// zero denom case for now.
|
||||
if (stateNotZero != C.getState())
|
||||
C.addTransition(C.GenerateNode(B, stateNotZero));
|
||||
}
|
||||
@ -828,5 +829,5 @@ void GRExprEngine::RegisterInternalChecks() {
|
||||
registerCheck(new CheckAttrNonNull());
|
||||
registerCheck(new CheckUndefinedArg());
|
||||
registerCheck(new CheckBadCall());
|
||||
registerCheck(new CheckBadDiv());
|
||||
registerCheck(new CheckDivZero());
|
||||
}
|
||||
|
@ -21,9 +21,7 @@
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
using namespace clang;
|
||||
|
||||
@ -341,20 +339,19 @@ void LiveVariables::dumpLiveness(const ValTy& V, SourceManager& SM) const {
|
||||
for (AnalysisDataTy::decl_iterator I = AD.begin_decl(),
|
||||
E = AD.end_decl(); I!=E; ++I)
|
||||
if (V.getDeclBit(I->second)) {
|
||||
fprintf(stderr, " %s <", I->first->getIdentifier()->getName());
|
||||
llvm::errs() << " " << I->first->getIdentifier()->getName() << " <";
|
||||
I->first->getLocation().dump(SM);
|
||||
fprintf(stderr, ">\n");
|
||||
llvm::errs() << ">\n";
|
||||
}
|
||||
}
|
||||
|
||||
void LiveVariables::dumpBlockLiveness(SourceManager& M) const {
|
||||
for (BlockDataMapTy::iterator I = getBlockDataMap().begin(),
|
||||
E = getBlockDataMap().end(); I!=E; ++I) {
|
||||
fprintf(stderr, "\n[ B%d (live variables at block exit) ]\n",
|
||||
I->first->getBlockID());
|
||||
|
||||
llvm::errs() << "\n[ B" << I->first->getBlockID()
|
||||
<< " (live variables at block exit) ]\n";
|
||||
dumpLiveness(I->second,M);
|
||||
}
|
||||
|
||||
fprintf(stderr,"\n");
|
||||
llvm::errs() << "\n";
|
||||
}
|
||||
|
@ -262,7 +262,8 @@ class VISIBILITY_HIDDEN RegionStoreManager : public StoreManager {
|
||||
//===-------------------------------------------------------------------===//
|
||||
|
||||
const GRState *InvalidateRegion(const GRState *state, const MemRegion *R,
|
||||
const Expr *E, unsigned Count);
|
||||
const Expr *E, unsigned Count,
|
||||
InvalidatedSymbols *IS);
|
||||
|
||||
private:
|
||||
void RemoveSubRegionBindings(RegionBindings &B, const MemRegion *R,
|
||||
@ -455,7 +456,8 @@ void RegionStoreManager::RemoveSubRegionBindings(RegionBindings &B,
|
||||
const GRState *RegionStoreManager::InvalidateRegion(const GRState *state,
|
||||
const MemRegion *R,
|
||||
const Expr *Ex,
|
||||
unsigned Count) {
|
||||
unsigned Count,
|
||||
InvalidatedSymbols *IS) {
|
||||
ASTContext& Ctx = StateMgr.getContext();
|
||||
|
||||
// Strip away casts.
|
||||
@ -490,9 +492,21 @@ const GRState *RegionStoreManager::InvalidateRegion(const GRState *state,
|
||||
if (Optional<SVal> V = getDirectBinding(B, R)) {
|
||||
if (const MemRegion *RV = V->getAsRegion())
|
||||
WorkList.push_back(RV);
|
||||
|
||||
// A symbol? Mark it touched by the invalidation.
|
||||
if (IS) {
|
||||
if (SymbolRef Sym = V->getAsSymbol())
|
||||
IS->insert(Sym);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle region.
|
||||
// Symbolic region? Mark that symbol touched by the invalidation.
|
||||
if (IS) {
|
||||
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
|
||||
IS->insert(SR->getSymbol());
|
||||
}
|
||||
|
||||
// Handle the region itself.
|
||||
if (isa<AllocaRegion>(R) || isa<SymbolicRegion>(R) ||
|
||||
isa<ObjCObjectRegion>(R)) {
|
||||
// Invalidate the region by setting its default value to
|
||||
@ -1230,8 +1244,8 @@ SVal RegionStoreManager::RetrieveObjCIvar(const GRState* state,
|
||||
|
||||
const MemRegion *superR = R->getSuperRegion();
|
||||
|
||||
// Check if the super region has a binding.
|
||||
if (Optional<SVal> V = getDirectBinding(B, superR)) {
|
||||
// Check if the super region has a default binding.
|
||||
if (Optional<SVal> V = getDefaultBinding(B, superR)) {
|
||||
if (SymbolRef parentSym = V->getAsSymbol())
|
||||
return ValMgr.getDerivedRegionValueSymbolVal(parentSym, R);
|
||||
|
||||
@ -1376,7 +1390,7 @@ const GRState *RegionStoreManager::Bind(const GRState *state, Loc L, SVal V) {
|
||||
// For now, just invalidate the fields of the struct/union/class.
|
||||
// FIXME: Precisely handle the fields of the record.
|
||||
if (superTy->isRecordType())
|
||||
return InvalidateRegion(state, superR, NULL, 0);
|
||||
return InvalidateRegion(state, superR, NULL, 0, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1588,36 +1602,13 @@ RegionStoreManager::CopyLazyBindings(nonloc::LazyCompoundVal V,
|
||||
//===----------------------------------------------------------------------===//
|
||||
// State pruning.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
class VISIBILITY_HIDDEN RBDNode
|
||||
: public std::pair<const GRState*, const MemRegion *> {
|
||||
public:
|
||||
RBDNode(const GRState *st, const MemRegion *r)
|
||||
: std::pair<const GRState*, const MemRegion*>(st, r) {}
|
||||
|
||||
const GRState *getState() const { return first; }
|
||||
const MemRegion *getRegion() const { return second; }
|
||||
};
|
||||
|
||||
enum VisitFlag { NotVisited = 0, VisitedFromSubRegion, VisitedFromSuperRegion };
|
||||
|
||||
class RBDItem : public RBDNode {
|
||||
private:
|
||||
const VisitFlag VF;
|
||||
|
||||
public:
|
||||
RBDItem(const GRState *st, const MemRegion *r, VisitFlag vf)
|
||||
: RBDNode(st, r), VF(vf) {}
|
||||
|
||||
VisitFlag getVisitFlag() const { return VF; }
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
|
||||
SymbolReaper& SymReaper,
|
||||
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots)
|
||||
{
|
||||
typedef std::pair<const GRState*, const MemRegion *> RBDNode;
|
||||
|
||||
Store store = state.getStore();
|
||||
RegionBindings B = GetRegionBindings(store);
|
||||
|
||||
@ -1638,27 +1629,26 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
|
||||
|
||||
// Process the "intermediate" roots to find if they are referenced by
|
||||
// real roots.
|
||||
llvm::SmallVector<RBDItem, 10> WorkList;
|
||||
llvm::DenseMap<const MemRegion*,unsigned> IntermediateVisited;
|
||||
llvm::SmallVector<RBDNode, 10> WorkList;
|
||||
llvm::DenseSet<const MemRegion*> IntermediateVisited;
|
||||
|
||||
while (!IntermediateRoots.empty()) {
|
||||
const MemRegion* R = IntermediateRoots.back();
|
||||
IntermediateRoots.pop_back();
|
||||
|
||||
unsigned &visited = IntermediateVisited[R];
|
||||
if (visited)
|
||||
if (IntermediateVisited.count(R))
|
||||
continue;
|
||||
visited = 1;
|
||||
IntermediateVisited.insert(R);
|
||||
|
||||
if (const VarRegion* VR = dyn_cast<VarRegion>(R)) {
|
||||
if (SymReaper.isLive(Loc, VR->getDecl()))
|
||||
WorkList.push_back(RBDItem(&state, VR, VisitedFromSuperRegion));
|
||||
WorkList.push_back(std::make_pair(&state, VR));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (const SymbolicRegion* SR = dyn_cast<SymbolicRegion>(R)) {
|
||||
if (SymReaper.isLive(SR->getSymbol()))
|
||||
WorkList.push_back(RBDItem(&state, SR, VisitedFromSuperRegion));
|
||||
WorkList.push_back(std::make_pair(&state, SR));
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1671,54 +1661,40 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
|
||||
// Enqueue the RegionRoots onto WorkList.
|
||||
for (llvm::SmallVectorImpl<const MemRegion*>::iterator I=RegionRoots.begin(),
|
||||
E=RegionRoots.end(); I!=E; ++I) {
|
||||
WorkList.push_back(RBDItem(&state, *I, VisitedFromSuperRegion));
|
||||
WorkList.push_back(std::make_pair(&state, *I));
|
||||
}
|
||||
RegionRoots.clear();
|
||||
|
||||
// Process the worklist.
|
||||
typedef llvm::DenseMap<std::pair<const GRState*, const MemRegion*>, VisitFlag>
|
||||
VisitMap;
|
||||
|
||||
VisitMap Visited;
|
||||
llvm::DenseSet<RBDNode> Visited;
|
||||
|
||||
while (!WorkList.empty()) {
|
||||
RBDItem N = WorkList.back();
|
||||
RBDNode N = WorkList.back();
|
||||
WorkList.pop_back();
|
||||
|
||||
// Have we visited this node before?
|
||||
VisitFlag &VF = Visited[N];
|
||||
if (VF >= N.getVisitFlag())
|
||||
if (Visited.count(N))
|
||||
continue;
|
||||
|
||||
const MemRegion *R = N.getRegion();
|
||||
const GRState *state_N = N.getState();
|
||||
|
||||
// Enqueue subregions?
|
||||
if (N.getVisitFlag() == VisitedFromSuperRegion) {
|
||||
RegionStoreSubRegionMap *M;
|
||||
|
||||
if (&state == state_N)
|
||||
M = SubRegions.get();
|
||||
else {
|
||||
RegionStoreSubRegionMap *& SM = SC[state_N];
|
||||
if (!SM)
|
||||
SM = getRegionStoreSubRegionMap(state_N->getStore());
|
||||
M = SM;
|
||||
}
|
||||
|
||||
RegionStoreSubRegionMap::iterator I, E;
|
||||
for (llvm::tie(I, E) = M->begin_end(R); I != E; ++I)
|
||||
WorkList.push_back(RBDItem(state_N, *I, VisitedFromSuperRegion));
|
||||
}
|
||||
Visited.insert(N);
|
||||
|
||||
// At this point, if we have already visited this region before, we are
|
||||
// done.
|
||||
if (VF != NotVisited) {
|
||||
VF = N.getVisitFlag();
|
||||
continue;
|
||||
}
|
||||
VF = N.getVisitFlag();
|
||||
const MemRegion *R = N.second;
|
||||
const GRState *state_N = N.first;
|
||||
|
||||
// Enqueue subregions.
|
||||
RegionStoreSubRegionMap *M;
|
||||
|
||||
if (&state == state_N)
|
||||
M = SubRegions.get();
|
||||
else {
|
||||
RegionStoreSubRegionMap *& SM = SC[state_N];
|
||||
if (!SM)
|
||||
SM = getRegionStoreSubRegionMap(state_N->getStore());
|
||||
M = SM;
|
||||
}
|
||||
|
||||
RegionStoreSubRegionMap::iterator I, E;
|
||||
for (llvm::tie(I, E) = M->begin_end(R); I != E; ++I)
|
||||
WorkList.push_back(std::make_pair(state_N, *I));
|
||||
|
||||
// Enqueue the super region.
|
||||
if (const SubRegion *SR = dyn_cast<SubRegion>(R)) {
|
||||
const MemRegion *superR = SR->getSuperRegion();
|
||||
@ -1726,12 +1702,9 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
|
||||
// If 'R' is a field or an element, we want to keep the bindings
|
||||
// for the other fields and elements around. The reason is that
|
||||
// pointer arithmetic can get us to the other fields or elements.
|
||||
// FIXME: add an assertion that this is always true.
|
||||
VisitFlag NewVisit =
|
||||
isa<FieldRegion>(R) || isa<ElementRegion>(R) || isa<ObjCIvarRegion>(R)
|
||||
? VisitedFromSuperRegion : VisitedFromSubRegion;
|
||||
|
||||
WorkList.push_back(RBDItem(state_N, superR, NewVisit));
|
||||
assert(isa<FieldRegion>(R) || isa<ElementRegion>(R)
|
||||
|| isa<ObjCIvarRegion>(R));
|
||||
WorkList.push_back(std::make_pair(state_N, superR));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1752,8 +1725,7 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
|
||||
dyn_cast<nonloc::LazyCompoundVal>(V.getPointer())) {
|
||||
|
||||
const LazyCompoundValData *D = LCV->getCVData();
|
||||
WorkList.push_back(RBDItem(D->getState(), D->getRegion(),
|
||||
VisitedFromSuperRegion));
|
||||
WorkList.push_back(std::make_pair(D->getState(), D->getRegion()));
|
||||
}
|
||||
else {
|
||||
// Update the set of live symbols.
|
||||
@ -1763,7 +1735,7 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
|
||||
|
||||
// If V is a region, then add it to the worklist.
|
||||
if (const MemRegion *RX = V->getAsRegion())
|
||||
WorkList.push_back(RBDItem(state_N, RX, VisitedFromSuperRegion));
|
||||
WorkList.push_back(std::make_pair(state_N, RX));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1774,7 +1746,7 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
|
||||
for (RegionBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
|
||||
const MemRegion* R = I.getKey();
|
||||
// If this region live? Is so, none of its symbols are dead.
|
||||
if (Visited.find(std::make_pair(&state, R)) != Visited.end())
|
||||
if (Visited.count(std::make_pair(&state, R)))
|
||||
continue;
|
||||
|
||||
// Remove this dead region from the store.
|
||||
@ -1820,7 +1792,7 @@ GRState const *RegionStoreManager::EnterStackFrame(GRState const *state,
|
||||
void RegionStoreManager::print(Store store, llvm::raw_ostream& OS,
|
||||
const char* nl, const char *sep) {
|
||||
RegionBindings B = GetRegionBindings(store);
|
||||
OS << "Store (direct bindings):" << nl;
|
||||
OS << "Store (direct and default bindings):" << nl;
|
||||
|
||||
for (RegionBindings::iterator I = B.begin(), E = B.end(); I != E; ++I)
|
||||
OS << ' ' << I.getKey() << " : " << I.getData() << nl;
|
||||
|
@ -346,16 +346,29 @@ SVal SimpleSValuator::EvalBinOpNN(const GRState *state,
|
||||
nonloc::SymbolVal *slhs = cast<nonloc::SymbolVal>(&lhs);
|
||||
SymbolRef Sym = slhs->getSymbol();
|
||||
|
||||
// Does the symbol simplify to a constant?
|
||||
// Does the symbol simplify to a constant? If so, "fold" the constant
|
||||
// by setting 'lhs' to a ConcreteInt and try again.
|
||||
if (Sym->getType(ValMgr.getContext())->isIntegerType())
|
||||
if (const llvm::APSInt *Constant = state->getSymVal(Sym)) {
|
||||
// What should we convert it to?
|
||||
if (nonloc::ConcreteInt *rhs_I = dyn_cast<nonloc::ConcreteInt>(&rhs)){
|
||||
BasicValueFactory &BVF = ValMgr.getBasicValueFactory();
|
||||
lhs = nonloc::ConcreteInt(BVF.Convert(rhs_I->getValue(),
|
||||
*Constant));
|
||||
// The symbol evaluates to a constant. If necessary, promote the
|
||||
// folded constant (LHS) to the result type.
|
||||
BasicValueFactory &BVF = ValMgr.getBasicValueFactory();
|
||||
const llvm::APSInt &lhs_I = BVF.Convert(resultTy, *Constant);
|
||||
lhs = nonloc::ConcreteInt(lhs_I);
|
||||
|
||||
// Also promote the RHS (if necessary).
|
||||
|
||||
// For shifts, it necessary promote the RHS to the result type.
|
||||
if (BinaryOperator::isShiftOp(op))
|
||||
continue;
|
||||
|
||||
// Other operators: do an implicit conversion. This shouldn't be
|
||||
// necessary once we support truncation/extension of symbolic values.
|
||||
if (nonloc::ConcreteInt *rhs_I = dyn_cast<nonloc::ConcreteInt>(&rhs)){
|
||||
rhs = nonloc::ConcreteInt(BVF.Convert(resultTy, rhs_I->getValue()));
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isa<nonloc::ConcreteInt>(rhs)) {
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <cstring>
|
||||
@ -82,9 +83,14 @@ static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
|
||||
#ifndef NDEBUG
|
||||
static bool IsFirst = true;
|
||||
if (IsFirst) {
|
||||
for (unsigned i = 1; i != NumDiagEntries; ++i)
|
||||
for (unsigned i = 1; i != NumDiagEntries; ++i) {
|
||||
assert(StaticDiagInfo[i-1].DiagID != StaticDiagInfo[i].DiagID &&
|
||||
"Diag ID conflict, the enums at the start of clang::diag (in "
|
||||
"Diagnostic.h) probably need to be increased");
|
||||
|
||||
assert(StaticDiagInfo[i-1] < StaticDiagInfo[i] &&
|
||||
"Improperly sorted diag info");
|
||||
}
|
||||
IsFirst = false;
|
||||
}
|
||||
#endif
|
||||
@ -184,6 +190,8 @@ namespace clang {
|
||||
static void DummyArgToStringFn(Diagnostic::ArgumentKind AK, intptr_t QT,
|
||||
const char *Modifier, unsigned ML,
|
||||
const char *Argument, unsigned ArgLen,
|
||||
const Diagnostic::ArgumentValue *PrevArgs,
|
||||
unsigned NumPrevArgs,
|
||||
llvm::SmallVectorImpl<char> &Output,
|
||||
void *Cookie) {
|
||||
const char *Str = "<can't format argument>";
|
||||
@ -222,6 +230,8 @@ Diagnostic::~Diagnostic() {
|
||||
|
||||
|
||||
void Diagnostic::pushMappings() {
|
||||
// Avoids undefined behavior when the stack has to resize.
|
||||
DiagMappingsStack.reserve(DiagMappingsStack.size() + 1);
|
||||
DiagMappingsStack.push_back(DiagMappingsStack.back());
|
||||
}
|
||||
|
||||
@ -679,6 +689,12 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
|
||||
const char *DiagStr = getDiags()->getDescription(getID());
|
||||
const char *DiagEnd = DiagStr+strlen(DiagStr);
|
||||
|
||||
/// FormattedArgs - Keep track of all of the arguments formatted by
|
||||
/// ConvertArgToString and pass them into subsequent calls to
|
||||
/// ConvertArgToString, allowing the implementation to avoid redundancies in
|
||||
/// obvious cases.
|
||||
llvm::SmallVector<Diagnostic::ArgumentValue, 8> FormattedArgs;
|
||||
|
||||
while (DiagStr != DiagEnd) {
|
||||
if (DiagStr[0] != '%') {
|
||||
// Append non-%0 substrings to Str if we have one.
|
||||
@ -726,7 +742,9 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
|
||||
assert(isdigit(*DiagStr) && "Invalid format for argument in diagnostic");
|
||||
unsigned ArgNo = *DiagStr++ - '0';
|
||||
|
||||
switch (getArgKind(ArgNo)) {
|
||||
Diagnostic::ArgumentKind Kind = getArgKind(ArgNo);
|
||||
|
||||
switch (Kind) {
|
||||
// ---- STRINGS ----
|
||||
case Diagnostic::ak_std_string: {
|
||||
const std::string &S = getArgStdStr(ArgNo);
|
||||
@ -757,9 +775,7 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
|
||||
HandlePluralModifier((unsigned)Val, Argument, ArgumentLen, OutStr);
|
||||
} else {
|
||||
assert(ModifierLen == 0 && "Unknown integer modifier");
|
||||
// FIXME: Optimize
|
||||
std::string S = llvm::itostr(Val);
|
||||
OutStr.append(S.begin(), S.end());
|
||||
llvm::raw_svector_ostream(OutStr) << Val;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -774,10 +790,7 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
|
||||
HandlePluralModifier((unsigned)Val, Argument, ArgumentLen, OutStr);
|
||||
} else {
|
||||
assert(ModifierLen == 0 && "Unknown integer modifier");
|
||||
|
||||
// FIXME: Optimize
|
||||
std::string S = llvm::utostr_32(Val);
|
||||
OutStr.append(S.begin(), S.end());
|
||||
llvm::raw_svector_ostream(OutStr) << Val;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -793,9 +806,7 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
|
||||
continue;
|
||||
}
|
||||
|
||||
OutStr.push_back('\'');
|
||||
OutStr.append(II->getName(), II->getName() + II->getLength());
|
||||
OutStr.push_back('\'');
|
||||
llvm::raw_svector_ostream(OutStr) << '\'' << II->getName() << '\'';
|
||||
break;
|
||||
}
|
||||
case Diagnostic::ak_qualtype:
|
||||
@ -803,11 +814,23 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
|
||||
case Diagnostic::ak_nameddecl:
|
||||
case Diagnostic::ak_nestednamespec:
|
||||
case Diagnostic::ak_declcontext:
|
||||
getDiags()->ConvertArgToString(getArgKind(ArgNo), getRawArg(ArgNo),
|
||||
getDiags()->ConvertArgToString(Kind, getRawArg(ArgNo),
|
||||
Modifier, ModifierLen,
|
||||
Argument, ArgumentLen, OutStr);
|
||||
Argument, ArgumentLen,
|
||||
FormattedArgs.data(), FormattedArgs.size(),
|
||||
OutStr);
|
||||
break;
|
||||
}
|
||||
|
||||
// Remember this argument info for subsequent formatting operations. Turn
|
||||
// std::strings into a null terminated string to make it be the same case as
|
||||
// all the other ones.
|
||||
if (Kind != Diagnostic::ak_std_string)
|
||||
FormattedArgs.push_back(std::make_pair(Kind, getRawArg(ArgNo)));
|
||||
else
|
||||
FormattedArgs.push_back(std::make_pair(Diagnostic::ak_c_string,
|
||||
(intptr_t)getArgStdStr(ArgNo).c_str()));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,6 +149,41 @@ FileManager::~FileManager() {
|
||||
delete &UniqueFiles;
|
||||
}
|
||||
|
||||
void FileManager::addStatCache(StatSysCallCache *statCache, bool AtBeginning) {
|
||||
assert(statCache && "No stat cache provided?");
|
||||
if (AtBeginning || StatCache.get() == 0) {
|
||||
statCache->setNextStatCache(StatCache.take());
|
||||
StatCache.reset(statCache);
|
||||
return;
|
||||
}
|
||||
|
||||
StatSysCallCache *LastCache = StatCache.get();
|
||||
while (LastCache->getNextStatCache())
|
||||
LastCache = LastCache->getNextStatCache();
|
||||
|
||||
LastCache->setNextStatCache(statCache);
|
||||
}
|
||||
|
||||
void FileManager::removeStatCache(StatSysCallCache *statCache) {
|
||||
if (!statCache)
|
||||
return;
|
||||
|
||||
if (StatCache.get() == statCache) {
|
||||
// This is the first stat cache.
|
||||
StatCache.reset(StatCache->takeNextStatCache());
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the stat cache in the list.
|
||||
StatSysCallCache *PrevCache = StatCache.get();
|
||||
while (PrevCache && PrevCache->getNextStatCache() != statCache)
|
||||
PrevCache = PrevCache->getNextStatCache();
|
||||
if (PrevCache)
|
||||
PrevCache->setNextStatCache(statCache->getNextStatCache());
|
||||
else
|
||||
assert(false && "Stat cache not found for removal");
|
||||
}
|
||||
|
||||
/// getDirectory - Lookup, cache, and verify the specified directory. This
|
||||
/// returns null if the directory doesn't exist.
|
||||
///
|
||||
@ -290,8 +325,8 @@ void FileManager::PrintStats() const {
|
||||
}
|
||||
|
||||
int MemorizeStatCalls::stat(const char *path, struct stat *buf) {
|
||||
int result = ::stat(path, buf);
|
||||
|
||||
int result = StatSysCallCache::stat(path, buf);
|
||||
|
||||
if (result != 0) {
|
||||
// Cache failed 'stat' results.
|
||||
struct stat empty;
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "clang/Basic/LangOptions.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cstdio>
|
||||
|
||||
using namespace clang;
|
||||
@ -153,7 +154,7 @@ tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {
|
||||
|
||||
unsigned Len = getLength();
|
||||
if (Len < 2) return tok::pp_not_keyword;
|
||||
const char *Name = getName();
|
||||
const char *Name = getNameStart();
|
||||
switch (HASH(Len, Name[0], Name[2])) {
|
||||
default: return tok::pp_not_keyword;
|
||||
CASE( 2, 'i', '\0', if);
|
||||
@ -301,24 +302,15 @@ IdentifierInfo *Selector::getIdentifierInfoForSlot(unsigned argIndex) const {
|
||||
}
|
||||
|
||||
std::string MultiKeywordSelector::getName() const {
|
||||
std::string Result;
|
||||
unsigned Length = 0;
|
||||
llvm::SmallString<256> Str;
|
||||
llvm::raw_svector_ostream OS(Str);
|
||||
for (keyword_iterator I = keyword_begin(), E = keyword_end(); I != E; ++I) {
|
||||
if (*I)
|
||||
Length += (*I)->getLength();
|
||||
++Length; // :
|
||||
OS << (*I)->getName();
|
||||
OS << ':';
|
||||
}
|
||||
|
||||
Result.reserve(Length);
|
||||
|
||||
for (keyword_iterator I = keyword_begin(), E = keyword_end(); I != E; ++I) {
|
||||
if (*I)
|
||||
Result.insert(Result.end(), (*I)->getName(),
|
||||
(*I)->getName()+(*I)->getLength());
|
||||
Result.push_back(':');
|
||||
}
|
||||
|
||||
return Result;
|
||||
return OS.str();
|
||||
}
|
||||
|
||||
std::string Selector::getAsString() const {
|
||||
@ -332,9 +324,10 @@ std::string Selector::getAsString() const {
|
||||
if (getNumArgs() == 0)
|
||||
return II->getName();
|
||||
|
||||
std::string Res = II ? II->getName() : "";
|
||||
Res += ":";
|
||||
return Res;
|
||||
if (!II)
|
||||
return ":";
|
||||
|
||||
return II->getName().str() + ":";
|
||||
}
|
||||
|
||||
// We have a multiple keyword selector (no embedded flags).
|
||||
|
@ -43,6 +43,7 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
|
||||
UIntMaxType = UnsignedLongLong;
|
||||
IntPtrType = SignedLong;
|
||||
WCharType = SignedInt;
|
||||
WIntType = SignedInt;
|
||||
Char16Type = UnsignedShort;
|
||||
Char32Type = UnsignedInt;
|
||||
Int64Type = SignedLongLong;
|
||||
@ -73,6 +74,57 @@ const char *TargetInfo::getTypeName(IntType T) {
|
||||
}
|
||||
}
|
||||
|
||||
/// getTypeConstantSuffix - Return the constant suffix for the specified
|
||||
/// integer type enum. For example, SignedLong -> "L".
|
||||
const char *TargetInfo::getTypeConstantSuffix(IntType T) {
|
||||
switch (T) {
|
||||
default: assert(0 && "not an integer!");
|
||||
case SignedShort:
|
||||
case SignedInt: return "";
|
||||
case SignedLong: return "L";
|
||||
case SignedLongLong: return "LL";
|
||||
case UnsignedShort:
|
||||
case UnsignedInt: return "U";
|
||||
case UnsignedLong: return "UL";
|
||||
case UnsignedLongLong: return "ULL";
|
||||
}
|
||||
}
|
||||
|
||||
/// getTypeWidth - Return the width (in bits) of the specified integer type
|
||||
/// enum. For example, SignedInt -> getIntWidth().
|
||||
unsigned TargetInfo::getTypeWidth(IntType T) const {
|
||||
switch (T) {
|
||||
default: assert(0 && "not an integer!");
|
||||
case SignedShort: return getShortWidth();
|
||||
case UnsignedShort: return getShortWidth();
|
||||
case SignedInt: return getIntWidth();
|
||||
case UnsignedInt: return getIntWidth();
|
||||
case SignedLong: return getLongWidth();
|
||||
case UnsignedLong: return getLongWidth();
|
||||
case SignedLongLong: return getLongLongWidth();
|
||||
case UnsignedLongLong: return getLongLongWidth();
|
||||
};
|
||||
}
|
||||
|
||||
/// getTypeSigned - Return whether an integer types is signed. Returns true if
|
||||
/// the type is signed; false otherwise.
|
||||
bool TargetInfo::getTypeSigned(IntType T) const {
|
||||
switch (T) {
|
||||
default: assert(0 && "not an integer!");
|
||||
case SignedShort:
|
||||
case SignedInt:
|
||||
case SignedLong:
|
||||
case SignedLongLong:
|
||||
return true;
|
||||
case UnsignedShort:
|
||||
case UnsignedInt:
|
||||
case UnsignedLong:
|
||||
case UnsignedLongLong:
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
|
@ -320,6 +320,27 @@ class OpenBSDTargetInfo : public OSTargetInfo<Target> {
|
||||
: OSTargetInfo<Target>(triple) {}
|
||||
};
|
||||
|
||||
// AuroraUX target
|
||||
template<typename Target>
|
||||
class AuroraUXTargetInfo : public OSTargetInfo<Target> {
|
||||
protected:
|
||||
virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
|
||||
std::vector<char> &Defs) const {
|
||||
DefineStd(Defs, "sun", Opts);
|
||||
DefineStd(Defs, "unix", Opts);
|
||||
Define(Defs, "__ELF__");
|
||||
Define(Defs, "__svr4__");
|
||||
Define(Defs, "__SVR4");
|
||||
}
|
||||
public:
|
||||
AuroraUXTargetInfo(const std::string& triple)
|
||||
: OSTargetInfo<Target>(triple) {
|
||||
this->UserLabelPrefix = "";
|
||||
this->WCharType = this->SignedLong;
|
||||
// FIXME: WIntType should be SignedLong
|
||||
}
|
||||
};
|
||||
|
||||
// Solaris target
|
||||
template<typename Target>
|
||||
class SolarisTargetInfo : public OSTargetInfo<Target> {
|
||||
@ -1456,6 +1477,14 @@ void SparcV8TargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
|
||||
} // end anonymous namespace.
|
||||
|
||||
namespace {
|
||||
class AuroraUXSparcV8TargetInfo : public AuroraUXTargetInfo<SparcV8TargetInfo> {
|
||||
public:
|
||||
AuroraUXSparcV8TargetInfo(const std::string& triple) :
|
||||
AuroraUXTargetInfo<SparcV8TargetInfo>(triple) {
|
||||
SizeType = UnsignedInt;
|
||||
PtrDiffType = SignedInt;
|
||||
}
|
||||
};
|
||||
class SolarisSparcV8TargetInfo : public SolarisTargetInfo<SparcV8TargetInfo> {
|
||||
public:
|
||||
SolarisSparcV8TargetInfo(const std::string& triple) :
|
||||
@ -1573,8 +1602,8 @@ namespace {
|
||||
}
|
||||
virtual bool validateAsmConstraint(const char *&Name,
|
||||
TargetInfo::ConstraintInfo &info) const {
|
||||
// FIXME: implement
|
||||
return true;
|
||||
// No target constraints for now.
|
||||
return false;
|
||||
}
|
||||
virtual const char *getClobbers() const {
|
||||
// FIXME: Is this really right?
|
||||
@ -1846,6 +1875,8 @@ TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) {
|
||||
return new PPC64TargetInfo(T);
|
||||
|
||||
case llvm::Triple::sparc:
|
||||
if (os == llvm::Triple::AuroraUX)
|
||||
return new AuroraUXSparcV8TargetInfo(T);
|
||||
if (os == llvm::Triple::Solaris)
|
||||
return new SolarisSparcV8TargetInfo(T);
|
||||
return new SparcV8TargetInfo(T);
|
||||
@ -1858,6 +1889,8 @@ TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) {
|
||||
|
||||
case llvm::Triple::x86:
|
||||
switch (os) {
|
||||
case llvm::Triple::AuroraUX:
|
||||
return new AuroraUXTargetInfo<X86_32TargetInfo>(T);
|
||||
case llvm::Triple::Darwin:
|
||||
return new DarwinI386TargetInfo(T);
|
||||
case llvm::Triple::Linux:
|
||||
@ -1884,6 +1917,8 @@ TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) {
|
||||
|
||||
case llvm::Triple::x86_64:
|
||||
switch (os) {
|
||||
case llvm::Triple::AuroraUX:
|
||||
return new AuroraUXTargetInfo<X86_64TargetInfo>(T);
|
||||
case llvm::Triple::Darwin:
|
||||
return new DarwinX86_64TargetInfo(T);
|
||||
case llvm::Triple::Linux:
|
||||
|
@ -73,29 +73,60 @@ llvm::Constant *BlockModule::getNSConcreteStackBlock() {
|
||||
return NSConcreteStackBlock;
|
||||
}
|
||||
|
||||
static void CollectBlockDeclRefInfo(const Stmt *S,
|
||||
CodeGenFunction::BlockInfo &Info) {
|
||||
static void CollectBlockDeclRefInfo(
|
||||
const Stmt *S, CodeGenFunction::BlockInfo &Info,
|
||||
llvm::SmallSet<const DeclContext *, 16> &InnerContexts) {
|
||||
for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
|
||||
I != E; ++I)
|
||||
if (*I)
|
||||
CollectBlockDeclRefInfo(*I, Info);
|
||||
CollectBlockDeclRefInfo(*I, Info, InnerContexts);
|
||||
|
||||
if (const BlockDeclRefExpr *DE = dyn_cast<BlockDeclRefExpr>(S)) {
|
||||
// We want to ensure we walk down into block literals so we can find
|
||||
// all nested BlockDeclRefExprs.
|
||||
if (const BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
|
||||
InnerContexts.insert(cast<DeclContext>(BE->getBlockDecl()));
|
||||
CollectBlockDeclRefInfo(BE->getBody(), Info, InnerContexts);
|
||||
}
|
||||
|
||||
if (const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) {
|
||||
// FIXME: Handle enums.
|
||||
if (isa<FunctionDecl>(DE->getDecl()))
|
||||
if (isa<FunctionDecl>(BDRE->getDecl()))
|
||||
return;
|
||||
|
||||
if (DE->isByRef())
|
||||
Info.ByRefDeclRefs.push_back(DE);
|
||||
else
|
||||
Info.ByCopyDeclRefs.push_back(DE);
|
||||
// Only Decls that escape are added.
|
||||
if (!InnerContexts.count(BDRE->getDecl()->getDeclContext()))
|
||||
Info.DeclRefs.push_back(BDRE);
|
||||
}
|
||||
}
|
||||
|
||||
/// CanBlockBeGlobal - Given a BlockInfo struct, determines if a block can be
|
||||
/// declared as a global variable instead of on the stack.
|
||||
static bool CanBlockBeGlobal(const CodeGenFunction::BlockInfo &Info) {
|
||||
return Info.ByRefDeclRefs.empty() && Info.ByCopyDeclRefs.empty();
|
||||
return Info.DeclRefs.empty();
|
||||
}
|
||||
|
||||
/// AllocateAllBlockDeclRefs - Preallocate all nested BlockDeclRefExprs to
|
||||
/// ensure we can generate the debug information for the parameter for the block
|
||||
/// invoke function.
|
||||
static void AllocateAllBlockDeclRefs(const CodeGenFunction::BlockInfo &Info,
|
||||
CodeGenFunction *CGF) {
|
||||
// Always allocate self, as it is often handy in the debugger, even if there
|
||||
// is no codegen in the block that uses it. This is also useful to always do
|
||||
// this as if we didn't, we'd have to figure out all code that uses a self
|
||||
// pointer, including implicit uses.
|
||||
if (const ObjCMethodDecl *OMD
|
||||
= dyn_cast_or_null<ObjCMethodDecl>(CGF->CurFuncDecl)) {
|
||||
ImplicitParamDecl *SelfDecl = OMD->getSelfDecl();
|
||||
BlockDeclRefExpr *BDRE = new (CGF->getContext())
|
||||
BlockDeclRefExpr(SelfDecl,
|
||||
SelfDecl->getType(), SourceLocation(), false);
|
||||
CGF->AllocateBlockDecl(BDRE);
|
||||
}
|
||||
|
||||
// FIXME: Also always forward the this pointer in C++ as well.
|
||||
|
||||
for (size_t i = 0; i < Info.DeclRefs.size(); ++i)
|
||||
CGF->AllocateBlockDecl(Info.DeclRefs[i]);
|
||||
}
|
||||
|
||||
// FIXME: Push most into CGM, passing down a few bits, like current function
|
||||
@ -104,7 +135,9 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
|
||||
|
||||
std::string Name = CurFn->getName();
|
||||
CodeGenFunction::BlockInfo Info(0, Name.c_str());
|
||||
CollectBlockDeclRefInfo(BE->getBody(), Info);
|
||||
llvm::SmallSet<const DeclContext *, 16> InnerContexts;
|
||||
InnerContexts.insert(BE->getBlockDecl());
|
||||
CollectBlockDeclRefInfo(BE->getBody(), Info, InnerContexts);
|
||||
|
||||
// Check if the block can be global.
|
||||
// FIXME: This test doesn't work for nested blocks yet. Longer term, I'd like
|
||||
@ -159,7 +192,8 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
|
||||
|
||||
if (subBlockDeclRefDecls.size() == 0) {
|
||||
// __descriptor
|
||||
Elts[4] = BuildDescriptorBlockDecl(subBlockHasCopyDispose, subBlockSize, 0, 0);
|
||||
Elts[4] = BuildDescriptorBlockDecl(subBlockHasCopyDispose, subBlockSize,
|
||||
0, 0);
|
||||
|
||||
// Optimize to being a global block.
|
||||
Elts[0] = CGM.getNSConcreteGlobalBlock();
|
||||
@ -269,7 +303,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
|
||||
llvm::Value *BlockLiteral = LoadBlockStruct();
|
||||
|
||||
Loc = Builder.CreateGEP(BlockLiteral,
|
||||
llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
|
||||
llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
|
||||
offset),
|
||||
"block.literal");
|
||||
Ty = llvm::PointerType::get(Ty, 0);
|
||||
@ -391,10 +425,6 @@ const llvm::Type *BlockModule::getGenericExtendedBlockLiteralType() {
|
||||
return GenericExtendedBlockLiteralType;
|
||||
}
|
||||
|
||||
bool BlockFunction::BlockRequiresCopying(QualType Ty) {
|
||||
return CGM.BlockRequiresCopying(Ty);
|
||||
}
|
||||
|
||||
RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E) {
|
||||
const BlockPointerType *BPT =
|
||||
E->getCallee()->getType()->getAs<BlockPointerType>();
|
||||
@ -447,24 +477,34 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E) {
|
||||
return EmitCall(FnInfo, Func, Args);
|
||||
}
|
||||
|
||||
llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const BlockDeclRefExpr *E) {
|
||||
uint64_t CodeGenFunction::AllocateBlockDecl(const BlockDeclRefExpr *E) {
|
||||
const ValueDecl *VD = E->getDecl();
|
||||
|
||||
uint64_t &offset = BlockDecls[VD];
|
||||
|
||||
|
||||
// See if we have already allocated an offset for this variable.
|
||||
if (offset == 0) {
|
||||
// Don't run the expensive check, unless we have to.
|
||||
if (!BlockHasCopyDispose && BlockRequiresCopying(E->getType()))
|
||||
if (offset)
|
||||
return offset;
|
||||
|
||||
// Don't run the expensive check, unless we have to.
|
||||
if (!BlockHasCopyDispose)
|
||||
if (E->isByRef()
|
||||
|| BlockRequiresCopying(E->getType()))
|
||||
BlockHasCopyDispose = true;
|
||||
// if not, allocate one now.
|
||||
offset = getBlockOffset(E);
|
||||
}
|
||||
|
||||
// if not, allocate one now.
|
||||
offset = getBlockOffset(E);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const BlockDeclRefExpr *E) {
|
||||
const ValueDecl *VD = E->getDecl();
|
||||
uint64_t offset = AllocateBlockDecl(E);
|
||||
|
||||
|
||||
llvm::Value *BlockLiteral = LoadBlockStruct();
|
||||
llvm::Value *V = Builder.CreateGEP(BlockLiteral,
|
||||
llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
|
||||
llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
|
||||
offset),
|
||||
"block.literal");
|
||||
if (E->isByRef()) {
|
||||
@ -576,7 +616,10 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
|
||||
}
|
||||
|
||||
llvm::Value *CodeGenFunction::LoadBlockStruct() {
|
||||
return Builder.CreateLoad(LocalDeclMap[getBlockStructDecl()], "self");
|
||||
llvm::Value *V = Builder.CreateLoad(LocalDeclMap[getBlockStructDecl()],
|
||||
"self");
|
||||
// For now, we codegen based upon byte offsets.
|
||||
return Builder.CreateBitCast(V, PtrToInt8Ty);
|
||||
}
|
||||
|
||||
llvm::Function *
|
||||
@ -605,14 +648,8 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
|
||||
LocalDeclMap[VD] = i->second;
|
||||
}
|
||||
|
||||
// FIXME: We need to rearrange the code for copy/dispose so we have this
|
||||
// sooner, so we can calculate offsets correctly.
|
||||
if (!BlockHasCopyDispose)
|
||||
BlockOffset = CGM.getTargetData()
|
||||
.getTypeStoreSizeInBits(CGM.getGenericBlockLiteralType()) / 8;
|
||||
else
|
||||
BlockOffset = CGM.getTargetData()
|
||||
.getTypeStoreSizeInBits(CGM.getGenericExtendedBlockLiteralType()) / 8;
|
||||
BlockOffset = CGM.getTargetData()
|
||||
.getTypeStoreSizeInBits(CGM.getGenericBlockLiteralType()) / 8;
|
||||
BlockAlign = getContext().getTypeAlign(getContext().VoidPtrTy) / 8;
|
||||
|
||||
const FunctionType *BlockFunctionType = BExpr->getFunctionType();
|
||||
@ -630,13 +667,22 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
|
||||
|
||||
FunctionArgList Args;
|
||||
|
||||
CurFuncDecl = OuterFuncDecl;
|
||||
|
||||
const BlockDecl *BD = BExpr->getBlockDecl();
|
||||
|
||||
IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor");
|
||||
|
||||
// Allocate all BlockDeclRefDecls, so we can calculate the right ParmTy below.
|
||||
AllocateAllBlockDeclRefs(Info, this);
|
||||
|
||||
QualType ParmTy = getContext().getBlockParmType(BlockHasCopyDispose,
|
||||
BlockDeclRefDecls);
|
||||
// FIXME: This leaks
|
||||
ImplicitParamDecl *SelfDecl =
|
||||
ImplicitParamDecl::Create(getContext(), 0,
|
||||
SourceLocation(), 0,
|
||||
getContext().getPointerType(getContext().VoidTy));
|
||||
SourceLocation(), II,
|
||||
ParmTy);
|
||||
|
||||
Args.push_back(std::make_pair(SelfDecl, SelfDecl->getType()));
|
||||
BlockStructDecl = SelfDecl;
|
||||
@ -758,11 +804,13 @@ GenerateCopyHelperFunction(bool BlockHasCopyDispose, const llvm::StructType *T,
|
||||
FunctionArgList Args;
|
||||
// FIXME: This leaks
|
||||
ImplicitParamDecl *Dst =
|
||||
ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
|
||||
ImplicitParamDecl::Create(getContext(), 0,
|
||||
SourceLocation(), 0,
|
||||
getContext().getPointerType(getContext().VoidTy));
|
||||
Args.push_back(std::make_pair(Dst, Dst->getType()));
|
||||
ImplicitParamDecl *Src =
|
||||
ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
|
||||
ImplicitParamDecl::Create(getContext(), 0,
|
||||
SourceLocation(), 0,
|
||||
getContext().getPointerType(getContext().VoidTy));
|
||||
Args.push_back(std::make_pair(Src, Src->getType()));
|
||||
|
||||
@ -843,7 +891,8 @@ GenerateDestroyHelperFunction(bool BlockHasCopyDispose,
|
||||
FunctionArgList Args;
|
||||
// FIXME: This leaks
|
||||
ImplicitParamDecl *Src =
|
||||
ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
|
||||
ImplicitParamDecl::Create(getContext(), 0,
|
||||
SourceLocation(), 0,
|
||||
getContext().getPointerType(getContext().VoidTy));
|
||||
|
||||
Args.push_back(std::make_pair(Src, Src->getType()));
|
||||
@ -922,13 +971,15 @@ GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) {
|
||||
FunctionArgList Args;
|
||||
// FIXME: This leaks
|
||||
ImplicitParamDecl *Dst =
|
||||
ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
|
||||
ImplicitParamDecl::Create(getContext(), 0,
|
||||
SourceLocation(), 0,
|
||||
getContext().getPointerType(getContext().VoidTy));
|
||||
Args.push_back(std::make_pair(Dst, Dst->getType()));
|
||||
|
||||
// FIXME: This leaks
|
||||
ImplicitParamDecl *Src =
|
||||
ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
|
||||
ImplicitParamDecl::Create(getContext(), 0,
|
||||
SourceLocation(), 0,
|
||||
getContext().getPointerType(getContext().VoidTy));
|
||||
Args.push_back(std::make_pair(Src, Src->getType()));
|
||||
|
||||
@ -991,7 +1042,8 @@ BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T,
|
||||
FunctionArgList Args;
|
||||
// FIXME: This leaks
|
||||
ImplicitParamDecl *Src =
|
||||
ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
|
||||
ImplicitParamDecl::Create(getContext(), 0,
|
||||
SourceLocation(), 0,
|
||||
getContext().getPointerType(getContext().VoidTy));
|
||||
|
||||
Args.push_back(std::make_pair(Src, Src->getType()));
|
||||
|
@ -115,15 +115,8 @@ class BlockModule : public BlockBase {
|
||||
PtrToInt8Ty = llvm::Type::getInt8PtrTy(M.getContext());
|
||||
}
|
||||
|
||||
bool BlockRequiresCopying(QualType Ty) {
|
||||
if (Ty->isBlockPointerType())
|
||||
return true;
|
||||
if (getContext().isObjCNSObjectType(Ty))
|
||||
return true;
|
||||
if (Ty->isObjCObjectPointerType())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
bool BlockRequiresCopying(QualType Ty)
|
||||
{ return getContext().BlockRequiresCopying(Ty); }
|
||||
};
|
||||
|
||||
class BlockFunction : public BlockBase {
|
||||
@ -165,11 +158,7 @@ class BlockFunction : public BlockBase {
|
||||
|
||||
/// ByCopyDeclRefs - Variables from parent scopes that have been imported
|
||||
/// into this block.
|
||||
llvm::SmallVector<const BlockDeclRefExpr *, 8> ByCopyDeclRefs;
|
||||
|
||||
// ByRefDeclRefs - __block variables from parent scopes that have been
|
||||
// imported into this block.
|
||||
llvm::SmallVector<const BlockDeclRefExpr *, 8> ByRefDeclRefs;
|
||||
llvm::SmallVector<const BlockDeclRefExpr *, 8> DeclRefs;
|
||||
|
||||
BlockInfo(const llvm::Type *blt, const char *n)
|
||||
: BlockLiteralTy(blt), Name(n) {
|
||||
@ -228,7 +217,8 @@ class BlockFunction : public BlockBase {
|
||||
llvm::Value *getBlockObjectDispose();
|
||||
void BuildBlockRelease(llvm::Value *DeclPtr, int flag = BLOCK_FIELD_IS_BYREF);
|
||||
|
||||
bool BlockRequiresCopying(QualType Ty);
|
||||
bool BlockRequiresCopying(QualType Ty)
|
||||
{ return getContext().BlockRequiresCopying(Ty); }
|
||||
};
|
||||
|
||||
} // end namespace CodeGen
|
||||
|
@ -590,12 +590,15 @@ void
|
||||
CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest,
|
||||
const CXXConstructExpr *E) {
|
||||
assert(Dest && "Must have a destination!");
|
||||
|
||||
const CXXRecordDecl *RD =
|
||||
cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl());
|
||||
if (RD->hasTrivialConstructor())
|
||||
const CXXConstructorDecl *CD = E->getConstructor();
|
||||
// For a copy constructor, even if it is trivial, must fall thru so
|
||||
// its argument is code-gen'ed.
|
||||
if (!CD->isCopyConstructor(getContext())) {
|
||||
const CXXRecordDecl *RD =
|
||||
cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl());
|
||||
if (RD->hasTrivialConstructor())
|
||||
return;
|
||||
|
||||
}
|
||||
// Code gen optimization to eliminate copy constructor and return
|
||||
// its first argument instead.
|
||||
if (getContext().getLangOptions().ElideConstructors && E->isElidable()) {
|
||||
@ -604,7 +607,7 @@ CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest,
|
||||
return;
|
||||
}
|
||||
// Call the constructor.
|
||||
EmitCXXConstructorCall(E->getConstructor(), Ctor_Complete, Dest,
|
||||
EmitCXXConstructorCall(CD, Ctor_Complete, Dest,
|
||||
E->arg_begin(), E->arg_end());
|
||||
}
|
||||
|
||||
|
@ -639,9 +639,8 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
|
||||
// If this structure was expanded into multiple arguments then
|
||||
// we need to create a temporary and reconstruct it from the
|
||||
// arguments.
|
||||
std::string Name = Arg->getNameAsString();
|
||||
llvm::Value *Temp = CreateTempAlloca(ConvertTypeForMem(Ty),
|
||||
(Name + ".addr").c_str());
|
||||
Arg->getName() + ".addr");
|
||||
// FIXME: What are the right qualifiers here?
|
||||
llvm::Function::arg_iterator End =
|
||||
ExpandTypeFromArgs(Ty, LValue::MakeAddr(Temp, Qualifiers()), AI);
|
||||
@ -650,7 +649,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
|
||||
// Name the arguments used in expansion and increment AI.
|
||||
unsigned Index = 0;
|
||||
for (; AI != End; ++AI, ++Index)
|
||||
AI->setName(Name + "." + llvm::Twine(Index));
|
||||
AI->setName(Arg->getName() + "." + llvm::Twine(Index));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -173,10 +173,14 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT,
|
||||
uint64_t Align = M->getContext().getTypeAlign(BT);
|
||||
uint64_t Offset = 0;
|
||||
|
||||
return DebugFactory.CreateBasicType(Unit,
|
||||
BT->getName(M->getContext().getLangOptions()),
|
||||
Unit, 0, Size, Align,
|
||||
Offset, /*flags*/ 0, Encoding);
|
||||
llvm::DIType DbgTy =
|
||||
DebugFactory.CreateBasicType(Unit,
|
||||
BT->getName(M->getContext().getLangOptions()),
|
||||
Unit, 0, Size, Align,
|
||||
Offset, /*flags*/ 0, Encoding);
|
||||
|
||||
TypeCache[QualType(BT, 0).getAsOpaquePtr()] = DbgTy.getNode();
|
||||
return DbgTy;
|
||||
}
|
||||
|
||||
llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty,
|
||||
@ -190,9 +194,12 @@ llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty,
|
||||
uint64_t Align = M->getContext().getTypeAlign(Ty);
|
||||
uint64_t Offset = 0;
|
||||
|
||||
return DebugFactory.CreateBasicType(Unit, "complex",
|
||||
Unit, 0, Size, Align,
|
||||
Offset, /*flags*/ 0, Encoding);
|
||||
llvm::DIType DbgTy =
|
||||
DebugFactory.CreateBasicType(Unit, "complex",
|
||||
Unit, 0, Size, Align,
|
||||
Offset, /*flags*/ 0, Encoding);
|
||||
TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode();
|
||||
return DbgTy;
|
||||
}
|
||||
|
||||
/// CreateCVRType - Get the qualified type from the cache or create
|
||||
@ -226,8 +233,11 @@ llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DICompileUnit U
|
||||
|
||||
// No need to fill in the Name, Line, Size, Alignment, Offset in case of
|
||||
// CVR derived types.
|
||||
return DebugFactory.CreateDerivedType(Tag, Unit, "", llvm::DICompileUnit(),
|
||||
0, 0, 0, 0, 0, FromTy);
|
||||
llvm::DIType DbgTy =
|
||||
DebugFactory.CreateDerivedType(Tag, Unit, "", llvm::DICompileUnit(),
|
||||
0, 0, 0, 0, 0, FromTy);
|
||||
TypeCache[Ty.getAsOpaquePtr()] = DbgTy.getNode();
|
||||
return DbgTy;
|
||||
}
|
||||
|
||||
llvm::DIType CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty,
|
||||
@ -238,9 +248,12 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty,
|
||||
uint64_t Size = M->getContext().getTypeSize(Ty);
|
||||
uint64_t Align = M->getContext().getTypeAlign(Ty);
|
||||
|
||||
return DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit,
|
||||
"", llvm::DICompileUnit(),
|
||||
0, Size, Align, 0, 0, EltTy);
|
||||
llvm::DIType DbgTy =
|
||||
DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit,
|
||||
"", llvm::DICompileUnit(),
|
||||
0, Size, Align, 0, 0, EltTy);
|
||||
TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode();
|
||||
return DbgTy;
|
||||
}
|
||||
|
||||
llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty,
|
||||
@ -251,9 +264,10 @@ llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty,
|
||||
uint64_t Size = M->getContext().getTypeSize(Ty);
|
||||
uint64_t Align = M->getContext().getTypeAlign(Ty);
|
||||
|
||||
return DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit,
|
||||
"", llvm::DICompileUnit(),
|
||||
0, Size, Align, 0, 0, EltTy);
|
||||
return
|
||||
DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit,
|
||||
"", llvm::DICompileUnit(),
|
||||
0, Size, Align, 0, 0, EltTy);
|
||||
}
|
||||
|
||||
llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
|
||||
@ -401,8 +415,11 @@ llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty,
|
||||
PresumedLoc PLoc = SM.getPresumedLoc(DefLoc);
|
||||
unsigned Line = PLoc.isInvalid() ? 0 : PLoc.getLine();
|
||||
|
||||
return DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_typedef, Unit,
|
||||
TyName, DefUnit, Line, 0, 0, 0, 0, Src);
|
||||
llvm::DIType DbgTy =
|
||||
DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_typedef, Unit,
|
||||
TyName, DefUnit, Line, 0, 0, 0, 0, Src);
|
||||
TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode();
|
||||
return DbgTy;
|
||||
}
|
||||
|
||||
llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty,
|
||||
@ -424,10 +441,13 @@ llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty,
|
||||
llvm::DIArray EltTypeArray =
|
||||
DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
|
||||
|
||||
return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type,
|
||||
Unit, "", llvm::DICompileUnit(),
|
||||
0, 0, 0, 0, 0,
|
||||
llvm::DIType(), EltTypeArray);
|
||||
llvm::DIType DbgTy =
|
||||
DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type,
|
||||
Unit, "", llvm::DICompileUnit(),
|
||||
0, 0, 0, 0, 0,
|
||||
llvm::DIType(), EltTypeArray);
|
||||
TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode();
|
||||
return DbgTy;
|
||||
}
|
||||
|
||||
/// CreateType - get structure or union type.
|
||||
@ -713,10 +733,14 @@ llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty,
|
||||
Align = M->getContext().getTypeAlign(Ty);
|
||||
}
|
||||
|
||||
return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_enumeration_type,
|
||||
Unit, EnumName, DefUnit, Line,
|
||||
Size, Align, 0, 0,
|
||||
llvm::DIType(), EltArray);
|
||||
llvm::DIType DbgTy =
|
||||
DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_enumeration_type,
|
||||
Unit, EnumName, DefUnit, Line,
|
||||
Size, Align, 0, 0,
|
||||
llvm::DIType(), EltArray);
|
||||
|
||||
TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode();
|
||||
return DbgTy;
|
||||
}
|
||||
|
||||
llvm::DIType CGDebugInfo::CreateType(const TagType *Ty,
|
||||
@ -767,11 +791,15 @@ llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
|
||||
llvm::DIArray SubscriptArray =
|
||||
DebugFactory.GetOrCreateArray(Subscripts.data(), Subscripts.size());
|
||||
|
||||
return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_array_type,
|
||||
Unit, "", llvm::DICompileUnit(),
|
||||
0, Size, Align, 0, 0,
|
||||
getOrCreateType(EltTy, Unit),
|
||||
SubscriptArray);
|
||||
llvm::DIType DbgTy =
|
||||
DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_array_type,
|
||||
Unit, "", llvm::DICompileUnit(),
|
||||
0, Size, Align, 0, 0,
|
||||
getOrCreateType(EltTy, Unit),
|
||||
SubscriptArray);
|
||||
|
||||
TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode();
|
||||
return DbgTy;
|
||||
}
|
||||
|
||||
|
||||
@ -793,7 +821,6 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty,
|
||||
|
||||
// Otherwise create the type.
|
||||
llvm::DIType Res = CreateTypeNode(Ty, Unit);
|
||||
TypeCache.insert(std::make_pair(Ty.getAsOpaquePtr(), Res.getNode()));
|
||||
return Res;
|
||||
}
|
||||
|
||||
@ -846,8 +873,6 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty,
|
||||
Unit);
|
||||
|
||||
case Type::ConstantArray:
|
||||
case Type::ConstantArrayWithExpr:
|
||||
case Type::ConstantArrayWithoutExpr:
|
||||
case Type::VariableArray:
|
||||
case Type::IncompleteArray:
|
||||
return CreateType(cast<ArrayType>(Ty), Unit);
|
||||
@ -863,7 +888,7 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty,
|
||||
|
||||
/// EmitFunctionStart - Constructs the debug code for entering a function -
|
||||
/// "llvm.dbg.func.start.".
|
||||
void CGDebugInfo::EmitFunctionStart(const char *Name, QualType ReturnType,
|
||||
void CGDebugInfo::EmitFunctionStart(const char *Name, QualType FnType,
|
||||
llvm::Function *Fn,
|
||||
CGBuilderTy &Builder) {
|
||||
const char *LinkageName = Name;
|
||||
@ -881,7 +906,7 @@ void CGDebugInfo::EmitFunctionStart(const char *Name, QualType ReturnType,
|
||||
|
||||
llvm::DISubprogram SP =
|
||||
DebugFactory.CreateSubprogram(Unit, Name, Name, LinkageName, Unit, LineNo,
|
||||
getOrCreateType(ReturnType, Unit),
|
||||
getOrCreateType(FnType, Unit),
|
||||
Fn->hasInternalLinkage(), true/*definition*/);
|
||||
|
||||
#ifndef ATTACH_DEBUG_INFO_TO_AN_INSN
|
||||
@ -1366,7 +1391,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
|
||||
}
|
||||
|
||||
DebugFactory.CreateGlobalVariable(getContext(Decl, Unit),
|
||||
Name, Name, "", Unit, LineNo,
|
||||
Name, Name, Name, Unit, LineNo,
|
||||
getOrCreateType(T, Unit),
|
||||
Var->hasInternalLinkage(),
|
||||
true/*definition*/, Var);
|
||||
@ -1396,7 +1421,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
|
||||
ArrayType::Normal, 0);
|
||||
}
|
||||
|
||||
DebugFactory.CreateGlobalVariable(Unit, Name, Name, "", Unit, LineNo,
|
||||
DebugFactory.CreateGlobalVariable(Unit, Name, Name, Name, Unit, LineNo,
|
||||
getOrCreateType(T, Unit),
|
||||
Var->hasInternalLinkage(),
|
||||
true/*definition*/, Var);
|
||||
|
@ -88,7 +88,7 @@ class CGDebugInfo {
|
||||
|
||||
/// EmitFunctionStart - Emit a call to llvm.dbg.function.start to indicate
|
||||
/// start of a new function.
|
||||
void EmitFunctionStart(const char *Name, QualType ReturnType,
|
||||
void EmitFunctionStart(const char *Name, QualType FnType,
|
||||
llvm::Function *Fn, CGBuilderTy &Builder);
|
||||
|
||||
/// EmitRegionStart - Emit a call to llvm.dbg.region.start to indicate start
|
||||
|
@ -37,6 +37,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
|
||||
case Decl::Enum: // enum X;
|
||||
case Decl::EnumConstant: // enum ? { X = ? }
|
||||
case Decl::CXXRecord: // struct/union/class X; [C++]
|
||||
case Decl::UsingDirective: // using X; [C++]
|
||||
// None of these decls require codegen support.
|
||||
return;
|
||||
|
||||
@ -275,8 +276,8 @@ const llvm::Type *CodeGenFunction::BuildByRefType(const ValueDecl *D) {
|
||||
unsigned NumPaddingBytes = AlignedOffsetInBytes - CurrentOffsetInBytes;
|
||||
if (NumPaddingBytes > 0) {
|
||||
const llvm::Type *Ty = llvm::Type::getInt8Ty(VMContext);
|
||||
// FIXME: We need a sema error for alignment larger than the minimum of the
|
||||
// maximal stack alignmint and the alignment of malloc on the system.
|
||||
// FIXME: We need a sema error for alignment larger than the minimum of
|
||||
// the maximal stack alignmint and the alignment of malloc on the system.
|
||||
if (NumPaddingBytes > 1)
|
||||
Ty = llvm::ArrayType::get(Ty, NumPaddingBytes);
|
||||
|
||||
|
@ -28,9 +28,9 @@ using namespace CodeGen;
|
||||
/// CreateTempAlloca - This creates a alloca and inserts it into the entry
|
||||
/// block.
|
||||
llvm::AllocaInst *CodeGenFunction::CreateTempAlloca(const llvm::Type *Ty,
|
||||
const char *Name) {
|
||||
const llvm::Twine &Name) {
|
||||
if (!Builder.isNamePreserving())
|
||||
Name = "";
|
||||
return new llvm::AllocaInst(Ty, 0, "", AllocaInsertPt);
|
||||
return new llvm::AllocaInst(Ty, 0, Name, AllocaInsertPt);
|
||||
}
|
||||
|
||||
@ -78,24 +78,18 @@ RValue CodeGenFunction::EmitAnyExprToTemp(const Expr *E,
|
||||
RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
|
||||
QualType DestType,
|
||||
bool IsInitializer) {
|
||||
bool ShouldDestroyTemporaries = false;
|
||||
unsigned OldNumLiveTemporaries = 0;
|
||||
|
||||
if (const CXXExprWithTemporaries *TE = dyn_cast<CXXExprWithTemporaries>(E)) {
|
||||
// If we shouldn't destroy the temporaries, just emit the
|
||||
// child expression.
|
||||
if (!TE->shouldDestroyTemporaries())
|
||||
return EmitReferenceBindingToExpr(TE->getSubExpr(), DestType,
|
||||
IsInitializer);
|
||||
ShouldDestroyTemporaries = TE->shouldDestroyTemporaries();
|
||||
|
||||
if (ShouldDestroyTemporaries) {
|
||||
// Keep track of the current cleanup stack depth.
|
||||
OldNumLiveTemporaries = LiveTemporaries.size();
|
||||
}
|
||||
|
||||
// Keep track of the current cleanup stack depth.
|
||||
unsigned OldNumLiveTemporaries = LiveTemporaries.size();
|
||||
|
||||
RValue RV = EmitReferenceBindingToExpr(TE->getSubExpr(), DestType,
|
||||
IsInitializer);
|
||||
|
||||
// Pop temporaries.
|
||||
while (LiveTemporaries.size() > OldNumLiveTemporaries)
|
||||
PopCXXTemporary();
|
||||
|
||||
return RV;
|
||||
E = TE->getSubExpr();
|
||||
}
|
||||
|
||||
RValue Val;
|
||||
@ -105,6 +99,12 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
|
||||
if (LV.isSimple())
|
||||
return RValue::get(LV.getAddress());
|
||||
Val = EmitLoadOfLValue(LV, E->getType());
|
||||
|
||||
if (ShouldDestroyTemporaries) {
|
||||
// Pop temporaries.
|
||||
while (LiveTemporaries.size() > OldNumLiveTemporaries)
|
||||
PopCXXTemporary();
|
||||
}
|
||||
} else {
|
||||
const CXXRecordDecl *BaseClassDecl = 0;
|
||||
const CXXRecordDecl *DerivedClassDecl = 0;
|
||||
@ -124,6 +124,12 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
|
||||
Val = EmitAnyExprToTemp(E, /*IsAggLocVolatile=*/false,
|
||||
IsInitializer);
|
||||
|
||||
if (ShouldDestroyTemporaries) {
|
||||
// Pop temporaries.
|
||||
while (LiveTemporaries.size() > OldNumLiveTemporaries)
|
||||
PopCXXTemporary();
|
||||
}
|
||||
|
||||
if (IsInitializer) {
|
||||
// We might have to destroy the temporary variable.
|
||||
if (const RecordType *RT = E->getType()->getAs<RecordType>()) {
|
||||
@ -297,6 +303,8 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
|
||||
case Expr::CXXReinterpretCastExprClass:
|
||||
case Expr::CXXConstCastExprClass:
|
||||
return EmitCastLValue(cast<CastExpr>(E));
|
||||
case Expr::CXXZeroInitValueExprClass:
|
||||
return EmitNullInitializationLValue(cast<CXXZeroInitValueExpr>(E));
|
||||
}
|
||||
}
|
||||
|
||||
@ -858,6 +866,9 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
|
||||
llvm::Value *V = LocalDeclMap[IPD];
|
||||
assert(V && "BlockVarDecl not entered in LocalDeclMap?");
|
||||
return LValue::MakeAddr(V, MakeQualifiers(E->getType()));
|
||||
} else if (const QualifiedDeclRefExpr *QDRExpr =
|
||||
dyn_cast<QualifiedDeclRefExpr>(E)) {
|
||||
return EmitPointerToDataMemberLValue(QDRExpr);
|
||||
}
|
||||
assert(0 && "Unimp declref");
|
||||
//an invalid LValue, but the assert will
|
||||
@ -1307,6 +1318,18 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
|
||||
}
|
||||
}
|
||||
|
||||
LValue CodeGenFunction::EmitNullInitializationLValue(
|
||||
const CXXZeroInitValueExpr *E) {
|
||||
QualType Ty = E->getType();
|
||||
const llvm::Type *LTy = ConvertTypeForMem(Ty);
|
||||
llvm::AllocaInst *Alloc = CreateTempAlloca(LTy);
|
||||
unsigned Align = getContext().getTypeAlign(Ty)/8;
|
||||
Alloc->setAlignment(Align);
|
||||
LValue lvalue = LValue::MakeAddr(Alloc, Qualifiers());
|
||||
EmitMemSetToZero(lvalue.getAddress(), Ty);
|
||||
return lvalue;
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Expression Emission
|
||||
//===--------------------------------------------------------------------===//
|
||||
@ -1356,11 +1379,24 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {
|
||||
return EmitLValue(E->getRHS());
|
||||
}
|
||||
|
||||
if (E->getOpcode() == BinaryOperator::PtrMemD)
|
||||
return EmitPointerToDataMemberBinaryExpr(E);
|
||||
|
||||
// Can only get l-value for binary operator expressions which are a
|
||||
// simple assignment of aggregate type.
|
||||
if (E->getOpcode() != BinaryOperator::Assign)
|
||||
return EmitUnsupportedLValue(E, "binary l-value expression");
|
||||
|
||||
if (!hasAggregateLLVMType(E->getType())) {
|
||||
// Emit the LHS as an l-value.
|
||||
LValue LV = EmitLValue(E->getLHS());
|
||||
|
||||
llvm::Value *RHS = EmitScalarExpr(E->getRHS());
|
||||
EmitStoreOfScalar(RHS, LV.getAddress(), LV.isVolatileQualified(),
|
||||
E->getType());
|
||||
return LV;
|
||||
}
|
||||
|
||||
llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType()));
|
||||
EmitAggExpr(E, Temp, false);
|
||||
// FIXME: Are these qualifiers correct?
|
||||
@ -1483,6 +1519,25 @@ LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) {
|
||||
}
|
||||
|
||||
|
||||
LValue CodeGenFunction::EmitPointerToDataMemberLValue(
|
||||
const QualifiedDeclRefExpr *E) {
|
||||
const FieldDecl *Field = cast<FieldDecl>(E->getDecl());
|
||||
const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Field->getDeclContext());
|
||||
QualType NNSpecTy =
|
||||
getContext().getCanonicalType(
|
||||
getContext().getTypeDeclType(const_cast<CXXRecordDecl*>(ClassDecl)));
|
||||
NNSpecTy = getContext().getPointerType(NNSpecTy);
|
||||
llvm::Value *V = llvm::Constant::getNullValue(ConvertType(NNSpecTy));
|
||||
LValue MemExpLV = EmitLValueForField(V, const_cast<FieldDecl*>(Field),
|
||||
/*isUnion*/false, /*Qualifiers*/0);
|
||||
const llvm::Type* ResultType = ConvertType(
|
||||
getContext().getPointerDiffType());
|
||||
V = Builder.CreatePtrToInt(MemExpLV.getAddress(), ResultType,
|
||||
"datamember");
|
||||
LValue LV = LValue::MakeAddr(V, MakeQualifiers(E->getType()));
|
||||
return LV;
|
||||
}
|
||||
|
||||
RValue CodeGenFunction::EmitCall(llvm::Value *Callee, QualType CalleeType,
|
||||
CallExpr::const_arg_iterator ArgBeg,
|
||||
CallExpr::const_arg_iterator ArgEnd,
|
||||
@ -1492,11 +1547,13 @@ RValue CodeGenFunction::EmitCall(llvm::Value *Callee, QualType CalleeType,
|
||||
assert(CalleeType->isFunctionPointerType() &&
|
||||
"Call must have function pointer type!");
|
||||
|
||||
QualType FnType = CalleeType->getAs<PointerType>()->getPointeeType();
|
||||
QualType ResultType = FnType->getAs<FunctionType>()->getResultType();
|
||||
CalleeType = getContext().getCanonicalType(CalleeType);
|
||||
|
||||
QualType FnType = cast<PointerType>(CalleeType)->getPointeeType();
|
||||
QualType ResultType = cast<FunctionType>(FnType)->getResultType();
|
||||
|
||||
CallArgList Args;
|
||||
EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(), ArgBeg, ArgEnd);
|
||||
EmitCallArgs(Args, dyn_cast<FunctionProtoType>(FnType), ArgBeg, ArgEnd);
|
||||
|
||||
// FIXME: We should not need to do this, it should be part of the function
|
||||
// type.
|
||||
@ -1508,3 +1565,25 @@ RValue CodeGenFunction::EmitCall(llvm::Value *Callee, QualType CalleeType,
|
||||
CallingConvention),
|
||||
Callee, Args, TargetDecl);
|
||||
}
|
||||
|
||||
LValue CodeGenFunction::EmitPointerToDataMemberBinaryExpr(
|
||||
const BinaryOperator *E) {
|
||||
llvm::Value *BaseV = EmitLValue(E->getLHS()).getAddress();
|
||||
const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(getLLVMContext());
|
||||
BaseV = Builder.CreateBitCast(BaseV, i8Ty);
|
||||
LValue RHSLV = EmitLValue(E->getRHS());
|
||||
llvm::Value *OffsetV =
|
||||
EmitLoadOfLValue(RHSLV, E->getRHS()->getType()).getScalarVal();
|
||||
const llvm::Type* ResultType = ConvertType(getContext().getPointerDiffType());
|
||||
OffsetV = Builder.CreateBitCast(OffsetV, ResultType);
|
||||
llvm::Value *AddV = Builder.CreateInBoundsGEP(BaseV, OffsetV, "add.ptr");
|
||||
QualType Ty = E->getRHS()->getType();
|
||||
const MemberPointerType *MemPtrType = Ty->getAs<MemberPointerType>();
|
||||
Ty = MemPtrType->getPointeeType();
|
||||
const llvm::Type* PType =
|
||||
ConvertType(getContext().getPointerType(Ty));
|
||||
AddV = Builder.CreateBitCast(AddV, PType);
|
||||
LValue LV = LValue::MakeAddr(AddV, MakeQualifiers(Ty));
|
||||
return LV;
|
||||
}
|
||||
|
||||
|
@ -92,6 +92,7 @@ class VISIBILITY_HIDDEN AggExprEmitter : public StmtVisitor<AggExprEmitter> {
|
||||
void VisitCallExpr(const CallExpr *E);
|
||||
void VisitStmtExpr(const StmtExpr *E);
|
||||
void VisitBinaryOperator(const BinaryOperator *BO);
|
||||
void VisitPointerToDataMemberBinaryOperator(const BinaryOperator *BO);
|
||||
void VisitBinAssign(const BinaryOperator *E);
|
||||
void VisitBinComma(const BinaryOperator *E);
|
||||
void VisitUnaryAddrOf(const UnaryOperator *E);
|
||||
@ -112,6 +113,7 @@ class VISIBILITY_HIDDEN AggExprEmitter : public StmtVisitor<AggExprEmitter> {
|
||||
void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);
|
||||
void VisitCXXConstructExpr(const CXXConstructExpr *E);
|
||||
void VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E);
|
||||
void VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E);
|
||||
|
||||
void VisitVAArgExpr(VAArgExpr *E);
|
||||
|
||||
@ -214,6 +216,12 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
|
||||
break;
|
||||
}
|
||||
|
||||
case CastExpr::CK_BitCast: {
|
||||
// This must be a member function pointer cast.
|
||||
Visit(E->getSubExpr());
|
||||
break;
|
||||
}
|
||||
|
||||
case CastExpr::CK_BaseToDerivedMemberPointer: {
|
||||
QualType SrcType = E->getSubExpr()->getType();
|
||||
|
||||
@ -285,6 +293,7 @@ void AggExprEmitter::VisitBinComma(const BinaryOperator *E) {
|
||||
void AggExprEmitter::VisitUnaryAddrOf(const UnaryOperator *E) {
|
||||
// We have a member function pointer.
|
||||
const MemberPointerType *MPT = E->getType()->getAs<MemberPointerType>();
|
||||
(void) MPT;
|
||||
assert(MPT->getPointeeType()->isFunctionProtoType() &&
|
||||
"Unexpected member pointer type!");
|
||||
|
||||
@ -320,7 +329,16 @@ void AggExprEmitter::VisitStmtExpr(const StmtExpr *E) {
|
||||
}
|
||||
|
||||
void AggExprEmitter::VisitBinaryOperator(const BinaryOperator *E) {
|
||||
CGF.ErrorUnsupported(E, "aggregate binary expression");
|
||||
if (E->getOpcode() == BinaryOperator::PtrMemD)
|
||||
VisitPointerToDataMemberBinaryOperator(E);
|
||||
else
|
||||
CGF.ErrorUnsupported(E, "aggregate binary expression");
|
||||
}
|
||||
|
||||
void AggExprEmitter::VisitPointerToDataMemberBinaryOperator(
|
||||
const BinaryOperator *E) {
|
||||
LValue LV = CGF.EmitPointerToDataMemberBinaryExpr(E);
|
||||
EmitFinalDestCopy(E, LV);
|
||||
}
|
||||
|
||||
void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) {
|
||||
@ -438,6 +456,11 @@ void AggExprEmitter::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) {
|
||||
CGF.EmitCXXExprWithTemporaries(E, DestPtr, VolatileDest, IsInitializer);
|
||||
}
|
||||
|
||||
void AggExprEmitter::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) {
|
||||
LValue lvalue = LValue::MakeAddr(DestPtr, Qualifiers());
|
||||
EmitNullInitializationToLValue(lvalue, E->getType());
|
||||
}
|
||||
|
||||
void AggExprEmitter::EmitInitializationToLValue(Expr* E, LValue LV) {
|
||||
// FIXME: Ignore result?
|
||||
// FIXME: Are initializers affected by volatile?
|
||||
|
@ -542,7 +542,11 @@ class VISIBILITY_HIDDEN ConstExprEmitter :
|
||||
return CS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
case CastExpr::CK_BitCast:
|
||||
// This must be a member function pointer cast.
|
||||
return Visit(E->getSubExpr());
|
||||
|
||||
default: {
|
||||
// FIXME: This should be handled by the CK_NoOp cast kind.
|
||||
// Explicit and implicit no-op casts
|
||||
|
@ -106,6 +106,7 @@ class VISIBILITY_HIDDEN ScalarExprEmitter
|
||||
return 0;
|
||||
}
|
||||
Value *VisitExpr(Expr *S);
|
||||
|
||||
Value *VisitParenExpr(ParenExpr *PE) { return Visit(PE->getSubExpr()); }
|
||||
|
||||
// Leaves.
|
||||
@ -181,48 +182,7 @@ class VISIBILITY_HIDDEN ScalarExprEmitter
|
||||
|
||||
Value *VisitPredefinedExpr(Expr *E) { return EmitLValue(E).getAddress(); }
|
||||
|
||||
Value *VisitInitListExpr(InitListExpr *E) {
|
||||
bool Ignore = TestAndClearIgnoreResultAssign();
|
||||
(void)Ignore;
|
||||
assert (Ignore == false && "init list ignored");
|
||||
unsigned NumInitElements = E->getNumInits();
|
||||
|
||||
if (E->hadArrayRangeDesignator()) {
|
||||
CGF.ErrorUnsupported(E, "GNU array range designator extension");
|
||||
}
|
||||
|
||||
const llvm::VectorType *VType =
|
||||
dyn_cast<llvm::VectorType>(ConvertType(E->getType()));
|
||||
|
||||
// We have a scalar in braces. Just use the first element.
|
||||
if (!VType)
|
||||
return Visit(E->getInit(0));
|
||||
|
||||
unsigned NumVectorElements = VType->getNumElements();
|
||||
const llvm::Type *ElementType = VType->getElementType();
|
||||
|
||||
// Emit individual vector element stores.
|
||||
llvm::Value *V = llvm::UndefValue::get(VType);
|
||||
|
||||
// Emit initializers
|
||||
unsigned i;
|
||||
for (i = 0; i < NumInitElements; ++i) {
|
||||
Value *NewV = Visit(E->getInit(i));
|
||||
Value *Idx =
|
||||
llvm::ConstantInt::get(llvm::Type::getInt32Ty(CGF.getLLVMContext()), i);
|
||||
V = Builder.CreateInsertElement(V, NewV, Idx);
|
||||
}
|
||||
|
||||
// Emit remaining default initializers
|
||||
for (/* Do not initialize i*/; i < NumVectorElements; ++i) {
|
||||
Value *Idx =
|
||||
llvm::ConstantInt::get(llvm::Type::getInt32Ty(CGF.getLLVMContext()), i);
|
||||
llvm::Value *NewV = llvm::Constant::getNullValue(ElementType);
|
||||
V = Builder.CreateInsertElement(V, NewV, Idx);
|
||||
}
|
||||
|
||||
return V;
|
||||
}
|
||||
Value *VisitInitListExpr(InitListExpr *E);
|
||||
|
||||
Value *VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) {
|
||||
return llvm::Constant::getNullValue(ConvertType(E->getType()));
|
||||
@ -404,7 +364,7 @@ class VISIBILITY_HIDDEN ScalarExprEmitter
|
||||
/// EmitConversionToBool - Convert the specified expression value to a
|
||||
/// boolean (i1) truth value. This is equivalent to "Val != 0".
|
||||
Value *ScalarExprEmitter::EmitConversionToBool(Value *Src, QualType SrcType) {
|
||||
assert(SrcType->isCanonical() && "EmitScalarConversion strips typedefs");
|
||||
assert(SrcType.isCanonical() && "EmitScalarConversion strips typedefs");
|
||||
|
||||
if (SrcType->isRealFloatingType()) {
|
||||
// Compare against 0.0 for fp scalars.
|
||||
@ -577,6 +537,13 @@ EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src,
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
Value *ScalarExprEmitter::VisitExpr(Expr *E) {
|
||||
if (const BinaryOperator *BExpr = dyn_cast<BinaryOperator>(E))
|
||||
if (BExpr->getOpcode() == BinaryOperator::PtrMemD) {
|
||||
LValue LV = CGF.EmitPointerToDataMemberBinaryExpr(BExpr);
|
||||
Value *InVal = CGF.EmitLoadOfLValue(LV, E->getType()).getScalarVal();
|
||||
return InVal;
|
||||
}
|
||||
|
||||
CGF.ErrorUnsupported(E, "scalar expression");
|
||||
if (E->getType()->isVoidType())
|
||||
return 0;
|
||||
@ -616,6 +583,174 @@ Value *ScalarExprEmitter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
|
||||
return Builder.CreateExtractElement(Base, Idx, "vecext");
|
||||
}
|
||||
|
||||
static llvm::Constant *getMaskElt(llvm::ShuffleVectorInst *SVI, unsigned Idx,
|
||||
unsigned Off, const llvm::Type *I32Ty) {
|
||||
int MV = SVI->getMaskValue(Idx);
|
||||
if (MV == -1)
|
||||
return llvm::UndefValue::get(I32Ty);
|
||||
return llvm::ConstantInt::get(I32Ty, Off+MV);
|
||||
}
|
||||
|
||||
Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) {
|
||||
bool Ignore = TestAndClearIgnoreResultAssign();
|
||||
(void)Ignore;
|
||||
assert (Ignore == false && "init list ignored");
|
||||
unsigned NumInitElements = E->getNumInits();
|
||||
|
||||
if (E->hadArrayRangeDesignator())
|
||||
CGF.ErrorUnsupported(E, "GNU array range designator extension");
|
||||
|
||||
const llvm::VectorType *VType =
|
||||
dyn_cast<llvm::VectorType>(ConvertType(E->getType()));
|
||||
|
||||
// We have a scalar in braces. Just use the first element.
|
||||
if (!VType)
|
||||
return Visit(E->getInit(0));
|
||||
|
||||
unsigned ResElts = VType->getNumElements();
|
||||
const llvm::Type *I32Ty = llvm::Type::getInt32Ty(CGF.getLLVMContext());
|
||||
|
||||
// Loop over initializers collecting the Value for each, and remembering
|
||||
// whether the source was swizzle (ExtVectorElementExpr). This will allow
|
||||
// us to fold the shuffle for the swizzle into the shuffle for the vector
|
||||
// initializer, since LLVM optimizers generally do not want to touch
|
||||
// shuffles.
|
||||
unsigned CurIdx = 0;
|
||||
bool VIsUndefShuffle = false;
|
||||
llvm::Value *V = llvm::UndefValue::get(VType);
|
||||
for (unsigned i = 0; i != NumInitElements; ++i) {
|
||||
Expr *IE = E->getInit(i);
|
||||
Value *Init = Visit(IE);
|
||||
llvm::SmallVector<llvm::Constant*, 16> Args;
|
||||
|
||||
const llvm::VectorType *VVT = dyn_cast<llvm::VectorType>(Init->getType());
|
||||
|
||||
// Handle scalar elements. If the scalar initializer is actually one
|
||||
// element of a different vector of the same width, use shuffle instead of
|
||||
// extract+insert.
|
||||
if (!VVT) {
|
||||
if (isa<ExtVectorElementExpr>(IE)) {
|
||||
llvm::ExtractElementInst *EI = cast<llvm::ExtractElementInst>(Init);
|
||||
|
||||
if (EI->getVectorOperandType()->getNumElements() == ResElts) {
|
||||
llvm::ConstantInt *C = cast<llvm::ConstantInt>(EI->getIndexOperand());
|
||||
Value *LHS = 0, *RHS = 0;
|
||||
if (CurIdx == 0) {
|
||||
// insert into undef -> shuffle (src, undef)
|
||||
Args.push_back(C);
|
||||
for (unsigned j = 1; j != ResElts; ++j)
|
||||
Args.push_back(llvm::UndefValue::get(I32Ty));
|
||||
|
||||
LHS = EI->getVectorOperand();
|
||||
RHS = V;
|
||||
VIsUndefShuffle = true;
|
||||
} else if (VIsUndefShuffle) {
|
||||
// insert into undefshuffle && size match -> shuffle (v, src)
|
||||
llvm::ShuffleVectorInst *SVV = cast<llvm::ShuffleVectorInst>(V);
|
||||
for (unsigned j = 0; j != CurIdx; ++j)
|
||||
Args.push_back(getMaskElt(SVV, j, 0, I32Ty));
|
||||
Args.push_back(llvm::ConstantInt::get(I32Ty,
|
||||
ResElts + C->getZExtValue()));
|
||||
for (unsigned j = CurIdx + 1; j != ResElts; ++j)
|
||||
Args.push_back(llvm::UndefValue::get(I32Ty));
|
||||
|
||||
LHS = cast<llvm::ShuffleVectorInst>(V)->getOperand(0);
|
||||
RHS = EI->getVectorOperand();
|
||||
VIsUndefShuffle = false;
|
||||
}
|
||||
if (!Args.empty()) {
|
||||
llvm::Constant *Mask = llvm::ConstantVector::get(&Args[0], ResElts);
|
||||
V = Builder.CreateShuffleVector(LHS, RHS, Mask);
|
||||
++CurIdx;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
Value *Idx = llvm::ConstantInt::get(I32Ty, CurIdx);
|
||||
V = Builder.CreateInsertElement(V, Init, Idx, "vecinit");
|
||||
VIsUndefShuffle = false;
|
||||
++CurIdx;
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned InitElts = VVT->getNumElements();
|
||||
|
||||
// If the initializer is an ExtVecEltExpr (a swizzle), and the swizzle's
|
||||
// input is the same width as the vector being constructed, generate an
|
||||
// optimized shuffle of the swizzle input into the result.
|
||||
if (isa<ExtVectorElementExpr>(IE)) {
|
||||
llvm::ShuffleVectorInst *SVI = cast<llvm::ShuffleVectorInst>(Init);
|
||||
Value *SVOp = SVI->getOperand(0);
|
||||
const llvm::VectorType *OpTy = cast<llvm::VectorType>(SVOp->getType());
|
||||
|
||||
if (OpTy->getNumElements() == ResElts) {
|
||||
unsigned Offset = (CurIdx == 0) ? 0 : ResElts;
|
||||
|
||||
for (unsigned j = 0; j != CurIdx; ++j) {
|
||||
// If the current vector initializer is a shuffle with undef, merge
|
||||
// this shuffle directly into it.
|
||||
if (VIsUndefShuffle) {
|
||||
Args.push_back(getMaskElt(cast<llvm::ShuffleVectorInst>(V), j, 0,
|
||||
I32Ty));
|
||||
} else {
|
||||
Args.push_back(llvm::ConstantInt::get(I32Ty, j));
|
||||
}
|
||||
}
|
||||
for (unsigned j = 0, je = InitElts; j != je; ++j)
|
||||
Args.push_back(getMaskElt(SVI, j, Offset, I32Ty));
|
||||
for (unsigned j = CurIdx + InitElts; j != ResElts; ++j)
|
||||
Args.push_back(llvm::UndefValue::get(I32Ty));
|
||||
|
||||
if (VIsUndefShuffle)
|
||||
V = cast<llvm::ShuffleVectorInst>(V)->getOperand(0);
|
||||
|
||||
Init = SVOp;
|
||||
}
|
||||
}
|
||||
|
||||
// Extend init to result vector length, and then shuffle its contribution
|
||||
// to the vector initializer into V.
|
||||
if (Args.empty()) {
|
||||
for (unsigned j = 0; j != InitElts; ++j)
|
||||
Args.push_back(llvm::ConstantInt::get(I32Ty, j));
|
||||
for (unsigned j = InitElts; j != ResElts; ++j)
|
||||
Args.push_back(llvm::UndefValue::get(I32Ty));
|
||||
llvm::Constant *Mask = llvm::ConstantVector::get(&Args[0], ResElts);
|
||||
Init = Builder.CreateShuffleVector(Init, llvm::UndefValue::get(VVT),
|
||||
Mask, "vecext");
|
||||
|
||||
Args.clear();
|
||||
for (unsigned j = 0; j != CurIdx; ++j)
|
||||
Args.push_back(llvm::ConstantInt::get(I32Ty, j));
|
||||
for (unsigned j = 0; j != InitElts; ++j)
|
||||
Args.push_back(llvm::ConstantInt::get(I32Ty, j+ResElts));
|
||||
for (unsigned j = CurIdx + InitElts; j != ResElts; ++j)
|
||||
Args.push_back(llvm::UndefValue::get(I32Ty));
|
||||
}
|
||||
|
||||
// If V is undef, make sure it ends up on the RHS of the shuffle to aid
|
||||
// merging subsequent shuffles into this one.
|
||||
if (CurIdx == 0)
|
||||
std::swap(V, Init);
|
||||
llvm::Constant *Mask = llvm::ConstantVector::get(&Args[0], ResElts);
|
||||
V = Builder.CreateShuffleVector(V, Init, Mask, "vecinit");
|
||||
VIsUndefShuffle = isa<llvm::UndefValue>(Init);
|
||||
CurIdx += InitElts;
|
||||
}
|
||||
|
||||
// FIXME: evaluate codegen vs. shuffling against constant null vector.
|
||||
// Emit remaining default initializers.
|
||||
const llvm::Type *EltTy = VType->getElementType();
|
||||
|
||||
// Emit remaining default initializers
|
||||
for (/* Do not initialize i*/; CurIdx < ResElts; ++CurIdx) {
|
||||
Value *Idx = llvm::ConstantInt::get(I32Ty, CurIdx);
|
||||
llvm::Value *Init = llvm::Constant::getNullValue(EltTy);
|
||||
V = Builder.CreateInsertElement(V, Init, Idx, "vecinit");
|
||||
}
|
||||
return V;
|
||||
}
|
||||
|
||||
// VisitCastExpr - Emit code for an explicit or implicit cast. Implicit casts
|
||||
// have to handle a more broad range of conversions than explicit casts, as they
|
||||
// handle things like function to ptr-to-function decay etc.
|
||||
@ -700,7 +835,16 @@ Value *ScalarExprEmitter::EmitCastExpr(const CastExpr *CE) {
|
||||
|
||||
case CastExpr::CK_IntegralToPointer: {
|
||||
Value *Src = Visit(const_cast<Expr*>(E));
|
||||
return Builder.CreateIntToPtr(Src, ConvertType(DestTy));
|
||||
|
||||
// First, convert to the correct width so that we control the kind of
|
||||
// extension.
|
||||
const llvm::Type *MiddleTy =
|
||||
llvm::IntegerType::get(VMContext, CGF.LLVMPointerWidth);
|
||||
bool InputSigned = E->getType()->isSignedIntegerType();
|
||||
llvm::Value* IntResult =
|
||||
Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv");
|
||||
|
||||
return Builder.CreateIntToPtr(IntResult, ConvertType(DestTy));
|
||||
}
|
||||
|
||||
case CastExpr::CK_PointerToIntegral: {
|
||||
@ -1379,18 +1523,20 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) {
|
||||
}
|
||||
|
||||
Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
|
||||
const llvm::Type *ResTy = ConvertType(E->getType());
|
||||
|
||||
// If we have 0 && RHS, see if we can elide RHS, if so, just return 0.
|
||||
// If we have 1 && X, just emit X without inserting the control flow.
|
||||
if (int Cond = CGF.ConstantFoldsToSimpleInteger(E->getLHS())) {
|
||||
if (Cond == 1) { // If we have 1 && X, just emit X.
|
||||
Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS());
|
||||
// ZExt result to int.
|
||||
return Builder.CreateZExt(RHSCond, CGF.LLVMIntTy, "land.ext");
|
||||
// ZExt result to int or bool.
|
||||
return Builder.CreateZExtOrBitCast(RHSCond, ResTy, "land.ext");
|
||||
}
|
||||
|
||||
// 0 && RHS: If it is safe, just elide the RHS, and return 0.
|
||||
// 0 && RHS: If it is safe, just elide the RHS, and return 0/false.
|
||||
if (!CGF.ContainsLabel(E->getRHS()))
|
||||
return llvm::Constant::getNullValue(CGF.LLVMIntTy);
|
||||
return llvm::Constant::getNullValue(ResTy);
|
||||
}
|
||||
|
||||
llvm::BasicBlock *ContBlock = CGF.createBasicBlock("land.end");
|
||||
@ -1423,22 +1569,24 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
|
||||
PN->addIncoming(RHSCond, RHSBlock);
|
||||
|
||||
// ZExt result to int.
|
||||
return Builder.CreateZExt(PN, CGF.LLVMIntTy, "land.ext");
|
||||
return Builder.CreateZExtOrBitCast(PN, ResTy, "land.ext");
|
||||
}
|
||||
|
||||
Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
|
||||
const llvm::Type *ResTy = ConvertType(E->getType());
|
||||
|
||||
// If we have 1 || RHS, see if we can elide RHS, if so, just return 1.
|
||||
// If we have 0 || X, just emit X without inserting the control flow.
|
||||
if (int Cond = CGF.ConstantFoldsToSimpleInteger(E->getLHS())) {
|
||||
if (Cond == -1) { // If we have 0 || X, just emit X.
|
||||
Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS());
|
||||
// ZExt result to int.
|
||||
return Builder.CreateZExt(RHSCond, CGF.LLVMIntTy, "lor.ext");
|
||||
// ZExt result to int or bool.
|
||||
return Builder.CreateZExtOrBitCast(RHSCond, ResTy, "lor.ext");
|
||||
}
|
||||
|
||||
// 1 || RHS: If it is safe, just elide the RHS, and return 1.
|
||||
// 1 || RHS: If it is safe, just elide the RHS, and return 1/true.
|
||||
if (!CGF.ContainsLabel(E->getRHS()))
|
||||
return llvm::ConstantInt::get(CGF.LLVMIntTy, 1);
|
||||
return llvm::ConstantInt::get(ResTy, 1);
|
||||
}
|
||||
|
||||
llvm::BasicBlock *ContBlock = CGF.createBasicBlock("lor.end");
|
||||
@ -1474,7 +1622,7 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
|
||||
PN->addIncoming(RHSCond, RHSBlock);
|
||||
|
||||
// ZExt result to int.
|
||||
return Builder.CreateZExt(PN, CGF.LLVMIntTy, "lor.ext");
|
||||
return Builder.CreateZExtOrBitCast(PN, ResTy, "lor.ext");
|
||||
}
|
||||
|
||||
Value *ScalarExprEmitter::VisitBinComma(const BinaryOperator *E) {
|
||||
|
@ -850,7 +850,7 @@ class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
|
||||
/// \param[out] NameOut - The return value.
|
||||
void GetNameForMethod(const ObjCMethodDecl *OMD,
|
||||
const ObjCContainerDecl *CD,
|
||||
std::string &NameOut);
|
||||
llvm::SmallVectorImpl<char> &NameOut);
|
||||
|
||||
/// GetMethodVarName - Return a unique constant for the given
|
||||
/// selector's name. The return value has type char *.
|
||||
@ -900,7 +900,7 @@ class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
|
||||
|
||||
/// EmitPropertyList - Emit the given property list. The return
|
||||
/// value has type PropertyListPtrTy.
|
||||
llvm::Constant *EmitPropertyList(const std::string &Name,
|
||||
llvm::Constant *EmitPropertyList(llvm::Twine Name,
|
||||
const Decl *Container,
|
||||
const ObjCContainerDecl *OCD,
|
||||
const ObjCCommonTypesHelper &ObjCTypes);
|
||||
@ -924,7 +924,7 @@ class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
|
||||
/// \param Align - The alignment for the variable, or 0.
|
||||
/// \param AddToUsed - Whether the variable should be added to
|
||||
/// "llvm.used".
|
||||
llvm::GlobalVariable *CreateMetadataVar(const std::string &Name,
|
||||
llvm::GlobalVariable *CreateMetadataVar(llvm::Twine Name,
|
||||
llvm::Constant *Init,
|
||||
const char *Section,
|
||||
unsigned Align,
|
||||
@ -1025,7 +1025,7 @@ class CGObjCMac : public CGObjCCommonMac {
|
||||
|
||||
/// EmitMethodList - Emit the method list for the given
|
||||
/// implementation. The return value has type MethodListPtrTy.
|
||||
llvm::Constant *EmitMethodList(const std::string &Name,
|
||||
llvm::Constant *EmitMethodList(llvm::Twine Name,
|
||||
const char *Section,
|
||||
const ConstantVector &Methods);
|
||||
|
||||
@ -1040,7 +1040,7 @@ class CGObjCMac : public CGObjCCommonMac {
|
||||
/// - begin, end: The method list to output.
|
||||
///
|
||||
/// The return value has type MethodDescriptionListPtrTy.
|
||||
llvm::Constant *EmitMethodDescList(const std::string &Name,
|
||||
llvm::Constant *EmitMethodDescList(llvm::Twine Name,
|
||||
const char *Section,
|
||||
const ConstantVector &Methods);
|
||||
|
||||
@ -1066,7 +1066,7 @@ class CGObjCMac : public CGObjCCommonMac {
|
||||
|
||||
/// EmitProtocolList - Generate the list of referenced
|
||||
/// protocols. The return value has type ProtocolListPtrTy.
|
||||
llvm::Constant *EmitProtocolList(const std::string &Name,
|
||||
llvm::Constant *EmitProtocolList(llvm::Twine Name,
|
||||
ObjCProtocolDecl::protocol_iterator begin,
|
||||
ObjCProtocolDecl::protocol_iterator end);
|
||||
|
||||
@ -1197,7 +1197,7 @@ class CGObjCNonFragileABIMac : public CGObjCCommonMac {
|
||||
|
||||
/// EmitMethodList - Emit the method list for the given
|
||||
/// implementation. The return value has type MethodListnfABITy.
|
||||
llvm::Constant *EmitMethodList(const std::string &Name,
|
||||
llvm::Constant *EmitMethodList(llvm::Twine Name,
|
||||
const char *Section,
|
||||
const ConstantVector &Methods);
|
||||
/// EmitIvarList - Emit the ivar list for the given
|
||||
@ -1224,7 +1224,7 @@ class CGObjCNonFragileABIMac : public CGObjCCommonMac {
|
||||
|
||||
/// EmitProtocolList - Generate the list of referenced
|
||||
/// protocols. The return value has type ProtocolListPtrTy.
|
||||
llvm::Constant *EmitProtocolList(const std::string &Name,
|
||||
llvm::Constant *EmitProtocolList(llvm::Twine Name,
|
||||
ObjCProtocolDecl::protocol_iterator begin,
|
||||
ObjCProtocolDecl::protocol_iterator end);
|
||||
|
||||
@ -1616,8 +1616,6 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
|
||||
// resolved. Investigate. Its also wasteful to look this up over and over.
|
||||
LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
|
||||
|
||||
const char *ProtocolName = PD->getNameAsCString();
|
||||
|
||||
// Construct method lists.
|
||||
std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
|
||||
std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
|
||||
@ -1647,17 +1645,15 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
|
||||
Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods);
|
||||
Values[1] = GetClassName(PD->getIdentifier());
|
||||
Values[2] =
|
||||
EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getNameAsString(),
|
||||
EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
|
||||
PD->protocol_begin(),
|
||||
PD->protocol_end());
|
||||
Values[3] =
|
||||
EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_"
|
||||
+ PD->getNameAsString(),
|
||||
EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
|
||||
"__OBJC,__cat_inst_meth,regular,no_dead_strip",
|
||||
InstanceMethods);
|
||||
Values[4] =
|
||||
EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_"
|
||||
+ PD->getNameAsString(),
|
||||
EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
|
||||
"__OBJC,__cat_cls_meth,regular,no_dead_strip",
|
||||
ClassMethods);
|
||||
llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
|
||||
@ -1672,7 +1668,7 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
|
||||
new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
|
||||
llvm::GlobalValue::InternalLinkage,
|
||||
Init,
|
||||
std::string("\01L_OBJC_PROTOCOL_")+ProtocolName);
|
||||
"\01L_OBJC_PROTOCOL_" + PD->getName());
|
||||
Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
|
||||
Entry->setAlignment(4);
|
||||
// FIXME: Is this necessary? Why only for protocol?
|
||||
@ -1694,7 +1690,7 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
|
||||
new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
|
||||
llvm::GlobalValue::ExternalLinkage,
|
||||
0,
|
||||
"\01L_OBJC_PROTOCOL_" + PD->getNameAsString());
|
||||
"\01L_OBJC_PROTOCOL_" + PD->getName());
|
||||
Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
|
||||
Entry->setAlignment(4);
|
||||
// FIXME: Is this necessary? Why only for protocol?
|
||||
@ -1722,16 +1718,14 @@ CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
|
||||
Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
|
||||
Values[1] =
|
||||
EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
|
||||
+ PD->getNameAsString(),
|
||||
+ PD->getName(),
|
||||
"__OBJC,__cat_inst_meth,regular,no_dead_strip",
|
||||
OptInstanceMethods);
|
||||
Values[2] =
|
||||
EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_"
|
||||
+ PD->getNameAsString(),
|
||||
EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
|
||||
"__OBJC,__cat_cls_meth,regular,no_dead_strip",
|
||||
OptClassMethods);
|
||||
Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" +
|
||||
PD->getNameAsString(),
|
||||
Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(),
|
||||
0, PD, ObjCTypes);
|
||||
|
||||
// Return null if no extension bits are used.
|
||||
@ -1743,7 +1737,7 @@ CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
|
||||
llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
|
||||
|
||||
// No special section, but goes in llvm.used
|
||||
return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getNameAsString(),
|
||||
return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),
|
||||
Init,
|
||||
0, 0, true);
|
||||
}
|
||||
@ -1756,7 +1750,7 @@ CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
|
||||
};
|
||||
*/
|
||||
llvm::Constant *
|
||||
CGObjCMac::EmitProtocolList(const std::string &Name,
|
||||
CGObjCMac::EmitProtocolList(llvm::Twine Name,
|
||||
ObjCProtocolDecl::protocol_iterator begin,
|
||||
ObjCProtocolDecl::protocol_iterator end) {
|
||||
std::vector<llvm::Constant*> ProtocolRefs;
|
||||
@ -1800,7 +1794,7 @@ CGObjCMac::EmitProtocolList(const std::string &Name,
|
||||
struct _objc_property[prop_count];
|
||||
};
|
||||
*/
|
||||
llvm::Constant *CGObjCCommonMac::EmitPropertyList(const std::string &Name,
|
||||
llvm::Constant *CGObjCCommonMac::EmitPropertyList(llvm::Twine Name,
|
||||
const Decl *Container,
|
||||
const ObjCContainerDecl *OCD,
|
||||
const ObjCCommonTypesHelper &ObjCTypes) {
|
||||
@ -1854,7 +1848,7 @@ CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
|
||||
Desc);
|
||||
}
|
||||
|
||||
llvm::Constant *CGObjCMac::EmitMethodDescList(const std::string &Name,
|
||||
llvm::Constant *CGObjCMac::EmitMethodDescList(llvm::Twine Name,
|
||||
const char *Section,
|
||||
const ConstantVector &Methods) {
|
||||
// Return null for empty list.
|
||||
@ -1894,8 +1888,10 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
|
||||
const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
|
||||
const ObjCCategoryDecl *Category =
|
||||
Interface->FindCategoryDeclaration(OCD->getIdentifier());
|
||||
std::string ExtName(Interface->getNameAsString() + "_" +
|
||||
OCD->getNameAsString());
|
||||
|
||||
llvm::SmallString<256> ExtName;
|
||||
llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
|
||||
<< OCD->getName();
|
||||
|
||||
std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
|
||||
for (ObjCCategoryImplDecl::instmeth_iterator
|
||||
@ -1914,17 +1910,16 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
|
||||
Values[1] = GetClassName(Interface->getIdentifier());
|
||||
LazySymbols.insert(Interface->getIdentifier());
|
||||
Values[2] =
|
||||
EmitMethodList(std::string("\01L_OBJC_CATEGORY_INSTANCE_METHODS_") +
|
||||
ExtName,
|
||||
EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
|
||||
"__OBJC,__cat_inst_meth,regular,no_dead_strip",
|
||||
InstanceMethods);
|
||||
Values[3] =
|
||||
EmitMethodList(std::string("\01L_OBJC_CATEGORY_CLASS_METHODS_") + ExtName,
|
||||
EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
|
||||
"__OBJC,__cat_cls_meth,regular,no_dead_strip",
|
||||
ClassMethods);
|
||||
if (Category) {
|
||||
Values[4] =
|
||||
EmitProtocolList(std::string("\01L_OBJC_CATEGORY_PROTOCOLS_") + ExtName,
|
||||
EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
|
||||
Category->protocol_begin(),
|
||||
Category->protocol_end());
|
||||
} else {
|
||||
@ -1934,7 +1929,7 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
|
||||
|
||||
// If there is no category @interface then there can be no properties.
|
||||
if (Category) {
|
||||
Values[6] = EmitPropertyList(std::string("\01l_OBJC_$_PROP_LIST_")+ExtName,
|
||||
Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
|
||||
OCD, Category, ObjCTypes);
|
||||
} else {
|
||||
Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
|
||||
@ -1944,7 +1939,7 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
|
||||
Values);
|
||||
|
||||
llvm::GlobalVariable *GV =
|
||||
CreateMetadataVar(std::string("\01L_OBJC_CATEGORY_")+ExtName, Init,
|
||||
CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,
|
||||
"__OBJC,__category,regular,no_dead_strip",
|
||||
4, true);
|
||||
DefinedCategories.push_back(GV);
|
||||
@ -1988,7 +1983,7 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
|
||||
ObjCInterfaceDecl *Interface =
|
||||
const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
|
||||
llvm::Constant *Protocols =
|
||||
EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getNameAsString(),
|
||||
EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
|
||||
Interface->protocol_begin(),
|
||||
Interface->protocol_end());
|
||||
unsigned Flags = eClassFlags_Factory;
|
||||
@ -2046,7 +2041,7 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
|
||||
Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
|
||||
Values[ 6] = EmitIvarList(ID, false);
|
||||
Values[ 7] =
|
||||
EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getNameAsString(),
|
||||
EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),
|
||||
"__OBJC,__inst_meth,regular,no_dead_strip",
|
||||
InstanceMethods);
|
||||
// cache is always NULL.
|
||||
@ -2058,7 +2053,7 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
|
||||
Values);
|
||||
|
||||
llvm::GlobalVariable *GV =
|
||||
CreateMetadataVar(std::string("\01L_OBJC_CLASS_")+ClassName, Init,
|
||||
CreateMetadataVar("\01L_OBJC_CLASS_" + ClassName, Init,
|
||||
"__OBJC,__class,regular,no_dead_strip",
|
||||
4, true);
|
||||
DefinedClasses.push_back(GV);
|
||||
@ -2174,7 +2169,7 @@ CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
|
||||
std::vector<llvm::Constant*> Values(3);
|
||||
Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
|
||||
Values[1] = BuildIvarLayout(ID, false);
|
||||
Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getNameAsString(),
|
||||
Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
|
||||
ID, ID->getClassInterface(), ObjCTypes);
|
||||
|
||||
// Return null if no extension bits are used.
|
||||
@ -2183,7 +2178,7 @@ CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
|
||||
|
||||
llvm::Constant *Init =
|
||||
llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
|
||||
return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getNameAsString(),
|
||||
return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),
|
||||
Init, "__OBJC,__class_ext,regular,no_dead_strip",
|
||||
4, true);
|
||||
}
|
||||
@ -2243,12 +2238,11 @@ llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
|
||||
|
||||
llvm::GlobalVariable *GV;
|
||||
if (ForClass)
|
||||
GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getNameAsString(),
|
||||
GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),
|
||||
Init, "__OBJC,__class_vars,regular,no_dead_strip",
|
||||
4, true);
|
||||
else
|
||||
GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_"
|
||||
+ ID->getNameAsString(),
|
||||
GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),
|
||||
Init, "__OBJC,__instance_vars,regular,no_dead_strip",
|
||||
4, true);
|
||||
return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
|
||||
@ -2286,7 +2280,7 @@ llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
|
||||
return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
|
||||
}
|
||||
|
||||
llvm::Constant *CGObjCMac::EmitMethodList(const std::string &Name,
|
||||
llvm::Constant *CGObjCMac::EmitMethodList(llvm::Twine Name,
|
||||
const char *Section,
|
||||
const ConstantVector &Methods) {
|
||||
// Return null for empty list.
|
||||
@ -2308,7 +2302,7 @@ llvm::Constant *CGObjCMac::EmitMethodList(const std::string &Name,
|
||||
|
||||
llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
|
||||
const ObjCContainerDecl *CD) {
|
||||
std::string Name;
|
||||
llvm::SmallString<256> Name;
|
||||
GetNameForMethod(OMD, CD, Name);
|
||||
|
||||
CodeGenTypes &Types = CGM.getTypes();
|
||||
@ -2317,7 +2311,7 @@ llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
|
||||
llvm::Function *Method =
|
||||
llvm::Function::Create(MethodTy,
|
||||
llvm::GlobalValue::InternalLinkage,
|
||||
Name,
|
||||
Name.str(),
|
||||
&CGM.getModule());
|
||||
MethodDefinitions.insert(std::make_pair(OMD, Method));
|
||||
|
||||
@ -2325,7 +2319,7 @@ llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
|
||||
}
|
||||
|
||||
llvm::GlobalVariable *
|
||||
CGObjCCommonMac::CreateMetadataVar(const std::string &Name,
|
||||
CGObjCCommonMac::CreateMetadataVar(llvm::Twine Name,
|
||||
llvm::Constant *Init,
|
||||
const char *Section,
|
||||
unsigned Align,
|
||||
@ -2985,7 +2979,8 @@ llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
|
||||
|
||||
if (!Entry)
|
||||
Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
|
||||
llvm::ConstantArray::get(VMContext, Ident->getName()),
|
||||
llvm::ConstantArray::get(VMContext,
|
||||
Ident->getNameStart()),
|
||||
"__TEXT,__cstring,cstring_literals",
|
||||
1, true);
|
||||
|
||||
@ -3434,7 +3429,8 @@ llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
|
||||
|
||||
if (!Entry)
|
||||
Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
|
||||
llvm::ConstantArray::get(VMContext, Ident->getName()),
|
||||
llvm::ConstantArray::get(VMContext,
|
||||
Ident->getNameStart()),
|
||||
"__TEXT,__cstring,cstring_literals",
|
||||
1, true);
|
||||
|
||||
@ -3453,21 +3449,15 @@ CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
|
||||
|
||||
void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
|
||||
const ObjCContainerDecl *CD,
|
||||
std::string &NameOut) {
|
||||
NameOut = '\01';
|
||||
NameOut += (D->isInstanceMethod() ? '-' : '+');
|
||||
NameOut += '[';
|
||||
llvm::SmallVectorImpl<char> &Name) {
|
||||
llvm::raw_svector_ostream OS(Name);
|
||||
assert (CD && "Missing container decl in GetNameForMethod");
|
||||
NameOut += CD->getNameAsString();
|
||||
OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
|
||||
<< '[' << CD->getName();
|
||||
if (const ObjCCategoryImplDecl *CID =
|
||||
dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext())) {
|
||||
NameOut += '(';
|
||||
NameOut += CID->getNameAsString();
|
||||
NameOut+= ')';
|
||||
}
|
||||
NameOut += ' ';
|
||||
NameOut += D->getSelector().getAsString();
|
||||
NameOut += ']';
|
||||
dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
|
||||
OS << '(' << CID->getNameAsString() << ')';
|
||||
OS << ' ' << D->getSelector().getAsString() << ']';
|
||||
}
|
||||
|
||||
void CGObjCMac::FinishModule() {
|
||||
@ -4256,7 +4246,7 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
|
||||
const ObjCInterfaceDecl *OID = ID->getClassInterface();
|
||||
assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
|
||||
Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
|
||||
+ OID->getNameAsString(),
|
||||
+ OID->getName(),
|
||||
OID->protocol_begin(),
|
||||
OID->protocol_end());
|
||||
|
||||
@ -4269,9 +4259,8 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
|
||||
if (flags & CLS_META)
|
||||
Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
|
||||
else
|
||||
Values[ 9] =
|
||||
EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getNameAsString(),
|
||||
ID, ID->getClassInterface(), ObjCTypes);
|
||||
Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
|
||||
ID, ID->getClassInterface(), ObjCTypes);
|
||||
llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
|
||||
Values);
|
||||
llvm::GlobalVariable *CLASS_RO_GV =
|
||||
@ -4532,16 +4521,16 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
|
||||
const ObjCCategoryDecl *Category =
|
||||
Interface->FindCategoryDeclaration(OCD->getIdentifier());
|
||||
if (Category) {
|
||||
std::string ExtName(Interface->getNameAsString() + "_$_" +
|
||||
OCD->getNameAsString());
|
||||
llvm::SmallString<256> ExtName;
|
||||
llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_"
|
||||
<< OCD->getName();
|
||||
Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
|
||||
+ Interface->getNameAsString() + "_$_"
|
||||
+ Category->getNameAsString(),
|
||||
+ Interface->getName() + "_$_"
|
||||
+ Category->getName(),
|
||||
Category->protocol_begin(),
|
||||
Category->protocol_end());
|
||||
Values[5] =
|
||||
EmitPropertyList(std::string("\01l_OBJC_$_PROP_LIST_") + ExtName,
|
||||
OCD, Category, ObjCTypes);
|
||||
Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
|
||||
OCD, Category, ObjCTypes);
|
||||
} else {
|
||||
Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
|
||||
Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
|
||||
@ -4593,10 +4582,9 @@ llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
|
||||
/// struct _objc_method method_list[method_count];
|
||||
/// }
|
||||
///
|
||||
llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(
|
||||
const std::string &Name,
|
||||
const char *Section,
|
||||
const ConstantVector &Methods) {
|
||||
llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(llvm::Twine Name,
|
||||
const char *Section,
|
||||
const ConstantVector &Methods) {
|
||||
// Return null for empty list.
|
||||
if (Methods.empty())
|
||||
return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
|
||||
@ -4742,7 +4730,7 @@ llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
|
||||
new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
|
||||
llvm::GlobalValue::InternalLinkage,
|
||||
Init,
|
||||
Prefix + OID->getNameAsString());
|
||||
Prefix + OID->getName());
|
||||
GV->setAlignment(
|
||||
CGM.getTargetData().getPrefTypeAlignment(Init->getType()));
|
||||
GV->setSection("__DATA, __objc_const");
|
||||
@ -4763,7 +4751,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
|
||||
new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
|
||||
llvm::GlobalValue::ExternalLinkage,
|
||||
0,
|
||||
"\01l_OBJC_PROTOCOL_$_" + PD->getNameAsString());
|
||||
"\01l_OBJC_PROTOCOL_$_" + PD->getName());
|
||||
Entry->setSection("__DATA,__datacoal_nt,coalesced");
|
||||
}
|
||||
|
||||
@ -4795,8 +4783,6 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
|
||||
if (Entry && Entry->hasInitializer())
|
||||
return Entry;
|
||||
|
||||
const char *ProtocolName = PD->getNameAsCString();
|
||||
|
||||
// Construct method lists.
|
||||
std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
|
||||
std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
|
||||
@ -4826,28 +4812,27 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
|
||||
// isa is NULL
|
||||
Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
|
||||
Values[1] = GetClassName(PD->getIdentifier());
|
||||
Values[2] = EmitProtocolList(
|
||||
"\01l_OBJC_$_PROTOCOL_REFS_" + PD->getNameAsString(),
|
||||
PD->protocol_begin(),
|
||||
PD->protocol_end());
|
||||
Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(),
|
||||
PD->protocol_begin(),
|
||||
PD->protocol_end());
|
||||
|
||||
Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
|
||||
+ PD->getNameAsString(),
|
||||
+ PD->getName(),
|
||||
"__DATA, __objc_const",
|
||||
InstanceMethods);
|
||||
Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
|
||||
+ PD->getNameAsString(),
|
||||
+ PD->getName(),
|
||||
"__DATA, __objc_const",
|
||||
ClassMethods);
|
||||
Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
|
||||
+ PD->getNameAsString(),
|
||||
+ PD->getName(),
|
||||
"__DATA, __objc_const",
|
||||
OptInstanceMethods);
|
||||
Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
|
||||
+ PD->getNameAsString(),
|
||||
+ PD->getName(),
|
||||
"__DATA, __objc_const",
|
||||
OptClassMethods);
|
||||
Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getNameAsString(),
|
||||
Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),
|
||||
0, PD, ObjCTypes);
|
||||
uint32_t Size =
|
||||
CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
|
||||
@ -4862,10 +4847,9 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
|
||||
Entry->setInitializer(Init);
|
||||
} else {
|
||||
Entry =
|
||||
new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
|
||||
llvm::GlobalValue::WeakAnyLinkage,
|
||||
Init,
|
||||
std::string("\01l_OBJC_PROTOCOL_$_")+ProtocolName);
|
||||
new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
|
||||
false, llvm::GlobalValue::WeakAnyLinkage, Init,
|
||||
"\01l_OBJC_PROTOCOL_$_" + PD->getName());
|
||||
Entry->setAlignment(
|
||||
CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ProtocolnfABITy));
|
||||
Entry->setSection("__DATA,__datacoal_nt,coalesced");
|
||||
@ -4875,13 +4859,10 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
|
||||
|
||||
// Use this protocol meta-data to build protocol list table in section
|
||||
// __DATA, __objc_protolist
|
||||
llvm::GlobalVariable *PTGV = new llvm::GlobalVariable(
|
||||
CGM.getModule(),
|
||||
ObjCTypes.ProtocolnfABIPtrTy, false,
|
||||
llvm::GlobalValue::WeakAnyLinkage,
|
||||
Entry,
|
||||
std::string("\01l_OBJC_LABEL_PROTOCOL_$_")
|
||||
+ProtocolName);
|
||||
llvm::GlobalVariable *PTGV =
|
||||
new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
|
||||
false, llvm::GlobalValue::WeakAnyLinkage, Entry,
|
||||
"\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName());
|
||||
PTGV->setAlignment(
|
||||
CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
|
||||
PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
|
||||
@ -4899,9 +4880,9 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
|
||||
/// @endcode
|
||||
///
|
||||
llvm::Constant *
|
||||
CGObjCNonFragileABIMac::EmitProtocolList(const std::string &Name,
|
||||
ObjCProtocolDecl::protocol_iterator begin,
|
||||
ObjCProtocolDecl::protocol_iterator end) {
|
||||
CGObjCNonFragileABIMac::EmitProtocolList(llvm::Twine Name,
|
||||
ObjCProtocolDecl::protocol_iterator begin,
|
||||
ObjCProtocolDecl::protocol_iterator end) {
|
||||
std::vector<llvm::Constant*> ProtocolRefs;
|
||||
|
||||
// Just return null for empty protocol lists
|
||||
@ -4909,10 +4890,12 @@ CGObjCNonFragileABIMac::EmitProtocolList(const std::string &Name,
|
||||
return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
|
||||
|
||||
// FIXME: We shouldn't need to do this lookup here, should we?
|
||||
llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
|
||||
llvm::SmallString<256> TmpName;
|
||||
Name.toVector(TmpName);
|
||||
llvm::GlobalVariable *GV =
|
||||
CGM.getModule().getGlobalVariable(TmpName.str(), true);
|
||||
if (GV)
|
||||
return llvm::ConstantExpr::getBitCast(GV,
|
||||
ObjCTypes.ProtocolListnfABIPtrTy);
|
||||
return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
|
||||
|
||||
for (; begin != end; ++begin)
|
||||
ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented???
|
||||
@ -5683,7 +5666,7 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
|
||||
new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
|
||||
llvm::GlobalValue::ExternalLinkage,
|
||||
0,
|
||||
(std::string("OBJC_EHTYPE_$_") +
|
||||
("OBJC_EHTYPE_$_" +
|
||||
ID->getIdentifier()->getName()));
|
||||
}
|
||||
|
||||
@ -5715,7 +5698,7 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
|
||||
Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
|
||||
llvm::GlobalValue::WeakAnyLinkage,
|
||||
Init,
|
||||
(std::string("OBJC_EHTYPE_$_") +
|
||||
("OBJC_EHTYPE_$_" +
|
||||
ID->getIdentifier()->getName()));
|
||||
}
|
||||
|
||||
|
@ -119,6 +119,43 @@ class VtableBuilder {
|
||||
|
||||
Index_t VBlookup(CXXRecordDecl *D, CXXRecordDecl *B);
|
||||
|
||||
Index_t getNVOffset_1(const CXXRecordDecl *D, const CXXRecordDecl *B,
|
||||
Index_t Offset = 0) {
|
||||
|
||||
if (B == D)
|
||||
return Offset;
|
||||
|
||||
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(D);
|
||||
for (CXXRecordDecl::base_class_const_iterator i = D->bases_begin(),
|
||||
e = D->bases_end(); i != e; ++i) {
|
||||
const CXXRecordDecl *Base =
|
||||
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
|
||||
int64_t BaseOffset = 0;
|
||||
if (!i->isVirtual())
|
||||
BaseOffset = Offset + Layout.getBaseClassOffset(Base);
|
||||
int64_t o = getNVOffset_1(Base, B, BaseOffset);
|
||||
if (o >= 0)
|
||||
return o;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// getNVOffset - Returns the non-virtual offset for the given (B) base of the
|
||||
/// derived class D.
|
||||
Index_t getNVOffset(QualType qB, QualType qD) {
|
||||
qD = qD->getAs<PointerType>()->getPointeeType();
|
||||
qB = qB->getAs<PointerType>()->getPointeeType();
|
||||
CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
|
||||
CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
|
||||
int64_t o = getNVOffset_1(D, B);
|
||||
if (o >= 0)
|
||||
return o;
|
||||
|
||||
assert(false && "FIXME: non-virtual base not found");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// getVbaseOffset - Returns the index into the vtable for the virtual base
|
||||
/// offset for the given (B) virtual base of the derived class D.
|
||||
Index_t getVbaseOffset(QualType qB, QualType qD) {
|
||||
@ -138,8 +175,10 @@ class VtableBuilder {
|
||||
}
|
||||
|
||||
bool OverrideMethod(const CXXMethodDecl *MD, llvm::Constant *m,
|
||||
bool MorallyVirtual, Index_t Offset) {
|
||||
bool MorallyVirtual, Index_t OverrideOffset,
|
||||
Index_t Offset) {
|
||||
typedef CXXMethodDecl::method_iterator meth_iter;
|
||||
// FIXME: Should OverrideOffset's be Offset?
|
||||
|
||||
// FIXME: Don't like the nested loops. For very large inheritance
|
||||
// heirarchies we could have a table on the side with the final overridder
|
||||
@ -166,11 +205,12 @@ class VtableBuilder {
|
||||
CallOffset ReturnOffset = std::make_pair(0, 0);
|
||||
if (oret != ret) {
|
||||
// FIXME: calculate offsets for covariance
|
||||
Index_t nv = 0;
|
||||
if (CovariantThunks.count(OMD)) {
|
||||
oret = CovariantThunks[OMD].second;
|
||||
CovariantThunks.erase(OMD);
|
||||
}
|
||||
// FIXME: Double check oret
|
||||
Index_t nv = getNVOffset(oret, ret)/8;
|
||||
ReturnOffset = std::make_pair(nv, getVbaseOffset(oret, ret));
|
||||
}
|
||||
Index[MD] = i;
|
||||
@ -180,17 +220,16 @@ class VtableBuilder {
|
||||
if (MorallyVirtual) {
|
||||
Index_t &idx = VCall[OMD];
|
||||
if (idx == 0) {
|
||||
VCallOffset[MD] = Offset/8;
|
||||
VCallOffset[MD] = OverrideOffset/8;
|
||||
idx = VCalls.size()+1;
|
||||
VCalls.push_back(0);
|
||||
} else {
|
||||
VCallOffset[MD] = VCallOffset[OMD];
|
||||
VCalls[idx-1] = -VCallOffset[OMD] + Offset/8;
|
||||
VCalls[idx-1] = -VCallOffset[OMD] + OverrideOffset/8;
|
||||
}
|
||||
VCall[MD] = idx;
|
||||
CallOffset ThisOffset;
|
||||
// FIXME: calculate non-virtual offset
|
||||
ThisOffset = std::make_pair(0 /* -CurrentVBaseOffset/8 + Offset/8 */,
|
||||
ThisOffset = std::make_pair(CurrentVBaseOffset/8 - Offset/8,
|
||||
-((idx+extra+2)*LLVMPointerWidth/8));
|
||||
// FIXME: Do we always have to build a covariant thunk to save oret,
|
||||
// which is the containing virtual base class?
|
||||
@ -204,8 +243,8 @@ class VtableBuilder {
|
||||
}
|
||||
|
||||
// FIXME: finish off
|
||||
int64_t O = VCallOffset[OMD] - Offset/8;
|
||||
// int64_t O = CurrentVBaseOffset/8 - Offset/8;
|
||||
int64_t O = VCallOffset[OMD] - OverrideOffset/8;
|
||||
// int64_t O = CurrentVBaseOffset/8 - OverrideOffset/8;
|
||||
if (O || ReturnOffset.first || ReturnOffset.second) {
|
||||
CallOffset ThisOffset = std::make_pair(O, 0);
|
||||
|
||||
@ -248,11 +287,11 @@ class VtableBuilder {
|
||||
CovariantThunks.clear();
|
||||
}
|
||||
|
||||
void OverrideMethods(Path_t *Path, bool MorallyVirtual) {
|
||||
void OverrideMethods(Path_t *Path, bool MorallyVirtual, int64_t Offset) {
|
||||
for (Path_t::reverse_iterator i = Path->rbegin(),
|
||||
e = Path->rend(); i != e; ++i) {
|
||||
const CXXRecordDecl *RD = i->first;
|
||||
int64_t Offset = i->second;
|
||||
int64_t OverrideOffset = i->second;
|
||||
for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
|
||||
++mi) {
|
||||
if (!mi->isVirtual())
|
||||
@ -272,7 +311,7 @@ class VtableBuilder {
|
||||
m = wrap(CGM.GetAddrOfFunction(MD, Ty));
|
||||
}
|
||||
|
||||
OverrideMethod(MD, m, MorallyVirtual, Offset);
|
||||
OverrideMethod(MD, m, MorallyVirtual, OverrideOffset, Offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -291,7 +330,7 @@ class VtableBuilder {
|
||||
}
|
||||
|
||||
// If we can find a previously allocated slot for this, reuse it.
|
||||
if (OverrideMethod(MD, m, MorallyVirtual, Offset))
|
||||
if (OverrideMethod(MD, m, MorallyVirtual, Offset, Offset))
|
||||
return;
|
||||
|
||||
// else allocate a new slot.
|
||||
@ -344,7 +383,7 @@ class VtableBuilder {
|
||||
llvm::Constant *e = 0;
|
||||
D(VCalls.insert(VCalls.begin(), 673));
|
||||
D(VCalls.push_back(672));
|
||||
methods.insert(methods.begin() + InsertionPoint, VCalls.size()/*+2*/, e);
|
||||
methods.insert(methods.begin() + InsertionPoint, VCalls.size(), e);
|
||||
// The vcalls come first...
|
||||
for (std::vector<Index_t>::reverse_iterator i = VCalls.rbegin(),
|
||||
e = VCalls.rend();
|
||||
@ -380,7 +419,9 @@ class VtableBuilder {
|
||||
int VCallInsertionPoint = methods.size();
|
||||
if (!DeferVCalls) {
|
||||
insertVCalls(VCallInsertionPoint);
|
||||
}
|
||||
} else
|
||||
// FIXME: just for extra, or for all uses of VCalls.size post this?
|
||||
extra = -VCalls.size();
|
||||
|
||||
if (ForVirtualBase) {
|
||||
D(methods.push_back(wrap(668)));
|
||||
@ -463,7 +504,7 @@ class VtableBuilder {
|
||||
AddMethods(RD, MorallyVirtual, Offset);
|
||||
|
||||
if (Path)
|
||||
OverrideMethods(Path, MorallyVirtual);
|
||||
OverrideMethods(Path, MorallyVirtual, Offset);
|
||||
|
||||
return end(RD, offsets, Layout, PrimaryBase, PrimaryBaseWasVirtual,
|
||||
MorallyVirtual, Offset, ForVirtualBase, Path);
|
||||
|
@ -167,18 +167,20 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
|
||||
|
||||
Builder.SetInsertPoint(EntryBB);
|
||||
|
||||
QualType FnType = getContext().getFunctionType(RetTy, 0, 0, false, 0);
|
||||
|
||||
// Emit subprogram debug descriptor.
|
||||
// FIXME: The cast here is a huge hack.
|
||||
if (CGDebugInfo *DI = getDebugInfo()) {
|
||||
DI->setLocation(StartLoc);
|
||||
if (isa<FunctionDecl>(D)) {
|
||||
DI->EmitFunctionStart(CGM.getMangledName(GD), RetTy, CurFn, Builder);
|
||||
DI->EmitFunctionStart(CGM.getMangledName(GD), FnType, CurFn, Builder);
|
||||
} else {
|
||||
// Just use LLVM function name.
|
||||
|
||||
// FIXME: Remove unnecessary conversion to std::string when API settles.
|
||||
DI->EmitFunctionStart(std::string(Fn->getName()).c_str(),
|
||||
RetTy, CurFn, Builder);
|
||||
FnType, CurFn, Builder);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@ namespace llvm {
|
||||
class LLVMContext;
|
||||
class Module;
|
||||
class SwitchInst;
|
||||
class Twine;
|
||||
class Value;
|
||||
}
|
||||
|
||||
@ -355,6 +356,7 @@ class CodeGenFunction : public BlockFunction {
|
||||
void BlockForwardSelf();
|
||||
llvm::Value *LoadBlockStruct();
|
||||
|
||||
uint64_t AllocateBlockDecl(const BlockDeclRefExpr *E);
|
||||
llvm::Value *GetAddrOfBlockDecl(const BlockDeclRefExpr *E);
|
||||
const llvm::Type *BuildByRefType(const ValueDecl *D);
|
||||
|
||||
@ -508,7 +510,7 @@ class CodeGenFunction : public BlockFunction {
|
||||
/// CreateTempAlloca - This creates a alloca and inserts it into the entry
|
||||
/// block.
|
||||
llvm::AllocaInst *CreateTempAlloca(const llvm::Type *Ty,
|
||||
const char *Name = "tmp");
|
||||
const llvm::Twine &Name = "tmp");
|
||||
|
||||
/// EvaluateExprAsBool - Perform the usual unary conversions on the specified
|
||||
/// expression and compare the result against zero, returning an Int1Ty value.
|
||||
@ -816,7 +818,9 @@ class CodeGenFunction : public BlockFunction {
|
||||
LValue EmitCompoundLiteralLValue(const CompoundLiteralExpr *E);
|
||||
LValue EmitConditionalOperatorLValue(const ConditionalOperator *E);
|
||||
LValue EmitCastLValue(const CastExpr *E);
|
||||
|
||||
LValue EmitNullInitializationLValue(const CXXZeroInitValueExpr *E);
|
||||
LValue EmitPointerToDataMemberLValue(const QualifiedDeclRefExpr *E);
|
||||
|
||||
llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface,
|
||||
const ObjCIvarDecl *Ivar);
|
||||
LValue EmitLValueForField(llvm::Value* Base, FieldDecl* Field,
|
||||
@ -841,7 +845,8 @@ class CodeGenFunction : public BlockFunction {
|
||||
LValue EmitObjCKVCRefLValue(const ObjCImplicitSetterGetterRefExpr *E);
|
||||
LValue EmitObjCSuperExprLValue(const ObjCSuperExpr *E);
|
||||
LValue EmitStmtExprLValue(const StmtExpr *E);
|
||||
|
||||
LValue EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Scalar Expression Emission
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
@ -825,7 +825,7 @@ llvm::Constant *
|
||||
CodeGenModule::CreateRuntimeFunction(const llvm::FunctionType *FTy,
|
||||
const char *Name) {
|
||||
// Convert Name to be a uniqued string from the IdentifierInfo table.
|
||||
Name = getContext().Idents.get(Name).getName();
|
||||
Name = getContext().Idents.get(Name).getNameStart();
|
||||
return GetOrCreateLLVMFunction(Name, FTy, GlobalDecl());
|
||||
}
|
||||
|
||||
@ -911,7 +911,7 @@ llvm::Constant *
|
||||
CodeGenModule::CreateRuntimeVariable(const llvm::Type *Ty,
|
||||
const char *Name) {
|
||||
// Convert Name to be a uniqued string from the IdentifierInfo table.
|
||||
Name = getContext().Idents.get(Name).getName();
|
||||
Name = getContext().Idents.get(Name).getNameStart();
|
||||
return GetOrCreateLLVMGlobal(Name, llvm::PointerType::getUnqual(Ty), 0);
|
||||
}
|
||||
|
||||
@ -1254,7 +1254,7 @@ void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) {
|
||||
|
||||
// Unique the name through the identifier table.
|
||||
const char *AliaseeName = AA->getAliasee().c_str();
|
||||
AliaseeName = getContext().Idents.get(AliaseeName).getName();
|
||||
AliaseeName = getContext().Idents.get(AliaseeName).getNameStart();
|
||||
|
||||
// Create a reference to the named value. This ensures that it is emitted
|
||||
// if a deferred decl.
|
||||
@ -1341,7 +1341,7 @@ llvm::Value *CodeGenModule::getBuiltinLibFunction(const FunctionDecl *FD,
|
||||
cast<llvm::FunctionType>(getTypes().ConvertType(Type));
|
||||
|
||||
// Unique the name through the identifier table.
|
||||
Name = getContext().Idents.get(Name).getName();
|
||||
Name = getContext().Idents.get(Name).getNameStart();
|
||||
return GetOrCreateLLVMFunction(Name, Ty, GlobalDecl(FD));
|
||||
}
|
||||
|
||||
|
@ -248,7 +248,12 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
|
||||
FD = PrimaryTemplate->getTemplatedDecl();
|
||||
}
|
||||
|
||||
mangleBareFunctionType(FD->getType()->getAs<FunctionType>(), MangleReturnType);
|
||||
// Do the canonicalization out here because parameter types can
|
||||
// undergo additional canonicalization (e.g. array decay).
|
||||
FunctionType *FT = cast<FunctionType>(Context.getASTContext()
|
||||
.getCanonicalType(FD->getType()));
|
||||
|
||||
mangleBareFunctionType(FT, MangleReturnType);
|
||||
}
|
||||
|
||||
static bool isStdNamespace(const DeclContext *DC) {
|
||||
@ -705,7 +710,7 @@ void CXXNameMangler::mangleType(QualType T) {
|
||||
// Only operate on the canonical type!
|
||||
T = Context.getASTContext().getCanonicalType(T);
|
||||
|
||||
bool IsSubstitutable = !isa<BuiltinType>(T);
|
||||
bool IsSubstitutable = T.hasQualifiers() || !isa<BuiltinType>(T);
|
||||
if (IsSubstitutable && mangleSubstitution(T))
|
||||
return;
|
||||
|
||||
@ -1236,10 +1241,7 @@ static bool isCharSpecialization(QualType T, const char *Name) {
|
||||
if (!isCharType(TemplateArgs[0].getAsType()))
|
||||
return false;
|
||||
|
||||
if (strcmp(SD->getIdentifier()->getName(), Name) != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return SD->getIdentifier()->getName() == Name;
|
||||
}
|
||||
|
||||
bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
|
||||
|
@ -353,11 +353,17 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
|
||||
|
||||
return ABIArgInfo::getDirect();
|
||||
} else if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
|
||||
// Structures with flexible arrays are always indirect.
|
||||
if (const RecordType *RT = RetTy->getAsStructureType())
|
||||
if (const RecordType *RT = RetTy->getAsStructureType()) {
|
||||
// Structures with either a non-trivial destructor or a non-trivial
|
||||
// copy constructor are always indirect.
|
||||
if (hasNonTrivialDestructorOrCopyConstructor(RT))
|
||||
return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
|
||||
|
||||
// Structures with flexible arrays are always indirect.
|
||||
if (RT->getDecl()->hasFlexibleArrayMember())
|
||||
return ABIArgInfo::getIndirect(0);
|
||||
|
||||
}
|
||||
|
||||
// If specified, structs and unions are always indirect.
|
||||
if (!IsSmallStructInRegABI && !RetTy->isAnyComplexType())
|
||||
return ABIArgInfo::getIndirect(0);
|
||||
@ -1744,14 +1750,14 @@ const ABIInfo &CodeGenTypes::getABIInfo() const {
|
||||
return *(TheABIInfo = new SystemZABIInfo());
|
||||
|
||||
case llvm::Triple::x86:
|
||||
if (Triple.getOS() == llvm::Triple::Darwin)
|
||||
return *(TheABIInfo = new X86_32ABIInfo(Context, true, true));
|
||||
|
||||
switch (Triple.getOS()) {
|
||||
case llvm::Triple::Darwin:
|
||||
return *(TheABIInfo = new X86_32ABIInfo(Context, true, true));
|
||||
case llvm::Triple::Cygwin:
|
||||
case llvm::Triple::DragonFly:
|
||||
case llvm::Triple::MinGW32:
|
||||
case llvm::Triple::MinGW64:
|
||||
case llvm::Triple::AuroraUX:
|
||||
case llvm::Triple::DragonFly:
|
||||
case llvm::Triple::FreeBSD:
|
||||
case llvm::Triple::OpenBSD:
|
||||
return *(TheABIInfo = new X86_32ABIInfo(Context, false, true));
|
||||
|
@ -38,7 +38,8 @@ Darwin::Darwin(const HostInfo &Host, const llvm::Triple& Triple,
|
||||
DarwinVersion[2] = _DarwinVersion[2];
|
||||
|
||||
llvm::raw_string_ostream(MacosxVersionMin)
|
||||
<< "10." << DarwinVersion[0] - 4 << '.' << DarwinVersion[1];
|
||||
<< "10." << std::max(0, (int)DarwinVersion[0] - 4) << '.'
|
||||
<< DarwinVersion[1];
|
||||
|
||||
// FIXME: Lift default up.
|
||||
IPhoneOSVersionMin = "3.0";
|
||||
@ -54,7 +55,6 @@ DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple,
|
||||
GCCVersion[2] = _GCCVersion[2];
|
||||
|
||||
// Set up the tool chain paths to match gcc.
|
||||
|
||||
ToolChainDir = "i686-apple-darwin";
|
||||
ToolChainDir += llvm::utostr(DarwinVersion[0]);
|
||||
ToolChainDir += "/";
|
||||
@ -64,6 +64,26 @@ DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple,
|
||||
ToolChainDir += '.';
|
||||
ToolChainDir += llvm::utostr(GCCVersion[2]);
|
||||
|
||||
// Try the next major version if that tool chain dir is invalid.
|
||||
std::string Tmp = "/usr/lib/gcc/" + ToolChainDir;
|
||||
if (!llvm::sys::Path(Tmp).exists()) {
|
||||
std::string Next = "i686-apple-darwin";
|
||||
Next += llvm::utostr(DarwinVersion[0] + 1);
|
||||
Next += "/";
|
||||
Next += llvm::utostr(GCCVersion[0]);
|
||||
Next += '.';
|
||||
Next += llvm::utostr(GCCVersion[1]);
|
||||
Next += '.';
|
||||
Next += llvm::utostr(GCCVersion[2]);
|
||||
|
||||
// Use that if it exists, otherwise hope the user isn't linking.
|
||||
//
|
||||
// FIXME: Drop dependency on gcc's tool chain.
|
||||
Tmp = "/usr/lib/gcc/" + Next;
|
||||
if (llvm::sys::Path(Tmp).exists())
|
||||
ToolChainDir = Next;
|
||||
}
|
||||
|
||||
std::string Path;
|
||||
if (getArchName() == "x86_64") {
|
||||
Path = getHost().getDriver().Dir;
|
||||
@ -676,6 +696,7 @@ AuroraUX::AuroraUX(const HostInfo &Host, const llvm::Triple& Triple)
|
||||
getFilePaths().push_back("/usr/lib");
|
||||
getFilePaths().push_back("/usr/sfw/lib");
|
||||
getFilePaths().push_back("/opt/gcc4/lib");
|
||||
getFilePaths().push_back("/opt/gcc4/lib/gcc/i386-pc-solaris2.11/4.2.4");
|
||||
|
||||
}
|
||||
|
||||
|
@ -142,10 +142,15 @@ void Clang::AddPreprocessingOptions(const Driver &D,
|
||||
continue;
|
||||
|
||||
if (A->getOption().matches(options::OPT_include)) {
|
||||
// Use PCH if the user requested it, except for C++ (for now).
|
||||
bool UsePCH = D.CCCUsePCH;
|
||||
if (types::isCXX(Inputs[0].getType()))
|
||||
UsePCH = false;
|
||||
|
||||
bool FoundPTH = false;
|
||||
bool FoundPCH = false;
|
||||
llvm::sys::Path P(A->getValue(Args));
|
||||
if (D.CCCUsePCH) {
|
||||
if (UsePCH) {
|
||||
P.appendSuffix("pch");
|
||||
if (P.exists())
|
||||
FoundPCH = true;
|
||||
@ -164,8 +169,8 @@ void Clang::AddPreprocessingOptions(const Driver &D,
|
||||
if (!FoundPCH && !FoundPTH) {
|
||||
P.appendSuffix("gch");
|
||||
if (P.exists()) {
|
||||
FoundPCH = D.CCCUsePCH;
|
||||
FoundPTH = !D.CCCUsePCH;
|
||||
FoundPCH = UsePCH;
|
||||
FoundPTH = !UsePCH;
|
||||
}
|
||||
else
|
||||
P.eraseSuffix();
|
||||
@ -173,7 +178,7 @@ void Clang::AddPreprocessingOptions(const Driver &D,
|
||||
|
||||
if (FoundPCH || FoundPTH) {
|
||||
A->claim();
|
||||
if (D.CCCUsePCH)
|
||||
if (UsePCH)
|
||||
CmdArgs.push_back("-include-pch");
|
||||
else
|
||||
CmdArgs.push_back("-include-pth");
|
||||
@ -528,7 +533,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
else
|
||||
CmdArgs.push_back("-E");
|
||||
} else if (isa<PrecompileJobAction>(JA)) {
|
||||
if (D.CCCUsePCH)
|
||||
// Use PCH if the user requested it, except for C++ (for now).
|
||||
bool UsePCH = D.CCCUsePCH;
|
||||
if (types::isCXX(Inputs[0].getType()))
|
||||
UsePCH = false;
|
||||
|
||||
if (UsePCH)
|
||||
CmdArgs.push_back("-emit-pch");
|
||||
else
|
||||
CmdArgs.push_back("-emit-pth");
|
||||
@ -759,7 +769,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
// option.
|
||||
if (Arg *Std = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) {
|
||||
if (Std->getOption().matches(options::OPT_ansi))
|
||||
CmdArgs.push_back("-std=c89");
|
||||
if (types::isCXX(InputType))
|
||||
CmdArgs.push_back("-std=c++98");
|
||||
else
|
||||
CmdArgs.push_back("-std=c89");
|
||||
else
|
||||
Std->render(Args, CmdArgs);
|
||||
|
||||
@ -2149,7 +2162,7 @@ void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
}
|
||||
|
||||
const char *Exec =
|
||||
Args.MakeArgString(getToolChain().GetProgramPath(C, "as"));
|
||||
Args.MakeArgString(getToolChain().GetProgramPath(C, "gas"));
|
||||
Dest.addCommand(new Command(JA, Exec, CmdArgs));
|
||||
}
|
||||
|
||||
@ -2164,18 +2177,19 @@ void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
if ((!Args.hasArg(options::OPT_nostdlib)) &&
|
||||
(!Args.hasArg(options::OPT_shared))) {
|
||||
CmdArgs.push_back("-e");
|
||||
CmdArgs.push_back("__start");
|
||||
CmdArgs.push_back("_start");
|
||||
}
|
||||
|
||||
if (Args.hasArg(options::OPT_static)) {
|
||||
CmdArgs.push_back("-Bstatic");
|
||||
CmdArgs.push_back("-dn");
|
||||
} else {
|
||||
CmdArgs.push_back("--eh-frame-hdr");
|
||||
// CmdArgs.push_back("--eh-frame-hdr");
|
||||
CmdArgs.push_back("-Bdynamic");
|
||||
if (Args.hasArg(options::OPT_shared)) {
|
||||
CmdArgs.push_back("-shared");
|
||||
} else {
|
||||
CmdArgs.push_back("-dynamic-linker");
|
||||
CmdArgs.push_back("--dynamic-linker");
|
||||
CmdArgs.push_back("/lib/ld.so.1"); // 64Bit Path /lib/amd64/ld.so.1
|
||||
}
|
||||
}
|
||||
@ -2193,11 +2207,14 @@ void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
if (!Args.hasArg(options::OPT_nostdlib) &&
|
||||
!Args.hasArg(options::OPT_nostartfiles)) {
|
||||
if (!Args.hasArg(options::OPT_shared)) {
|
||||
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crt0.o")));
|
||||
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crt1.o")));
|
||||
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o")));
|
||||
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbegin.o")));
|
||||
} else {
|
||||
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbeginS.o")));
|
||||
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o")));
|
||||
// CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbeginS.o")));
|
||||
}
|
||||
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtn.o")));
|
||||
}
|
||||
|
||||
CmdArgs.push_back(MakeFormattedString(Args,
|
||||
@ -2242,8 +2259,8 @@ void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
!Args.hasArg(options::OPT_nostartfiles)) {
|
||||
if (!Args.hasArg(options::OPT_shared))
|
||||
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtend.o")));
|
||||
else
|
||||
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o")));
|
||||
// else
|
||||
// CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o")));
|
||||
}
|
||||
|
||||
const char *Exec =
|
||||
|
@ -21,11 +21,20 @@
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/System/Path.h"
|
||||
|
||||
using namespace clang;
|
||||
|
||||
ASTUnit::ASTUnit(Diagnostic &_Diags) : Diags(_Diags) { }
|
||||
ASTUnit::~ASTUnit() { }
|
||||
ASTUnit::ASTUnit(DiagnosticClient *diagClient) : tempFile(false) {
|
||||
Diags.setClient(diagClient ? diagClient : new TextDiagnosticBuffer());
|
||||
}
|
||||
ASTUnit::~ASTUnit() {
|
||||
if (tempFile)
|
||||
llvm::sys::Path(getPCHFileName()).eraseFromDisk();
|
||||
|
||||
// The ASTUnit object owns the DiagnosticClient.
|
||||
delete Diags.getClient();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
@ -80,17 +89,18 @@ const std::string &ASTUnit::getOriginalSourceFileName() {
|
||||
return dyn_cast<PCHReader>(Ctx->getExternalSource())->getOriginalSourceFile();
|
||||
}
|
||||
|
||||
FileManager &ASTUnit::getFileManager() {
|
||||
return HeaderInfo->getFileMgr();
|
||||
const std::string &ASTUnit::getPCHFileName() {
|
||||
return dyn_cast<PCHReader>(Ctx->getExternalSource())->getFileName();
|
||||
}
|
||||
|
||||
ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
|
||||
Diagnostic &Diags,
|
||||
FileManager &FileMgr,
|
||||
std::string *ErrMsg) {
|
||||
llvm::OwningPtr<ASTUnit> AST(new ASTUnit(Diags));
|
||||
|
||||
AST->HeaderInfo.reset(new HeaderSearch(FileMgr));
|
||||
std::string *ErrMsg,
|
||||
DiagnosticClient *diagClient,
|
||||
bool OnlyLocalDecls,
|
||||
bool UseBumpAllocator) {
|
||||
llvm::OwningPtr<ASTUnit> AST(new ASTUnit(diagClient));
|
||||
AST->OnlyLocalDecls = OnlyLocalDecls;
|
||||
AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager()));
|
||||
|
||||
// Gather Info for preprocessor construction later on.
|
||||
|
||||
@ -103,7 +113,8 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
|
||||
llvm::OwningPtr<PCHReader> Reader;
|
||||
llvm::OwningPtr<ExternalASTSource> Source;
|
||||
|
||||
Reader.reset(new PCHReader(AST->getSourceManager(), FileMgr, AST->Diags));
|
||||
Reader.reset(new PCHReader(AST->getSourceManager(), AST->getFileManager(),
|
||||
AST->Diags));
|
||||
Reader->setListener(new PCHInfoCollector(LangInfo, HeaderInfo, TargetTriple,
|
||||
Predefines, Counter));
|
||||
|
||||
@ -138,7 +149,7 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
|
||||
PP.getIdentifierTable(),
|
||||
PP.getSelectorTable(),
|
||||
PP.getBuiltinInfo(),
|
||||
/* FreeMemory = */ true,
|
||||
/* FreeMemory = */ !UseBumpAllocator,
|
||||
/* size_reserve = */0));
|
||||
ASTContext &Context = *AST->Ctx.get();
|
||||
|
||||
|
@ -196,7 +196,7 @@ void AnalysisConsumer::HandleTopLevelSingleDecl(Decl *D) {
|
||||
case Decl::Function: {
|
||||
FunctionDecl* FD = cast<FunctionDecl>(D);
|
||||
|
||||
if (Opts.AnalyzeSpecificFunction.size() > 0 &&
|
||||
if (!Opts.AnalyzeSpecificFunction.empty() &&
|
||||
Opts.AnalyzeSpecificFunction != FD->getIdentifier()->getName())
|
||||
break;
|
||||
|
||||
@ -273,6 +273,9 @@ void AnalysisConsumer::HandleCode(Decl *D, Stmt* Body, Actions& actions) {
|
||||
!Ctx->getSourceManager().isFromMainFile(D->getLocation()))
|
||||
return;
|
||||
|
||||
// Clear the AnalysisManager of old AnalysisContexts.
|
||||
Mgr->ClearContexts();
|
||||
|
||||
// Dispatch on the actions.
|
||||
for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I)
|
||||
(*I)(*Mgr, D);
|
||||
|
@ -20,11 +20,12 @@
|
||||
#include "clang/Basic/OnDiskHashTable.h"
|
||||
#include "clang/Lex/Lexer.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/System/Path.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
|
||||
// FIXME: put this somewhere else?
|
||||
#ifndef S_ISDIR
|
||||
@ -69,7 +70,7 @@ class VISIBILITY_HIDDEN PTHEntryKeyVariant {
|
||||
|
||||
bool isFile() const { return Kind == IsFE; }
|
||||
|
||||
const char* getCString() const {
|
||||
llvm::StringRef getString() const {
|
||||
return Kind == IsFE ? FE->getName() : Path;
|
||||
}
|
||||
|
||||
@ -113,14 +114,14 @@ class VISIBILITY_HIDDEN FileEntryPTHEntryInfo {
|
||||
typedef const PTHEntry& data_type_ref;
|
||||
|
||||
static unsigned ComputeHash(PTHEntryKeyVariant V) {
|
||||
return BernsteinHash(V.getCString());
|
||||
return llvm::HashString(V.getString());
|
||||
}
|
||||
|
||||
static std::pair<unsigned,unsigned>
|
||||
EmitKeyDataLength(llvm::raw_ostream& Out, PTHEntryKeyVariant V,
|
||||
const PTHEntry& E) {
|
||||
|
||||
unsigned n = strlen(V.getCString()) + 1 + 1;
|
||||
unsigned n = V.getString().size() + 1 + 1;
|
||||
::Emit16(Out, n);
|
||||
|
||||
unsigned m = V.getRepresentationLength() + (V.isFile() ? 4 + 4 : 0);
|
||||
@ -133,7 +134,7 @@ class VISIBILITY_HIDDEN FileEntryPTHEntryInfo {
|
||||
// Emit the entry kind.
|
||||
::Emit8(Out, (unsigned) V.getKind());
|
||||
// Emit the string.
|
||||
Out.write(V.getCString(), n - 1);
|
||||
Out.write(V.getString().data(), n - 1);
|
||||
}
|
||||
|
||||
static void EmitData(llvm::raw_ostream& Out, PTHEntryKeyVariant V,
|
||||
@ -516,7 +517,7 @@ class StatListener : public StatSysCallCache {
|
||||
~StatListener() {}
|
||||
|
||||
int stat(const char *path, struct stat *buf) {
|
||||
int result = ::stat(path, buf);
|
||||
int result = StatSysCallCache::stat(path, buf);
|
||||
|
||||
if (result != 0) // Failed 'stat'.
|
||||
PM.insert(path, PTHEntry());
|
||||
@ -553,7 +554,8 @@ void clang::CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS) {
|
||||
PTHWriter PW(*OS, PP);
|
||||
|
||||
// Install the 'stat' system call listener in the FileManager.
|
||||
PP.getFileManager().setStatCache(new StatListener(PW.getPM()));
|
||||
StatListener *StatCache = new StatListener(PW.getPM());
|
||||
PP.getFileManager().addStatCache(StatCache, /*AtBeginning=*/true);
|
||||
|
||||
// Lex through the entire file. This will populate SourceManager with
|
||||
// all of the header information.
|
||||
@ -562,7 +564,7 @@ void clang::CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS) {
|
||||
do { PP.Lex(Tok); } while (Tok.isNot(tok::eof));
|
||||
|
||||
// Generate the PTH file.
|
||||
PP.getFileManager().setStatCache(0);
|
||||
PP.getFileManager().removeStatCache(StatCache);
|
||||
PW.GeneratePTH(&MainFileName);
|
||||
}
|
||||
|
||||
@ -584,12 +586,12 @@ class VISIBILITY_HIDDEN PTHIdentifierTableTrait {
|
||||
typedef data_type data_type_ref;
|
||||
|
||||
static unsigned ComputeHash(PTHIdKey* key) {
|
||||
return BernsteinHash(key->II->getName());
|
||||
return llvm::HashString(key->II->getName());
|
||||
}
|
||||
|
||||
static std::pair<unsigned,unsigned>
|
||||
EmitKeyDataLength(llvm::raw_ostream& Out, const PTHIdKey* key, uint32_t) {
|
||||
unsigned n = strlen(key->II->getName()) + 1;
|
||||
unsigned n = key->II->getLength() + 1;
|
||||
::Emit16(Out, n);
|
||||
return std::make_pair(n, sizeof(uint32_t));
|
||||
}
|
||||
@ -598,7 +600,7 @@ class VISIBILITY_HIDDEN PTHIdentifierTableTrait {
|
||||
// Record the location of the key data. This is used when generating
|
||||
// the mapping from persistent IDs to strings.
|
||||
key->FileOffset = Out.tell();
|
||||
Out.write(key->II->getName(), n);
|
||||
Out.write(key->II->getNameStart(), n);
|
||||
}
|
||||
|
||||
static void EmitData(llvm::raw_ostream& Out, PTHIdKey*, uint32_t pID,
|
||||
|
@ -53,7 +53,7 @@ PCHGenerator::PCHGenerator(const Preprocessor &PP,
|
||||
// Install a stat() listener to keep track of all of the stat()
|
||||
// calls.
|
||||
StatCalls = new MemorizeStatCalls;
|
||||
PP.getFileManager().setStatCache(StatCalls);
|
||||
PP.getFileManager().addStatCache(StatCalls, /*AtBeginning=*/true);
|
||||
}
|
||||
|
||||
void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
|
||||
|
@ -369,6 +369,12 @@ void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,
|
||||
"x86_64-unknown-linux-gnu",
|
||||
"x86_64-unknown-linux-gnu",
|
||||
triple);
|
||||
// Gentoo x86 2009.1 stable
|
||||
AddGnuCPlusPlusIncludePaths(
|
||||
"/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4",
|
||||
"i686-pc-linux-gnu",
|
||||
"i686-pc-linux-gnu",
|
||||
triple);
|
||||
// Gentoo x86 2009.0 stable
|
||||
AddGnuCPlusPlusIncludePaths(
|
||||
"/usr/lib/gcc/i686-pc-linux-gnu/4.3.2/include/g++-v4",
|
||||
@ -386,6 +392,11 @@ void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,
|
||||
"i486-pc-linux-gnu",
|
||||
"i486-pc-linux-gnu",
|
||||
triple);
|
||||
// Ubuntu 9.04
|
||||
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
|
||||
"i486-linux-gnu",
|
||||
"i486-linux-gnu",
|
||||
triple);
|
||||
// Gentoo amd64 stable
|
||||
AddGnuCPlusPlusIncludePaths(
|
||||
"/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4",
|
||||
@ -400,6 +411,8 @@ void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,
|
||||
AddPath("/usr/include/c++/4.2", System, true, false, false);
|
||||
break;
|
||||
case llvm::Triple::Solaris:
|
||||
// Solaris - Fall though..
|
||||
case llvm::Triple::AuroraUX:
|
||||
// AuroraUX
|
||||
AddGnuCPlusPlusIncludePaths("/opt/gcc4/include/c++/4.2.4",
|
||||
"i386-pc-solaris2.11",
|
||||
|
@ -317,13 +317,22 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
|
||||
DefineBuiltinMacro(Buf, "_GNU_SOURCE=1");
|
||||
}
|
||||
|
||||
// Filter out some microsoft extensions when trying to parse in ms-compat
|
||||
// mode.
|
||||
if (LangOpts.Microsoft) {
|
||||
// Filter out some microsoft extensions when trying to parse in ms-compat
|
||||
// mode.
|
||||
DefineBuiltinMacro(Buf, "__int8=__INT8_TYPE__");
|
||||
DefineBuiltinMacro(Buf, "__int16=__INT16_TYPE__");
|
||||
DefineBuiltinMacro(Buf, "__int32=__INT32_TYPE__");
|
||||
DefineBuiltinMacro(Buf, "__int64=__INT64_TYPE__");
|
||||
// Work around some issues with Visual C++ headerws.
|
||||
if (LangOpts.CPlusPlus) {
|
||||
// Since we define wchar_t in C++ mode.
|
||||
DefineBuiltinMacro(Buf, "_WCHAR_T_DEFINED=1");
|
||||
DefineBuiltinMacro(Buf, "_NATIVE_WCHAR_T_DEFINED=1");
|
||||
// FIXME: This should be temporary until we have a __pragma
|
||||
// solution, to avoid some errors flagged in VC++ headers.
|
||||
DefineBuiltinMacro(Buf, "_CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES=0");
|
||||
}
|
||||
}
|
||||
|
||||
if (LangOpts.Optimize)
|
||||
@ -365,8 +374,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
|
||||
DefineType("__INTPTR_TYPE__", TI.getIntPtrType(), Buf);
|
||||
DefineType("__SIZE_TYPE__", TI.getSizeType(), Buf);
|
||||
DefineType("__WCHAR_TYPE__", TI.getWCharType(), Buf);
|
||||
// FIXME: TargetInfo hookize __WINT_TYPE__.
|
||||
DefineBuiltinMacro(Buf, "__WINT_TYPE__=int");
|
||||
DefineType("__WINT_TYPE__", TI.getWIntType(), Buf);
|
||||
|
||||
DefineFloatMacros(Buf, "FLT", &TI.getFloatFormat());
|
||||
DefineFloatMacros(Buf, "DBL", &TI.getDoubleFormat());
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/TypeLocVisitor.h"
|
||||
#include "clang/Lex/MacroInfo.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "clang/Lex/HeaderSearch.h"
|
||||
@ -27,6 +28,7 @@
|
||||
#include "clang/Basic/FileManager.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "clang/Basic/Version.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/Bitcode/BitstreamReader.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
@ -335,8 +337,6 @@ void PCHValidator::ReadCounter(unsigned Value) {
|
||||
PP.setCounterValue(Value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PCH reader implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -345,7 +345,7 @@ PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context,
|
||||
const char *isysroot)
|
||||
: Listener(new PCHValidator(PP, *this)), SourceMgr(PP.getSourceManager()),
|
||||
FileMgr(PP.getFileManager()), Diags(PP.getDiagnostics()),
|
||||
SemaObj(0), PP(&PP), Context(Context), Consumer(0),
|
||||
SemaObj(0), PP(&PP), Context(Context), StatCache(0), Consumer(0),
|
||||
IdentifierTableData(0), IdentifierLookupTable(0),
|
||||
IdentifierOffsets(0),
|
||||
MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
|
||||
@ -362,7 +362,7 @@ PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context,
|
||||
PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr,
|
||||
Diagnostic &Diags, const char *isysroot)
|
||||
: SourceMgr(SourceMgr), FileMgr(FileMgr), Diags(Diags),
|
||||
SemaObj(0), PP(0), Context(0), Consumer(0),
|
||||
SemaObj(0), PP(0), Context(0), StatCache(0), Consumer(0),
|
||||
IdentifierTableData(0), IdentifierLookupTable(0),
|
||||
IdentifierOffsets(0),
|
||||
MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
|
||||
@ -383,7 +383,7 @@ Expr *PCHReader::ReadDeclExpr() {
|
||||
}
|
||||
|
||||
Expr *PCHReader::ReadTypeExpr() {
|
||||
return dyn_cast_or_null<Expr>(ReadStmt(Stream));
|
||||
return dyn_cast_or_null<Expr>(ReadStmt(DeclsCursor));
|
||||
}
|
||||
|
||||
|
||||
@ -411,7 +411,7 @@ class VISIBILITY_HIDDEN PCHMethodPoolLookupTrait {
|
||||
unsigned R = 5381;
|
||||
for (unsigned I = 0; I != N; ++I)
|
||||
if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I))
|
||||
R = clang::BernsteinHashPartial(II->getName(), II->getLength(), R);
|
||||
R = llvm::HashString(II->getName(), R);
|
||||
return R;
|
||||
}
|
||||
|
||||
@ -521,7 +521,7 @@ class VISIBILITY_HIDDEN PCHIdentifierLookupTrait {
|
||||
}
|
||||
|
||||
static unsigned ComputeHash(const internal_key_type& a) {
|
||||
return BernsteinHash(a.first, a.second);
|
||||
return llvm::HashString(llvm::StringRef(a.first, a.second));
|
||||
}
|
||||
|
||||
// This hopefully will just get inlined and removed by the optimizer.
|
||||
@ -731,7 +731,7 @@ class VISIBILITY_HIDDEN PCHStatLookupTrait {
|
||||
typedef PCHStatData data_type;
|
||||
|
||||
static unsigned ComputeHash(const char *path) {
|
||||
return BernsteinHash(path);
|
||||
return llvm::HashString(path);
|
||||
}
|
||||
|
||||
static internal_key_type GetInternalKey(const char *path) { return path; }
|
||||
@ -794,7 +794,7 @@ class VISIBILITY_HIDDEN PCHStatCache : public StatSysCallCache {
|
||||
// If we don't get a hit in the PCH file just forward to 'stat'.
|
||||
if (I == Cache->end()) {
|
||||
++NumStatMisses;
|
||||
return ::stat(path, buf);
|
||||
return StatSysCallCache::stat(path, buf);
|
||||
}
|
||||
|
||||
++NumStatHits;
|
||||
@ -1158,15 +1158,7 @@ PCHReader::ReadPCHBlock() {
|
||||
|
||||
if (Code == llvm::bitc::ENTER_SUBBLOCK) {
|
||||
switch (Stream.ReadSubBlockID()) {
|
||||
case pch::TYPES_BLOCK_ID: // Skip types block (lazily loaded)
|
||||
default: // Skip unknown content.
|
||||
if (Stream.SkipBlock()) {
|
||||
Error("malformed block record in PCH file");
|
||||
return Failure;
|
||||
}
|
||||
break;
|
||||
|
||||
case pch::DECLS_BLOCK_ID:
|
||||
case pch::DECLTYPES_BLOCK_ID:
|
||||
// We lazily load the decls block, but we want to set up the
|
||||
// DeclsCursor cursor to point into it. Clone our current bitcode
|
||||
// cursor to it, enter the block and read the abbrevs in that block.
|
||||
@ -1174,7 +1166,7 @@ PCHReader::ReadPCHBlock() {
|
||||
DeclsCursor = Stream;
|
||||
if (Stream.SkipBlock() || // Skip with the main cursor.
|
||||
// Read the abbrevs.
|
||||
ReadBlockAbbrevs(DeclsCursor, pch::DECLS_BLOCK_ID)) {
|
||||
ReadBlockAbbrevs(DeclsCursor, pch::DECLTYPES_BLOCK_ID)) {
|
||||
Error("malformed block record in PCH file");
|
||||
return Failure;
|
||||
}
|
||||
@ -1352,13 +1344,16 @@ PCHReader::ReadPCHBlock() {
|
||||
}
|
||||
break;
|
||||
|
||||
case pch::STAT_CACHE:
|
||||
FileMgr.setStatCache(
|
||||
new PCHStatCache((const unsigned char *)BlobStart + Record[0],
|
||||
(const unsigned char *)BlobStart,
|
||||
NumStatHits, NumStatMisses));
|
||||
case pch::STAT_CACHE: {
|
||||
PCHStatCache *MyStatCache =
|
||||
new PCHStatCache((const unsigned char *)BlobStart + Record[0],
|
||||
(const unsigned char *)BlobStart,
|
||||
NumStatHits, NumStatMisses);
|
||||
FileMgr.addStatCache(MyStatCache);
|
||||
StatCache = MyStatCache;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case pch::EXT_VECTOR_DECLS:
|
||||
if (!ExtVectorDecls.empty()) {
|
||||
Error("duplicate EXT_VECTOR_DECLS record in PCH file");
|
||||
@ -1466,7 +1461,8 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
|
||||
SourceMgr.ClearPreallocatedSLocEntries();
|
||||
|
||||
// Remove the stat cache.
|
||||
FileMgr.setStatCache(0);
|
||||
if (StatCache)
|
||||
FileMgr.removeStatCache((PCHStatCache*)StatCache);
|
||||
|
||||
return IgnorePCH;
|
||||
}
|
||||
@ -1509,7 +1505,7 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
|
||||
IdentifierInfo *II = Identifiers[I];
|
||||
// Look in the on-disk hash table for an entry for
|
||||
PCHIdentifierLookupTrait Info(*this, II);
|
||||
std::pair<const char*, unsigned> Key(II->getName(), II->getLength());
|
||||
std::pair<const char*, unsigned> Key(II->getNameStart(), II->getLength());
|
||||
PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info);
|
||||
if (Pos == IdTable->end())
|
||||
continue;
|
||||
@ -1593,6 +1589,11 @@ void PCHReader::InitializeContext(ASTContext &Ctx) {
|
||||
if (unsigned ObjCClassRedef
|
||||
= SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS_REDEFINITION])
|
||||
Context->ObjCClassRedefinitionType = GetType(ObjCClassRedef);
|
||||
if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_DESCRIPTOR])
|
||||
Context->setBlockDescriptorType(GetType(String));
|
||||
if (unsigned String
|
||||
= SpecialTypes[pch::SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR])
|
||||
Context->setBlockDescriptorExtendedType(GetType(String));
|
||||
}
|
||||
|
||||
/// \brief Retrieve the name of the original source file name
|
||||
@ -1770,15 +1771,15 @@ void PCHReader::ReadComments(std::vector<SourceRange> &Comments) {
|
||||
QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
|
||||
// Keep track of where we are in the stream, then jump back there
|
||||
// after reading this type.
|
||||
SavedStreamPosition SavedPosition(Stream);
|
||||
SavedStreamPosition SavedPosition(DeclsCursor);
|
||||
|
||||
// Note that we are loading a type record.
|
||||
LoadingTypeOrDecl Loading(*this);
|
||||
|
||||
Stream.JumpToBit(Offset);
|
||||
DeclsCursor.JumpToBit(Offset);
|
||||
RecordData Record;
|
||||
unsigned Code = Stream.ReadCode();
|
||||
switch ((pch::TypeCode)Stream.ReadRecord(Code, Record)) {
|
||||
unsigned Code = DeclsCursor.ReadCode();
|
||||
switch ((pch::TypeCode)DeclsCursor.ReadRecord(Code, Record)) {
|
||||
case pch::TYPE_EXT_QUAL: {
|
||||
assert(Record.size() == 2 &&
|
||||
"Incorrect encoding of extended qualifier type");
|
||||
@ -1839,30 +1840,6 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
|
||||
ASM, IndexTypeQuals);
|
||||
}
|
||||
|
||||
case pch::TYPE_CONSTANT_ARRAY_WITH_EXPR: {
|
||||
QualType ElementType = GetType(Record[0]);
|
||||
ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
|
||||
unsigned IndexTypeQuals = Record[2];
|
||||
SourceLocation LBLoc = SourceLocation::getFromRawEncoding(Record[3]);
|
||||
SourceLocation RBLoc = SourceLocation::getFromRawEncoding(Record[4]);
|
||||
unsigned Idx = 5;
|
||||
llvm::APInt Size = ReadAPInt(Record, Idx);
|
||||
return Context->getConstantArrayWithExprType(ElementType,
|
||||
Size, ReadTypeExpr(),
|
||||
ASM, IndexTypeQuals,
|
||||
SourceRange(LBLoc, RBLoc));
|
||||
}
|
||||
|
||||
case pch::TYPE_CONSTANT_ARRAY_WITHOUT_EXPR: {
|
||||
QualType ElementType = GetType(Record[0]);
|
||||
ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
|
||||
unsigned IndexTypeQuals = Record[2];
|
||||
unsigned Idx = 3;
|
||||
llvm::APInt Size = ReadAPInt(Record, Idx);
|
||||
return Context->getConstantArrayWithoutExprType(ElementType, Size,
|
||||
ASM, IndexTypeQuals);
|
||||
}
|
||||
|
||||
case pch::TYPE_INCOMPLETE_ARRAY: {
|
||||
QualType ElementType = GetType(Record[0]);
|
||||
ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
|
||||
@ -1987,20 +1964,184 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
|
||||
return Context->getObjCObjectPointerType(OIT, Protos.data(), NumProtos);
|
||||
}
|
||||
|
||||
case pch::TYPE_OBJC_PROTOCOL_LIST: {
|
||||
case pch::TYPE_SUBST_TEMPLATE_TYPE_PARM: {
|
||||
unsigned Idx = 0;
|
||||
QualType OIT = GetType(Record[Idx++]);
|
||||
unsigned NumProtos = Record[Idx++];
|
||||
llvm::SmallVector<ObjCProtocolDecl*, 4> Protos;
|
||||
for (unsigned I = 0; I != NumProtos; ++I)
|
||||
Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++])));
|
||||
return Context->getObjCProtocolListType(OIT, Protos.data(), NumProtos);
|
||||
QualType Parm = GetType(Record[Idx++]);
|
||||
QualType Replacement = GetType(Record[Idx++]);
|
||||
return
|
||||
Context->getSubstTemplateTypeParmType(cast<TemplateTypeParmType>(Parm),
|
||||
Replacement);
|
||||
}
|
||||
}
|
||||
// Suppress a GCC warning
|
||||
return QualType();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class TypeLocReader : public TypeLocVisitor<TypeLocReader> {
|
||||
PCHReader &Reader;
|
||||
const PCHReader::RecordData &Record;
|
||||
unsigned &Idx;
|
||||
|
||||
public:
|
||||
TypeLocReader(PCHReader &Reader, const PCHReader::RecordData &Record,
|
||||
unsigned &Idx)
|
||||
: Reader(Reader), Record(Record), Idx(Idx) { }
|
||||
|
||||
// We want compile-time assurance that we've enumerated all of
|
||||
// these, so unfortunately we have to declare them first, then
|
||||
// define them out-of-line.
|
||||
#define ABSTRACT_TYPELOC(CLASS, PARENT)
|
||||
#define TYPELOC(CLASS, PARENT) \
|
||||
void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
|
||||
#include "clang/AST/TypeLocNodes.def"
|
||||
|
||||
void VisitFunctionTypeLoc(FunctionTypeLoc);
|
||||
void VisitArrayTypeLoc(ArrayTypeLoc);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void TypeLocReader::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
|
||||
// nothing to do
|
||||
}
|
||||
void TypeLocReader::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
|
||||
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitFixedWidthIntTypeLoc(FixedWidthIntTypeLoc TL) {
|
||||
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitComplexTypeLoc(ComplexTypeLoc TL) {
|
||||
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitPointerTypeLoc(PointerTypeLoc TL) {
|
||||
TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
|
||||
TL.setCaretLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
|
||||
TL.setAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
|
||||
TL.setAmpAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
|
||||
TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) {
|
||||
TL.setLBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
TL.setRBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
if (Record[Idx++])
|
||||
TL.setSizeExpr(Reader.ReadDeclExpr());
|
||||
else
|
||||
TL.setSizeExpr(0);
|
||||
}
|
||||
void TypeLocReader::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) {
|
||||
VisitArrayTypeLoc(TL);
|
||||
}
|
||||
void TypeLocReader::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) {
|
||||
VisitArrayTypeLoc(TL);
|
||||
}
|
||||
void TypeLocReader::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
|
||||
VisitArrayTypeLoc(TL);
|
||||
}
|
||||
void TypeLocReader::VisitDependentSizedArrayTypeLoc(
|
||||
DependentSizedArrayTypeLoc TL) {
|
||||
VisitArrayTypeLoc(TL);
|
||||
}
|
||||
void TypeLocReader::VisitDependentSizedExtVectorTypeLoc(
|
||||
DependentSizedExtVectorTypeLoc TL) {
|
||||
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) {
|
||||
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
|
||||
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
|
||||
TL.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
TL.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) {
|
||||
TL.setArg(i, cast_or_null<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
|
||||
}
|
||||
}
|
||||
void TypeLocReader::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
|
||||
VisitFunctionTypeLoc(TL);
|
||||
}
|
||||
void TypeLocReader::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
|
||||
VisitFunctionTypeLoc(TL);
|
||||
}
|
||||
void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
|
||||
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
|
||||
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
|
||||
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
|
||||
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) {
|
||||
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) {
|
||||
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
|
||||
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
|
||||
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitSubstTemplateTypeParmTypeLoc(
|
||||
SubstTemplateTypeParmTypeLoc TL) {
|
||||
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitTemplateSpecializationTypeLoc(
|
||||
TemplateSpecializationTypeLoc TL) {
|
||||
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitQualifiedNameTypeLoc(QualifiedNameTypeLoc TL) {
|
||||
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitTypenameTypeLoc(TypenameTypeLoc TL) {
|
||||
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
|
||||
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
|
||||
TL.setProtocolLoc(i, SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
|
||||
TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
TL.setHasBaseTypeAsWritten(Record[Idx++]);
|
||||
TL.setHasProtocolsAsWritten(Record[Idx++]);
|
||||
if (TL.hasProtocolsAsWritten())
|
||||
for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
|
||||
TL.setProtocolLoc(i, SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
|
||||
DeclaratorInfo *PCHReader::GetDeclaratorInfo(const RecordData &Record,
|
||||
unsigned &Idx) {
|
||||
QualType InfoTy = GetType(Record[Idx++]);
|
||||
if (InfoTy.isNull())
|
||||
return 0;
|
||||
|
||||
DeclaratorInfo *DInfo = getContext()->CreateDeclaratorInfo(InfoTy);
|
||||
TypeLocReader TLR(*this, Record, Idx);
|
||||
for (TypeLoc TL = DInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
|
||||
TLR.Visit(TL);
|
||||
return DInfo;
|
||||
}
|
||||
|
||||
QualType PCHReader::GetType(pch::TypeID ID) {
|
||||
unsigned FastQuals = ID & Qualifiers::FastMask;
|
||||
@ -2374,7 +2515,10 @@ IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {
|
||||
// All of the strings in the PCH file are preceded by a 16-bit
|
||||
// length. Extract that 16-bit length to avoid having to execute
|
||||
// strlen().
|
||||
const char *StrLenPtr = Str - 2;
|
||||
// NOTE: 'StrLenPtr' is an 'unsigned char*' so that we load bytes as
|
||||
// unsigned integers. This is important to avoid integer overflow when
|
||||
// we cast them to 'unsigned'.
|
||||
const unsigned char *StrLenPtr = (const unsigned char*) Str - 2;
|
||||
unsigned StrLen = (((unsigned) StrLenPtr[0])
|
||||
| (((unsigned) StrLenPtr[1]) << 8)) - 1;
|
||||
IdentifiersLoaded[ID - 1]
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include "clang/AST/DeclVisitor.h"
|
||||
#include "clang/AST/DeclGroup.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/TypeLocVisitor.h"
|
||||
using namespace clang;
|
||||
|
||||
|
||||
@ -86,6 +85,7 @@ void PCHDeclReader::VisitDecl(Decl *D) {
|
||||
D->setImplicit(Record[Idx++]);
|
||||
D->setUsed(Record[Idx++]);
|
||||
D->setAccess((AccessSpecifier)Record[Idx++]);
|
||||
D->setPCHLevel(Record[Idx++] + 1);
|
||||
}
|
||||
|
||||
void PCHDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
|
||||
@ -149,84 +149,11 @@ void PCHDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) {
|
||||
ECD->setInitVal(Reader.ReadAPSInt(Record, Idx));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class TypeLocReader : public TypeLocVisitor<TypeLocReader> {
|
||||
PCHReader &Reader;
|
||||
const PCHReader::RecordData &Record;
|
||||
unsigned &Idx;
|
||||
|
||||
public:
|
||||
TypeLocReader(PCHReader &Reader, const PCHReader::RecordData &Record,
|
||||
unsigned &Idx)
|
||||
: Reader(Reader), Record(Record), Idx(Idx) { }
|
||||
|
||||
#define ABSTRACT_TYPELOC(CLASS)
|
||||
#define TYPELOC(CLASS, PARENT) \
|
||||
void Visit##CLASS(CLASS TyLoc);
|
||||
#include "clang/AST/TypeLocNodes.def"
|
||||
|
||||
void VisitTypeLoc(TypeLoc TyLoc) {
|
||||
assert(0 && "A type loc wrapper was not handled!");
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void TypeLocReader::VisitQualifiedLoc(QualifiedLoc TyLoc) {
|
||||
// nothing to do
|
||||
}
|
||||
void TypeLocReader::VisitDefaultTypeSpecLoc(DefaultTypeSpecLoc TyLoc) {
|
||||
TyLoc.setStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitTypedefLoc(TypedefLoc TyLoc) {
|
||||
TyLoc.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitObjCInterfaceLoc(ObjCInterfaceLoc TyLoc) {
|
||||
TyLoc.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitObjCProtocolListLoc(ObjCProtocolListLoc TyLoc) {
|
||||
TyLoc.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
TyLoc.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
for (unsigned i = 0, e = TyLoc.getNumProtocols(); i != e; ++i)
|
||||
TyLoc.setProtocolLoc(i, SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitPointerLoc(PointerLoc TyLoc) {
|
||||
TyLoc.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitBlockPointerLoc(BlockPointerLoc TyLoc) {
|
||||
TyLoc.setCaretLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitMemberPointerLoc(MemberPointerLoc TyLoc) {
|
||||
TyLoc.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitReferenceLoc(ReferenceLoc TyLoc) {
|
||||
TyLoc.setAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitFunctionLoc(FunctionLoc TyLoc) {
|
||||
TyLoc.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
TyLoc.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
for (unsigned i = 0, e = TyLoc.getNumArgs(); i != e; ++i)
|
||||
TyLoc.setArg(i, cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
|
||||
}
|
||||
void TypeLocReader::VisitArrayLoc(ArrayLoc TyLoc) {
|
||||
TyLoc.setLBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
TyLoc.setRBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
if (Record[Idx++])
|
||||
TyLoc.setSizeExpr(Reader.ReadDeclExpr());
|
||||
}
|
||||
|
||||
void PCHDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) {
|
||||
VisitValueDecl(DD);
|
||||
QualType InfoTy = Reader.GetType(Record[Idx++]);
|
||||
if (InfoTy.isNull())
|
||||
return;
|
||||
|
||||
DeclaratorInfo *DInfo = Reader.getContext()->CreateDeclaratorInfo(InfoTy);
|
||||
TypeLocReader TLR(Reader, Record, Idx);
|
||||
for (TypeLoc TL = DInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
|
||||
TLR.Visit(TL);
|
||||
DD->setDeclaratorInfo(DInfo);
|
||||
DeclaratorInfo *DInfo = Reader.GetDeclaratorInfo(Record, Idx);
|
||||
if (DInfo)
|
||||
DD->setDeclaratorInfo(DInfo);
|
||||
}
|
||||
|
||||
void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "clang/AST/DeclContextInternals.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/TypeLocVisitor.h"
|
||||
#include "clang/Lex/MacroInfo.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "clang/Lex/HeaderSearch.h"
|
||||
@ -30,6 +31,7 @@
|
||||
#include "clang/Basic/Version.h"
|
||||
#include "llvm/ADT/APFloat.h"
|
||||
#include "llvm/ADT/APInt.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/Bitcode/BitstreamWriter.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
@ -117,23 +119,6 @@ void PCHTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) {
|
||||
Code = pch::TYPE_CONSTANT_ARRAY;
|
||||
}
|
||||
|
||||
void PCHTypeWriter
|
||||
::VisitConstantArrayWithExprType(const ConstantArrayWithExprType *T) {
|
||||
VisitArrayType(T);
|
||||
Writer.AddSourceLocation(T->getLBracketLoc(), Record);
|
||||
Writer.AddSourceLocation(T->getRBracketLoc(), Record);
|
||||
Writer.AddAPInt(T->getSize(), Record);
|
||||
Writer.AddStmt(T->getSizeExpr());
|
||||
Code = pch::TYPE_CONSTANT_ARRAY_WITH_EXPR;
|
||||
}
|
||||
|
||||
void PCHTypeWriter
|
||||
::VisitConstantArrayWithoutExprType(const ConstantArrayWithoutExprType *T) {
|
||||
VisitArrayType(T);
|
||||
Writer.AddAPInt(T->getSize(), Record);
|
||||
Code = pch::TYPE_CONSTANT_ARRAY_WITHOUT_EXPR;
|
||||
}
|
||||
|
||||
void PCHTypeWriter::VisitIncompleteArrayType(const IncompleteArrayType *T) {
|
||||
VisitArrayType(T);
|
||||
Code = pch::TYPE_INCOMPLETE_ARRAY;
|
||||
@ -224,6 +209,14 @@ void PCHTypeWriter::VisitElaboratedType(const ElaboratedType *T) {
|
||||
Code = pch::TYPE_ELABORATED;
|
||||
}
|
||||
|
||||
void
|
||||
PCHTypeWriter::VisitSubstTemplateTypeParmType(
|
||||
const SubstTemplateTypeParmType *T) {
|
||||
Writer.AddTypeRef(QualType(T->getReplacedParameter(), 0), Record);
|
||||
Writer.AddTypeRef(T->getReplacementType(), Record);
|
||||
Code = pch::TYPE_SUBST_TEMPLATE_TYPE_PARM;
|
||||
}
|
||||
|
||||
void
|
||||
PCHTypeWriter::VisitTemplateSpecializationType(
|
||||
const TemplateSpecializationType *T) {
|
||||
@ -255,13 +248,150 @@ PCHTypeWriter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
|
||||
Code = pch::TYPE_OBJC_OBJECT_POINTER;
|
||||
}
|
||||
|
||||
void PCHTypeWriter::VisitObjCProtocolListType(const ObjCProtocolListType *T) {
|
||||
Writer.AddTypeRef(T->getBaseType(), Record);
|
||||
Record.push_back(T->getNumProtocols());
|
||||
for (ObjCProtocolListType::qual_iterator I = T->qual_begin(),
|
||||
E = T->qual_end(); I != E; ++I)
|
||||
Writer.AddDeclRef(*I, Record);
|
||||
Code = pch::TYPE_OBJC_PROTOCOL_LIST;
|
||||
namespace {
|
||||
|
||||
class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> {
|
||||
PCHWriter &Writer;
|
||||
PCHWriter::RecordData &Record;
|
||||
|
||||
public:
|
||||
TypeLocWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
|
||||
: Writer(Writer), Record(Record) { }
|
||||
|
||||
#define ABSTRACT_TYPELOC(CLASS, PARENT)
|
||||
#define TYPELOC(CLASS, PARENT) \
|
||||
void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
|
||||
#include "clang/AST/TypeLocNodes.def"
|
||||
|
||||
void VisitArrayTypeLoc(ArrayTypeLoc TyLoc);
|
||||
void VisitFunctionTypeLoc(FunctionTypeLoc TyLoc);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void TypeLocWriter::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
|
||||
// nothing to do
|
||||
}
|
||||
void TypeLocWriter::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getNameLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitFixedWidthIntTypeLoc(FixedWidthIntTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getNameLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitComplexTypeLoc(ComplexTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getNameLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitPointerTypeLoc(PointerTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getStarLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getCaretLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getAmpLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getAmpAmpLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getStarLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitArrayTypeLoc(ArrayTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getLBracketLoc(), Record);
|
||||
Writer.AddSourceLocation(TL.getRBracketLoc(), Record);
|
||||
Record.push_back(TL.getSizeExpr() ? 1 : 0);
|
||||
if (TL.getSizeExpr())
|
||||
Writer.AddStmt(TL.getSizeExpr());
|
||||
}
|
||||
void TypeLocWriter::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) {
|
||||
VisitArrayTypeLoc(TL);
|
||||
}
|
||||
void TypeLocWriter::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) {
|
||||
VisitArrayTypeLoc(TL);
|
||||
}
|
||||
void TypeLocWriter::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
|
||||
VisitArrayTypeLoc(TL);
|
||||
}
|
||||
void TypeLocWriter::VisitDependentSizedArrayTypeLoc(
|
||||
DependentSizedArrayTypeLoc TL) {
|
||||
VisitArrayTypeLoc(TL);
|
||||
}
|
||||
void TypeLocWriter::VisitDependentSizedExtVectorTypeLoc(
|
||||
DependentSizedExtVectorTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getNameLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitVectorTypeLoc(VectorTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getNameLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getNameLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getLParenLoc(), Record);
|
||||
Writer.AddSourceLocation(TL.getRParenLoc(), Record);
|
||||
for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
|
||||
Writer.AddDeclRef(TL.getArg(i), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
|
||||
VisitFunctionTypeLoc(TL);
|
||||
}
|
||||
void TypeLocWriter::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
|
||||
VisitFunctionTypeLoc(TL);
|
||||
}
|
||||
void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getNameLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getNameLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getNameLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getNameLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitRecordTypeLoc(RecordTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getNameLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitEnumTypeLoc(EnumTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getNameLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getNameLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getNameLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitSubstTemplateTypeParmTypeLoc(
|
||||
SubstTemplateTypeParmTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getNameLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitTemplateSpecializationTypeLoc(
|
||||
TemplateSpecializationTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getNameLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitQualifiedNameTypeLoc(QualifiedNameTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getNameLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitTypenameTypeLoc(TypenameTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getNameLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getNameLoc(), Record);
|
||||
Writer.AddSourceLocation(TL.getLAngleLoc(), Record);
|
||||
Writer.AddSourceLocation(TL.getRAngleLoc(), Record);
|
||||
for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
|
||||
Writer.AddSourceLocation(TL.getProtocolLoc(i), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getStarLoc(), Record);
|
||||
Writer.AddSourceLocation(TL.getLAngleLoc(), Record);
|
||||
Writer.AddSourceLocation(TL.getRAngleLoc(), Record);
|
||||
Record.push_back(TL.hasBaseTypeAsWritten());
|
||||
Record.push_back(TL.hasProtocolsAsWritten());
|
||||
if (TL.hasProtocolsAsWritten())
|
||||
for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
|
||||
Writer.AddSourceLocation(TL.getProtocolLoc(i), Record);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -411,8 +541,8 @@ void PCHWriter::WriteBlockInfoBlock() {
|
||||
RECORD(PP_MACRO_FUNCTION_LIKE);
|
||||
RECORD(PP_TOKEN);
|
||||
|
||||
// Types block.
|
||||
BLOCK(TYPES_BLOCK);
|
||||
// Decls and Types block.
|
||||
BLOCK(DECLTYPES_BLOCK);
|
||||
RECORD(TYPE_EXT_QUAL);
|
||||
RECORD(TYPE_FIXED_WIDTH_INT);
|
||||
RECORD(TYPE_COMPLEX);
|
||||
@ -435,12 +565,6 @@ void PCHWriter::WriteBlockInfoBlock() {
|
||||
RECORD(TYPE_ENUM);
|
||||
RECORD(TYPE_OBJC_INTERFACE);
|
||||
RECORD(TYPE_OBJC_OBJECT_POINTER);
|
||||
RECORD(TYPE_OBJC_PROTOCOL_LIST);
|
||||
// Statements and Exprs can occur in the Types block.
|
||||
AddStmtsExprs(Stream, Record);
|
||||
|
||||
// Decls block.
|
||||
BLOCK(DECLS_BLOCK);
|
||||
RECORD(DECL_ATTR);
|
||||
RECORD(DECL_TRANSLATION_UNIT);
|
||||
RECORD(DECL_TYPEDEF);
|
||||
@ -470,7 +594,7 @@ void PCHWriter::WriteBlockInfoBlock() {
|
||||
RECORD(DECL_BLOCK);
|
||||
RECORD(DECL_CONTEXT_LEXICAL);
|
||||
RECORD(DECL_CONTEXT_VISIBLE);
|
||||
// Statements and Exprs can occur in the Decls block.
|
||||
// Statements and Exprs can occur in the Decls and Types block.
|
||||
AddStmtsExprs(Stream, Record);
|
||||
#undef RECORD
|
||||
#undef BLOCK
|
||||
@ -662,7 +786,7 @@ class VISIBILITY_HIDDEN PCHStatCacheTrait {
|
||||
typedef const data_type& data_type_ref;
|
||||
|
||||
static unsigned ComputeHash(const char *path) {
|
||||
return BernsteinHash(path);
|
||||
return llvm::HashString(path);
|
||||
}
|
||||
|
||||
std::pair<unsigned,unsigned>
|
||||
@ -878,10 +1002,10 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
|
||||
std::vector<uint32_t> SLocEntryOffsets;
|
||||
RecordData PreloadSLocs;
|
||||
SLocEntryOffsets.reserve(SourceMgr.sloc_entry_size() - 1);
|
||||
for (SourceManager::sloc_entry_iterator
|
||||
SLoc = SourceMgr.sloc_entry_begin() + 1,
|
||||
SLocEnd = SourceMgr.sloc_entry_end();
|
||||
SLoc != SLocEnd; ++SLoc) {
|
||||
for (unsigned I = 1, N = SourceMgr.sloc_entry_size(); I != N; ++I) {
|
||||
// Get this source location entry.
|
||||
const SrcMgr::SLocEntry *SLoc = &SourceMgr.getSLocEntry(I);
|
||||
|
||||
// Record the offset of this source-location entry.
|
||||
SLocEntryOffsets.push_back(Stream.GetCurrentBitNo());
|
||||
|
||||
@ -956,9 +1080,8 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
|
||||
|
||||
// Compute the token length for this macro expansion.
|
||||
unsigned NextOffset = SourceMgr.getNextOffset();
|
||||
SourceManager::sloc_entry_iterator NextSLoc = SLoc;
|
||||
if (++NextSLoc != SLocEnd)
|
||||
NextOffset = NextSLoc->getOffset();
|
||||
if (I + 1 != N)
|
||||
NextOffset = SourceMgr.getSLocEntry(I + 1).getOffset();
|
||||
Record.push_back(NextOffset - SLoc->getOffset() - 1);
|
||||
Stream.EmitRecordWithAbbrev(SLocInstantiationAbbrv, Record);
|
||||
}
|
||||
@ -1019,6 +1142,7 @@ void PCHWriter::WritePreprocessor(const Preprocessor &PP) {
|
||||
|
||||
// Loop over all the macro definitions that are live at the end of the file,
|
||||
// emitting each to the PP section.
|
||||
// FIXME: Make sure that this sees macros defined in included PCH files.
|
||||
for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end();
|
||||
I != E; ++I) {
|
||||
// FIXME: This emits macros in hash table order, we should do it in a stable
|
||||
@ -1152,22 +1276,6 @@ void PCHWriter::WriteType(QualType T) {
|
||||
FlushStmts();
|
||||
}
|
||||
|
||||
/// \brief Write a block containing all of the types.
|
||||
void PCHWriter::WriteTypesBlock(ASTContext &Context) {
|
||||
// Enter the types block.
|
||||
Stream.EnterSubblock(pch::TYPES_BLOCK_ID, 2);
|
||||
|
||||
// Emit all of the types that need to be emitted (so far).
|
||||
while (!TypesToEmit.empty()) {
|
||||
QualType T = TypesToEmit.front();
|
||||
TypesToEmit.pop();
|
||||
WriteType(T);
|
||||
}
|
||||
|
||||
// Exit the types block
|
||||
Stream.ExitBlock();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Declaration Serialization
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -1266,7 +1374,7 @@ class VISIBILITY_HIDDEN PCHMethodPoolTrait {
|
||||
unsigned R = 5381;
|
||||
for (unsigned I = 0; I != N; ++I)
|
||||
if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I))
|
||||
R = clang::BernsteinHashPartial(II->getName(), II->getLength(), R);
|
||||
R = llvm::HashString(II->getName(), R);
|
||||
return R;
|
||||
}
|
||||
|
||||
@ -1475,13 +1583,13 @@ class VISIBILITY_HIDDEN PCHIdentifierTableTrait {
|
||||
: Writer(Writer), PP(PP) { }
|
||||
|
||||
static unsigned ComputeHash(const IdentifierInfo* II) {
|
||||
return clang::BernsteinHash(II->getName());
|
||||
return llvm::HashString(II->getName());
|
||||
}
|
||||
|
||||
std::pair<unsigned,unsigned>
|
||||
EmitKeyDataLength(llvm::raw_ostream& Out, const IdentifierInfo* II,
|
||||
pch::IdentID ID) {
|
||||
unsigned KeyLen = strlen(II->getName()) + 1;
|
||||
unsigned KeyLen = II->getLength() + 1;
|
||||
unsigned DataLen = 4; // 4 bytes for the persistent ID << 1
|
||||
if (isInterestingIdentifier(II)) {
|
||||
DataLen += 2; // 2 bytes for builtin ID, flags
|
||||
@ -1506,7 +1614,7 @@ class VISIBILITY_HIDDEN PCHIdentifierTableTrait {
|
||||
// Record the location of the key data. This is used when generating
|
||||
// the mapping from persistent IDs to strings.
|
||||
Writer.SetIdentifierOffset(II, Out.tell());
|
||||
Out.write(II->getName(), KeyLen);
|
||||
Out.write(II->getNameStart(), KeyLen);
|
||||
}
|
||||
|
||||
void EmitData(llvm::raw_ostream& Out, const IdentifierInfo* II,
|
||||
@ -1810,7 +1918,7 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,
|
||||
|
||||
// The translation unit is the first declaration we'll emit.
|
||||
DeclIDs[Context.getTranslationUnitDecl()] = 1;
|
||||
DeclsToEmit.push(Context.getTranslationUnitDecl());
|
||||
DeclTypesToEmit.push(Context.getTranslationUnitDecl());
|
||||
|
||||
// Make sure that we emit IdentifierInfos (and any attached
|
||||
// declarations) for builtins.
|
||||
@ -1858,7 +1966,6 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,
|
||||
if (StatCalls && !isysroot)
|
||||
WriteStatCache(*StatCalls, isysroot);
|
||||
WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot);
|
||||
WritePreprocessor(PP);
|
||||
WriteComments(Context);
|
||||
// Write the record of special types.
|
||||
Record.clear();
|
||||
@ -1875,17 +1982,25 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,
|
||||
AddTypeRef(Context.getsigjmp_bufType(), Record);
|
||||
AddTypeRef(Context.ObjCIdRedefinitionType, Record);
|
||||
AddTypeRef(Context.ObjCClassRedefinitionType, Record);
|
||||
AddTypeRef(Context.getRawBlockdescriptorType(), Record);
|
||||
AddTypeRef(Context.getRawBlockdescriptorExtendedType(), Record);
|
||||
Stream.EmitRecord(pch::SPECIAL_TYPES, Record);
|
||||
|
||||
// Keep writing types and declarations until all types and
|
||||
// declarations have been written.
|
||||
do {
|
||||
if (!DeclsToEmit.empty())
|
||||
WriteDeclsBlock(Context);
|
||||
if (!TypesToEmit.empty())
|
||||
WriteTypesBlock(Context);
|
||||
} while (!(DeclsToEmit.empty() && TypesToEmit.empty()));
|
||||
|
||||
Stream.EnterSubblock(pch::DECLTYPES_BLOCK_ID, 3);
|
||||
WriteDeclsBlockAbbrevs();
|
||||
while (!DeclTypesToEmit.empty()) {
|
||||
DeclOrType DOT = DeclTypesToEmit.front();
|
||||
DeclTypesToEmit.pop();
|
||||
if (DOT.isType())
|
||||
WriteType(DOT.getType());
|
||||
else
|
||||
WriteDecl(Context, DOT.getDecl());
|
||||
}
|
||||
Stream.ExitBlock();
|
||||
|
||||
WritePreprocessor(PP);
|
||||
WriteMethodPool(SemaRef);
|
||||
WriteIdentifierTable(PP);
|
||||
|
||||
@ -1991,6 +2106,18 @@ void PCHWriter::AddSelectorRef(const Selector SelRef, RecordData &Record) {
|
||||
Record.push_back(SID);
|
||||
}
|
||||
|
||||
void PCHWriter::AddDeclaratorInfo(DeclaratorInfo *DInfo, RecordData &Record) {
|
||||
if (DInfo == 0) {
|
||||
AddTypeRef(QualType(), Record);
|
||||
return;
|
||||
}
|
||||
|
||||
AddTypeRef(DInfo->getType(), Record);
|
||||
TypeLocWriter TLW(*this, Record);
|
||||
for (TypeLoc TL = DInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
|
||||
TLW.Visit(TL);
|
||||
}
|
||||
|
||||
void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
|
||||
if (T.isNull()) {
|
||||
Record.push_back(pch::PREDEF_TYPE_NULL_ID);
|
||||
@ -2007,7 +2134,7 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
|
||||
// Assign it a new ID. This is the only time we enqueue a
|
||||
// qualified type, and it has no CV qualifiers.
|
||||
ID = NextTypeID++;
|
||||
TypesToEmit.push(T);
|
||||
DeclTypesToEmit.push(T);
|
||||
}
|
||||
|
||||
// Encode the type qualifiers in the type reference.
|
||||
@ -2061,7 +2188,7 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
|
||||
// We haven't seen this type before. Assign it a new ID and put it
|
||||
// into the queue of types to emit.
|
||||
ID = NextTypeID++;
|
||||
TypesToEmit.push(T);
|
||||
DeclTypesToEmit.push(T);
|
||||
}
|
||||
|
||||
// Encode the type qualifiers in the type reference.
|
||||
@ -2079,7 +2206,7 @@ void PCHWriter::AddDeclRef(const Decl *D, RecordData &Record) {
|
||||
// We haven't seen this declaration before. Give it a new ID and
|
||||
// enqueue it in the list of declarations to emit.
|
||||
ID = DeclIDs.size();
|
||||
DeclsToEmit.push(const_cast<Decl *>(D));
|
||||
DeclTypesToEmit.push(const_cast<Decl *>(D));
|
||||
}
|
||||
|
||||
Record.push_back(ID);
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include "clang/Frontend/PCHWriter.h"
|
||||
#include "clang/AST/DeclVisitor.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/TypeLocVisitor.h"
|
||||
#include "llvm/Bitcode/BitstreamWriter.h"
|
||||
#include <cstdio>
|
||||
|
||||
@ -88,6 +87,7 @@ void PCHDeclWriter::VisitDecl(Decl *D) {
|
||||
Record.push_back(D->isImplicit());
|
||||
Record.push_back(D->isUsed());
|
||||
Record.push_back(D->getAccess());
|
||||
Record.push_back(D->getPCHLevel());
|
||||
}
|
||||
|
||||
void PCHDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
|
||||
@ -149,84 +149,10 @@ void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) {
|
||||
Writer.AddAPSInt(D->getInitVal(), Record);
|
||||
Code = pch::DECL_ENUM_CONSTANT;
|
||||
}
|
||||
namespace {
|
||||
|
||||
class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> {
|
||||
PCHWriter &Writer;
|
||||
PCHWriter::RecordData &Record;
|
||||
|
||||
public:
|
||||
TypeLocWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
|
||||
: Writer(Writer), Record(Record) { }
|
||||
|
||||
#define ABSTRACT_TYPELOC(CLASS)
|
||||
#define TYPELOC(CLASS, PARENT) \
|
||||
void Visit##CLASS(CLASS TyLoc);
|
||||
#include "clang/AST/TypeLocNodes.def"
|
||||
|
||||
void VisitTypeLoc(TypeLoc TyLoc) {
|
||||
assert(0 && "A type loc wrapper was not handled!");
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void TypeLocWriter::VisitQualifiedLoc(QualifiedLoc TyLoc) {
|
||||
// nothing to do here
|
||||
}
|
||||
void TypeLocWriter::VisitDefaultTypeSpecLoc(DefaultTypeSpecLoc TyLoc) {
|
||||
Writer.AddSourceLocation(TyLoc.getStartLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitTypedefLoc(TypedefLoc TyLoc) {
|
||||
Writer.AddSourceLocation(TyLoc.getNameLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitObjCInterfaceLoc(ObjCInterfaceLoc TyLoc) {
|
||||
Writer.AddSourceLocation(TyLoc.getNameLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitObjCProtocolListLoc(ObjCProtocolListLoc TyLoc) {
|
||||
Writer.AddSourceLocation(TyLoc.getLAngleLoc(), Record);
|
||||
Writer.AddSourceLocation(TyLoc.getRAngleLoc(), Record);
|
||||
for (unsigned i = 0, e = TyLoc.getNumProtocols(); i != e; ++i)
|
||||
Writer.AddSourceLocation(TyLoc.getProtocolLoc(i), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitPointerLoc(PointerLoc TyLoc) {
|
||||
Writer.AddSourceLocation(TyLoc.getStarLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitBlockPointerLoc(BlockPointerLoc TyLoc) {
|
||||
Writer.AddSourceLocation(TyLoc.getCaretLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitMemberPointerLoc(MemberPointerLoc TyLoc) {
|
||||
Writer.AddSourceLocation(TyLoc.getStarLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitReferenceLoc(ReferenceLoc TyLoc) {
|
||||
Writer.AddSourceLocation(TyLoc.getAmpLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitFunctionLoc(FunctionLoc TyLoc) {
|
||||
Writer.AddSourceLocation(TyLoc.getLParenLoc(), Record);
|
||||
Writer.AddSourceLocation(TyLoc.getRParenLoc(), Record);
|
||||
for (unsigned i = 0, e = TyLoc.getNumArgs(); i != e; ++i)
|
||||
Writer.AddDeclRef(TyLoc.getArg(i), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitArrayLoc(ArrayLoc TyLoc) {
|
||||
Writer.AddSourceLocation(TyLoc.getLBracketLoc(), Record);
|
||||
Writer.AddSourceLocation(TyLoc.getRBracketLoc(), Record);
|
||||
Record.push_back(TyLoc.getSizeExpr() ? 1 : 0);
|
||||
if (TyLoc.getSizeExpr())
|
||||
Writer.AddStmt(TyLoc.getSizeExpr());
|
||||
}
|
||||
|
||||
void PCHDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) {
|
||||
VisitValueDecl(D);
|
||||
DeclaratorInfo *DInfo = D->getDeclaratorInfo();
|
||||
if (DInfo == 0) {
|
||||
Writer.AddTypeRef(QualType(), Record);
|
||||
return;
|
||||
}
|
||||
|
||||
Writer.AddTypeRef(DInfo->getTypeLoc().getSourceType(), Record);
|
||||
TypeLocWriter TLW(Writer, Record);
|
||||
for (TypeLoc TL = DInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
|
||||
TLW.Visit(TL);
|
||||
Writer.AddDeclaratorInfo(D->getDeclaratorInfo(), Record);
|
||||
}
|
||||
|
||||
void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
|
||||
@ -448,6 +374,7 @@ void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
|
||||
!D->isImplicit() &&
|
||||
!D->isUsed() &&
|
||||
D->getAccess() == AS_none &&
|
||||
D->getPCHLevel() == 0 &&
|
||||
D->getStorageClass() == 0 &&
|
||||
!D->hasCXXDirectInitializer() && // Can params have this ever?
|
||||
D->getObjCDeclQualifier() == 0)
|
||||
@ -523,6 +450,7 @@ void PCHWriter::WriteDeclsBlockAbbrevs() {
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // isImplicit
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // isUsed
|
||||
Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // PCH level
|
||||
|
||||
// NamedDecl
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier
|
||||
@ -607,80 +535,64 @@ static bool isRequiredDecl(const Decl *D, ASTContext &Context) {
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Write a block containing all of the declarations.
|
||||
void PCHWriter::WriteDeclsBlock(ASTContext &Context) {
|
||||
// Enter the declarations block.
|
||||
Stream.EnterSubblock(pch::DECLS_BLOCK_ID, 3);
|
||||
|
||||
// Output the abbreviations that we will use in this block.
|
||||
WriteDeclsBlockAbbrevs();
|
||||
|
||||
// Emit all of the declarations.
|
||||
void PCHWriter::WriteDecl(ASTContext &Context, Decl *D) {
|
||||
RecordData Record;
|
||||
PCHDeclWriter W(*this, Context, Record);
|
||||
while (!DeclsToEmit.empty()) {
|
||||
// Pull the next declaration off the queue
|
||||
Decl *D = DeclsToEmit.front();
|
||||
DeclsToEmit.pop();
|
||||
|
||||
// If this declaration is also a DeclContext, write blocks for the
|
||||
// declarations that lexically stored inside its context and those
|
||||
// declarations that are visible from its context. These blocks
|
||||
// are written before the declaration itself so that we can put
|
||||
// their offsets into the record for the declaration.
|
||||
uint64_t LexicalOffset = 0;
|
||||
uint64_t VisibleOffset = 0;
|
||||
DeclContext *DC = dyn_cast<DeclContext>(D);
|
||||
if (DC) {
|
||||
LexicalOffset = WriteDeclContextLexicalBlock(Context, DC);
|
||||
VisibleOffset = WriteDeclContextVisibleBlock(Context, DC);
|
||||
}
|
||||
|
||||
// Determine the ID for this declaration
|
||||
pch::DeclID &ID = DeclIDs[D];
|
||||
if (ID == 0)
|
||||
ID = DeclIDs.size();
|
||||
|
||||
unsigned Index = ID - 1;
|
||||
|
||||
// Record the offset for this declaration
|
||||
if (DeclOffsets.size() == Index)
|
||||
DeclOffsets.push_back(Stream.GetCurrentBitNo());
|
||||
else if (DeclOffsets.size() < Index) {
|
||||
DeclOffsets.resize(Index+1);
|
||||
DeclOffsets[Index] = Stream.GetCurrentBitNo();
|
||||
}
|
||||
|
||||
// Build and emit a record for this declaration
|
||||
Record.clear();
|
||||
W.Code = (pch::DeclCode)0;
|
||||
W.AbbrevToUse = 0;
|
||||
W.Visit(D);
|
||||
if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset);
|
||||
|
||||
if (!W.Code) {
|
||||
fprintf(stderr, "Cannot serialize declaration of kind %s\n",
|
||||
D->getDeclKindName());
|
||||
assert(false && "Unhandled declaration kind while generating PCH");
|
||||
exit(-1);
|
||||
}
|
||||
Stream.EmitRecord(W.Code, Record, W.AbbrevToUse);
|
||||
|
||||
// If the declaration had any attributes, write them now.
|
||||
if (D->hasAttrs())
|
||||
WriteAttributeRecord(D->getAttrs());
|
||||
|
||||
// Flush any expressions that were written as part of this declaration.
|
||||
FlushStmts();
|
||||
|
||||
// Note "external" declarations so that we can add them to a record in the
|
||||
// PCH file later.
|
||||
//
|
||||
// FIXME: This should be renamed, the predicate is much more complicated.
|
||||
if (isRequiredDecl(D, Context))
|
||||
ExternalDefinitions.push_back(ID);
|
||||
// If this declaration is also a DeclContext, write blocks for the
|
||||
// declarations that lexically stored inside its context and those
|
||||
// declarations that are visible from its context. These blocks
|
||||
// are written before the declaration itself so that we can put
|
||||
// their offsets into the record for the declaration.
|
||||
uint64_t LexicalOffset = 0;
|
||||
uint64_t VisibleOffset = 0;
|
||||
DeclContext *DC = dyn_cast<DeclContext>(D);
|
||||
if (DC) {
|
||||
LexicalOffset = WriteDeclContextLexicalBlock(Context, DC);
|
||||
VisibleOffset = WriteDeclContextVisibleBlock(Context, DC);
|
||||
}
|
||||
|
||||
// Exit the declarations block
|
||||
Stream.ExitBlock();
|
||||
// Determine the ID for this declaration
|
||||
pch::DeclID &ID = DeclIDs[D];
|
||||
if (ID == 0)
|
||||
ID = DeclIDs.size();
|
||||
|
||||
unsigned Index = ID - 1;
|
||||
|
||||
// Record the offset for this declaration
|
||||
if (DeclOffsets.size() == Index)
|
||||
DeclOffsets.push_back(Stream.GetCurrentBitNo());
|
||||
else if (DeclOffsets.size() < Index) {
|
||||
DeclOffsets.resize(Index+1);
|
||||
DeclOffsets[Index] = Stream.GetCurrentBitNo();
|
||||
}
|
||||
|
||||
// Build and emit a record for this declaration
|
||||
Record.clear();
|
||||
W.Code = (pch::DeclCode)0;
|
||||
W.AbbrevToUse = 0;
|
||||
W.Visit(D);
|
||||
if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset);
|
||||
|
||||
if (!W.Code) {
|
||||
fprintf(stderr, "Cannot serialize declaration of kind %s\n",
|
||||
D->getDeclKindName());
|
||||
assert(false && "Unhandled declaration kind while generating PCH");
|
||||
exit(-1);
|
||||
}
|
||||
Stream.EmitRecord(W.Code, Record, W.AbbrevToUse);
|
||||
|
||||
// If the declaration had any attributes, write them now.
|
||||
if (D->hasAttrs())
|
||||
WriteAttributeRecord(D->getAttrs());
|
||||
|
||||
// Flush any expressions that were written as part of this declaration.
|
||||
FlushStmts();
|
||||
|
||||
// Note "external" declarations so that we can add them to a record in the
|
||||
// PCH file later.
|
||||
//
|
||||
// FIXME: This should be renamed, the predicate is much more complicated.
|
||||
if (isRequiredDecl(D, Context))
|
||||
ExternalDefinitions.push_back(Index + 1);
|
||||
}
|
||||
|
@ -399,7 +399,7 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
|
||||
}
|
||||
|
||||
if (IdentifierInfo *II = Tok.getIdentifierInfo()) {
|
||||
OS.write(II->getName(), II->getLength());
|
||||
OS << II->getName();
|
||||
} else if (Tok.isLiteral() && !Tok.needsCleaning() &&
|
||||
Tok.getLiteralData()) {
|
||||
OS.write(Tok.getLiteralData(), Tok.getLength());
|
||||
@ -434,7 +434,7 @@ namespace {
|
||||
struct SortMacrosByID {
|
||||
typedef std::pair<IdentifierInfo*, MacroInfo*> id_macro_pair;
|
||||
bool operator()(const id_macro_pair &LHS, const id_macro_pair &RHS) const {
|
||||
return strcmp(LHS.first->getName(), RHS.first->getName()) < 0;
|
||||
return LHS.first->getName() < RHS.first->getName();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -128,13 +128,13 @@ void clang::RewriteMacrosInInput(Preprocessor &PP, llvm::raw_ostream *OS) {
|
||||
// comment the line out.
|
||||
if (RawTokens[CurRawTok].is(tok::identifier)) {
|
||||
const IdentifierInfo *II = RawTokens[CurRawTok].getIdentifierInfo();
|
||||
if (!strcmp(II->getName(), "warning")) {
|
||||
if (II->getName() == "warning") {
|
||||
// Comment out #warning.
|
||||
RB.InsertTextAfter(SM.getFileOffset(RawTok.getLocation()), "//");
|
||||
} else if (!strcmp(II->getName(), "pragma") &&
|
||||
} else if (II->getName() == "pragma" &&
|
||||
RawTokens[CurRawTok+1].is(tok::identifier) &&
|
||||
!strcmp(RawTokens[CurRawTok+1].getIdentifierInfo()->getName(),
|
||||
"mark")){
|
||||
(RawTokens[CurRawTok+1].getIdentifierInfo()->getName() ==
|
||||
"mark")) {
|
||||
// Comment out #pragma mark.
|
||||
RB.InsertTextAfter(SM.getFileOffset(RawTok.getLocation()), "//");
|
||||
}
|
||||
|
@ -675,7 +675,7 @@ static std::string getIvarAccessString(ObjCInterfaceDecl *ClassDecl,
|
||||
S = "((struct ";
|
||||
S += ClassDecl->getIdentifier()->getName();
|
||||
S += "_IMPL *)self)->";
|
||||
S += OID->getNameAsCString();
|
||||
S += OID->getName();
|
||||
return S;
|
||||
}
|
||||
|
||||
@ -2265,7 +2265,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
|
||||
if (clsName) { // class message.
|
||||
// FIXME: We need to fix Sema (and the AST for ObjCMessageExpr) to handle
|
||||
// the 'super' idiom within a class method.
|
||||
if (!strcmp(clsName->getName(), "super")) {
|
||||
if (clsName->getName() == "super") {
|
||||
MsgSendFlavor = MsgSendSuperFunctionDecl;
|
||||
if (MsgSendStretFlavor)
|
||||
MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
|
||||
@ -2289,9 +2289,9 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
|
||||
llvm::SmallVector<Expr*, 8> ClsExprs;
|
||||
QualType argType = Context->getPointerType(Context->CharTy);
|
||||
ClsExprs.push_back(StringLiteral::Create(*Context,
|
||||
SuperDecl->getIdentifier()->getName(),
|
||||
SuperDecl->getIdentifier()->getLength(),
|
||||
false, argType, SourceLocation()));
|
||||
SuperDecl->getIdentifier()->getNameStart(),
|
||||
SuperDecl->getIdentifier()->getLength(),
|
||||
false, argType, SourceLocation()));
|
||||
CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
|
||||
&ClsExprs[0],
|
||||
ClsExprs.size());
|
||||
@ -2343,7 +2343,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
|
||||
llvm::SmallVector<Expr*, 8> ClsExprs;
|
||||
QualType argType = Context->getPointerType(Context->CharTy);
|
||||
ClsExprs.push_back(StringLiteral::Create(*Context,
|
||||
clsName->getName(),
|
||||
clsName->getNameStart(),
|
||||
clsName->getLength(),
|
||||
false, argType,
|
||||
SourceLocation()));
|
||||
@ -2375,9 +2375,9 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
|
||||
llvm::SmallVector<Expr*, 8> ClsExprs;
|
||||
QualType argType = Context->getPointerType(Context->CharTy);
|
||||
ClsExprs.push_back(StringLiteral::Create(*Context,
|
||||
SuperDecl->getIdentifier()->getName(),
|
||||
SuperDecl->getIdentifier()->getLength(),
|
||||
false, argType, SourceLocation()));
|
||||
SuperDecl->getIdentifier()->getNameStart(),
|
||||
SuperDecl->getIdentifier()->getLength(),
|
||||
false, argType, SourceLocation()));
|
||||
CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
|
||||
&ClsExprs[0],
|
||||
ClsExprs.size());
|
||||
|
@ -214,6 +214,7 @@ static void SelectInterestingSourceRegion(std::string &SourceLine,
|
||||
// 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;
|
||||
|
||||
// Skip over any whitespace we see here; we're looking for
|
||||
@ -320,6 +321,11 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
|
||||
while (*LineEnd != '\n' && *LineEnd != '\r' && *LineEnd != '\0')
|
||||
++LineEnd;
|
||||
|
||||
// FIXME: This shouldn't be necessary, but the CaretEndColNo can extend past
|
||||
// the source line length as currently being computed. See
|
||||
// test/Misc/message-length.c.
|
||||
CaretEndColNo = std::min(CaretEndColNo, unsigned(LineEnd - LineStart));
|
||||
|
||||
// Copy the line of code into an std::string for ease of manipulation.
|
||||
std::string SourceLine(LineStart, LineEnd);
|
||||
|
||||
|
@ -101,7 +101,7 @@ void ASTLocation::print(llvm::raw_ostream &OS) const {
|
||||
break;
|
||||
|
||||
case N_Type: {
|
||||
QualType T = AsTypeLoc().getSourceType();
|
||||
QualType T = AsTypeLoc().getType();
|
||||
OS << "[Type: " << T->getTypeClassName() << " " << T.getAsString();
|
||||
}
|
||||
}
|
||||
|
@ -123,14 +123,14 @@ class ASTVisitor : public DeclVisitor<ImplClass>,
|
||||
BaseTypeLocVisitor::Visit(TL);
|
||||
}
|
||||
|
||||
void VisitArrayLoc(ArrayLoc TL) {
|
||||
BaseTypeLocVisitor::VisitArrayLoc(TL);
|
||||
void VisitArrayLoc(ArrayTypeLoc TL) {
|
||||
BaseTypeLocVisitor::VisitArrayTypeLoc(TL);
|
||||
if (TL.getSizeExpr())
|
||||
Visit(TL.getSizeExpr());
|
||||
}
|
||||
|
||||
void VisitFunctionLoc(FunctionLoc TL) {
|
||||
BaseTypeLocVisitor::VisitFunctionLoc(TL);
|
||||
void VisitFunctionTypeLoc(FunctionTypeLoc TL) {
|
||||
BaseTypeLocVisitor::VisitFunctionTypeLoc(TL);
|
||||
for (unsigned i = 0; i != TL.getNumArgs(); ++i)
|
||||
Visit(TL.getArg(i));
|
||||
}
|
||||
|
@ -31,8 +31,8 @@ class VISIBILITY_HIDDEN RefMapper : public ASTVisitor<RefMapper> {
|
||||
void VisitMemberExpr(MemberExpr *Node);
|
||||
void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node);
|
||||
|
||||
void VisitTypedefLoc(TypedefLoc TL);
|
||||
void VisitObjCInterfaceLoc(ObjCInterfaceLoc TL);
|
||||
void VisitTypedefTypeLoc(TypedefTypeLoc TL);
|
||||
void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL);
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
@ -55,12 +55,12 @@ void RefMapper::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
|
||||
Map.insert(std::make_pair(Node->getDecl(), ASTLocation(CurrentDecl, Node)));
|
||||
}
|
||||
|
||||
void RefMapper::VisitTypedefLoc(TypedefLoc TL) {
|
||||
void RefMapper::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
|
||||
NamedDecl *ND = TL.getTypedefDecl();
|
||||
Map.insert(std::make_pair(ND, ASTLocation(CurrentDecl, ND, TL.getNameLoc())));
|
||||
}
|
||||
|
||||
void RefMapper::VisitObjCInterfaceLoc(ObjCInterfaceLoc TL) {
|
||||
void RefMapper::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
|
||||
NamedDecl *ND = TL.getIFaceDecl();
|
||||
Map.insert(std::make_pair(ND, ASTLocation(CurrentDecl, ND, TL.getNameLoc())));
|
||||
}
|
||||
|
@ -72,7 +72,8 @@ Entity EntityGetter::VisitNamedDecl(NamedDecl *D) {
|
||||
|
||||
if (IdentifierInfo *II = LocalName.getAsIdentifierInfo()) {
|
||||
IdentifierInfo *GlobII =
|
||||
&ProgImpl.getIdents().get(II->getName(), II->getName() + II->getLength());
|
||||
&ProgImpl.getIdents().get(II->getNameStart(),
|
||||
II->getNameStart() + II->getLength());
|
||||
GlobName = DeclarationName(GlobII);
|
||||
} else {
|
||||
Selector LocalSel = LocalName.getObjCSelector();
|
||||
@ -139,8 +140,9 @@ Decl *EntityImpl::getDecl(ASTContext &AST) {
|
||||
DeclarationName LocalName;
|
||||
|
||||
if (IdentifierInfo *GlobII = Name.getAsIdentifierInfo()) {
|
||||
IdentifierInfo &II = AST.Idents.get(GlobII->getName(),
|
||||
GlobII->getName() + GlobII->getLength());
|
||||
IdentifierInfo &II =
|
||||
AST.Idents.get(GlobII->getNameStart(),
|
||||
GlobII->getNameStart() + GlobII->getLength());
|
||||
LocalName = DeclarationName(&II);
|
||||
} else {
|
||||
Selector GlobSel = Name.getObjCSelector();
|
||||
|
@ -29,8 +29,9 @@ Selector GlobalSelector::getSelector(ASTContext &AST) const {
|
||||
for (unsigned i = 0, e = GlobSel.isUnarySelector() ? 1 : GlobSel.getNumArgs();
|
||||
i != e; ++i) {
|
||||
IdentifierInfo *GlobII = GlobSel.getIdentifierInfoForSlot(i);
|
||||
IdentifierInfo *II = &AST.Idents.get(GlobII->getName(),
|
||||
GlobII->getName() + GlobII->getLength());
|
||||
IdentifierInfo *II =
|
||||
&AST.Idents.get(GlobII->getNameStart(),
|
||||
GlobII->getNameStart() + GlobII->getLength());
|
||||
Ids.push_back(II);
|
||||
}
|
||||
|
||||
@ -57,8 +58,9 @@ GlobalSelector GlobalSelector::get(Selector Sel, Program &Prog) {
|
||||
for (unsigned i = 0, e = Sel.isUnarySelector() ? 1 : Sel.getNumArgs();
|
||||
i != e; ++i) {
|
||||
IdentifierInfo *II = Sel.getIdentifierInfoForSlot(i);
|
||||
IdentifierInfo *GlobII = &ProgImpl.getIdents().get(II->getName(),
|
||||
II->getName() + II->getLength());
|
||||
IdentifierInfo *GlobII =
|
||||
&ProgImpl.getIdents().get(II->getNameStart(),
|
||||
II->getNameStart() + II->getLength());
|
||||
Ids.push_back(GlobII);
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user