Update clang to r84949.

This commit is contained in:
Roman Divacky 2009-10-23 14:22:18 +00:00
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
206 changed files with 7807 additions and 3604 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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'">;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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";
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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;
};
}
//===----------------------------------------------------------------------===//

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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