Update Clang sources to r73879.

This commit is contained in:
Ed Schouten 2009-06-22 08:08:35 +00:00
parent 7ef7bab7e3
commit b897c8660c
199 changed files with 7100 additions and 3110 deletions

View File

@ -1,11 +1,14 @@
macro(add_clang_library name)
set(srcs ${ARGN})
if(MSVC_IDE OR XCODE)
file( GLOB_RECURSE headers *.h)
file( GLOB_RECURSE headers *.h *.td *.def)
set(srcs ${srcs} ${headers})
string( REGEX MATCHALL "/[^/]+" split_path ${CMAKE_CURRENT_SOURCE_DIR})
list( GET split_path -1 dir)
file( GLOB_RECURSE headers ../../include/clang${dir}/*.h)
file( GLOB_RECURSE headers
../../include/clang${dir}/*.h
../../include/clang${dir}/*.td
../../include/clang${dir}/*.def)
set(srcs ${srcs} ${headers})
endif(MSVC_IDE OR XCODE)
add_library( ${name} ${srcs} )
@ -29,7 +32,7 @@ endmacro(add_clang_library)
macro(add_clang_executable name)
set(srcs ${ARGN})
if(MSVC_IDE)
file( GLOB_RECURSE headers *.h)
file( GLOB_RECURSE headers *.h *.td *.def)
set(srcs ${srcs} ${headers})
endif(MSVC_IDE)
add_llvm_executable( ${name} ${srcs} )

View File

@ -71,6 +71,7 @@ class ASTContext {
llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes;
std::vector<VariableArrayType*> VariableArrayTypes;
std::vector<DependentSizedArrayType*> DependentSizedArrayTypes;
std::vector<DependentSizedExtVectorType*> DependentSizedExtVectorTypes;
llvm::FoldingSet<VectorType> VectorTypes;
llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes;
llvm::FoldingSet<FunctionProtoType> FunctionProtoTypes;
@ -79,7 +80,7 @@ class ASTContext {
llvm::FoldingSet<QualifiedNameType> QualifiedNameTypes;
llvm::FoldingSet<TypenameType> TypenameTypes;
llvm::FoldingSet<ObjCQualifiedInterfaceType> ObjCQualifiedInterfaceTypes;
llvm::FoldingSet<ObjCQualifiedIdType> ObjCQualifiedIdTypes;
llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
@ -103,7 +104,7 @@ class ASTContext {
/// This is initially null and set by Sema::LazilyCreateBuiltin when
/// a builtin that takes a valist is encountered.
QualType BuiltinVaListType;
/// ObjCIdType - a pseudo built-in typedef type (set by Sema).
QualType ObjCIdType;
const RecordType *IdStructType;
@ -125,6 +126,12 @@ class ASTContext {
RecordDecl *ObjCFastEnumerationStateTypeDecl;
/// \brief Keeps track of all declaration attributes.
///
/// Since so few decls have attrs, we keep them in a hash map instead of
/// wasting space in the Decl class.
llvm::DenseMap<const Decl*, Attr*> DeclAttrs;
TranslationUnitDecl *TUDecl;
/// SourceMgr - The associated SourceManager object.
@ -163,6 +170,12 @@ class ASTContext {
return FullSourceLoc(Loc,SourceMgr);
}
/// \brief Retrieve the attributes for the given declaration.
Attr*& getDeclAttrs(const Decl *D) { return DeclAttrs[D]; }
/// \brief Erase the attributes corresponding to the given declaration.
void eraseDeclAttrs(const Decl *D) { DeclAttrs.erase(D); }
TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; }
@ -277,6 +290,14 @@ class ASTContext {
/// type.
QualType getExtVectorType(QualType VectorType, unsigned NumElts);
/// getDependentSizedExtVectorType - Returns a non-unique reference to
/// the type for a dependently-sized vector of the specified element
/// type. FIXME: We will need these to be uniqued, or at least
/// comparable, at some point.
QualType getDependentSizedExtVectorType(QualType VectorType,
Expr *SizeExpr,
SourceLocation AttrLoc);
/// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
///
QualType getFunctionNoProtoType(QualType ResultTy);
@ -299,6 +320,7 @@ class ASTContext {
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl);
QualType getTemplateTypeParmType(unsigned Depth, unsigned Index,
bool ParameterPack,
IdentifierInfo *Name = 0);
QualType getTemplateSpecializationType(TemplateName T,
@ -315,6 +337,12 @@ class ASTContext {
const TemplateSpecializationType *TemplateId,
QualType Canon = QualType());
/// getObjCObjectPointerType - Return a ObjCObjectPointerType type for the
/// given interface decl and the conforming protocol list.
QualType getObjCObjectPointerType(ObjCInterfaceDecl *Decl,
ObjCProtocolDecl **ProtocolList = 0,
unsigned NumProtocols = 0);
/// getObjCQualifiedInterfaceType - Return a
/// ObjCQualifiedInterfaceType type for the given interface decl and
/// the conforming protocol list.
@ -416,7 +444,7 @@ class ASTContext {
/// getObjCEncodingTypeSize returns size of type for objective-c encoding
/// purpose.
int getObjCEncodingTypeSize(QualType t);
/// This setter/getter represents the ObjC 'id' type. It is setup lazily, by
/// Sema. id is always a (typedef for a) pointer type, a pointer to a struct.
QualType getObjCIdType() const { return ObjCIdType; }

View File

@ -146,8 +146,8 @@ class NamespaceDecl : public NamedDecl, public DeclContext {
}
void setOriginalNamespace(NamespaceDecl *ND) { OrigNamespace = ND; }
SourceRange getSourceRange() const {
return SourceRange(LBracLoc, RBracLoc);
virtual SourceRange getSourceRange() const {
return SourceRange(getLocation(), RBracLoc);
}
SourceLocation getLBracLoc() const { return LBracLoc; }
@ -259,6 +259,8 @@ class VarDecl : public ValueDecl {
StorageClass getStorageClass() const { return (StorageClass)SClass; }
void setStorageClass(StorageClass SC) { SClass = SC; }
virtual SourceRange getSourceRange() const;
SourceLocation getTypeSpecStartLoc() const { return TypeSpecStartLoc; }
void setTypeSpecStartLoc(SourceLocation SL) {
@ -644,6 +646,8 @@ class FunctionDecl : public ValueDecl, public DeclContext {
// Move to DeclGroup when it is implemented.
SourceLocation TypeSpecStartLoc;
SourceLocation EndRangeLoc;
/// \brief The template or declaration that this declaration
/// describes or was instantiated from, respectively.
@ -667,7 +671,7 @@ class FunctionDecl : public ValueDecl, public DeclContext {
SClass(S), IsInline(isInline), C99InlineDefinition(false),
IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false),
HasWrittenPrototype(true), IsDeleted(false), TypeSpecStartLoc(TSSL),
TemplateOrInstantiation() {}
EndRangeLoc(L), TemplateOrInstantiation() {}
virtual ~FunctionDecl() {}
virtual void Destroy(ASTContext& C);
@ -677,7 +681,15 @@ class FunctionDecl : public ValueDecl, public DeclContext {
DeclarationName N, QualType T,
StorageClass S = None, bool isInline = false,
bool hasWrittenPrototype = true,
SourceLocation TSStartLoc = SourceLocation());
SourceLocation TSStartLoc = SourceLocation());
virtual SourceRange getSourceRange() const {
return SourceRange(getLocation(), EndRangeLoc);
}
void setLocEnd(SourceLocation E) {
assert(getLocation() <= E && "Invalid end location");
EndRangeLoc = E;
}
SourceLocation getTypeSpecStartLoc() const { return TypeSpecStartLoc; }
void setTypeSpecStartLoc(SourceLocation TS) { TypeSpecStartLoc = TS; }
@ -706,7 +718,7 @@ class FunctionDecl : public ValueDecl, public DeclContext {
/// CodeGenModule.cpp uses it, and I don't know if this would break it.
bool isThisDeclarationADefinition() const { return Body; }
void setBody(Stmt *B) { Body = B; }
void setBody(Stmt *B);
void setLazyBody(uint64_t Offset) { Body = Offset; }
/// Whether this function is marked as virtual explicitly.
@ -832,12 +844,12 @@ class FunctionDecl : public ValueDecl, public DeclContext {
/// The gnu_inline attribute only introduces GNU inline semantics
/// when all of the inline declarations of the function are marked
/// gnu_inline.
bool hasActiveGNUInlineAttribute() const;
bool hasActiveGNUInlineAttribute(ASTContext &Context) const;
/// \brief Determines whether this function is a GNU "extern
/// inline", which is roughly the opposite of a C99 "extern inline"
/// function.
bool isExternGNUInline() const;
bool isExternGNUInline(ASTContext &Context) const;
/// isOverloadedOperator - Whether this function declaration
/// represents an C++ overloaded operator, e.g., "operator+".

View File

@ -156,9 +156,15 @@ class Decl {
/// the implementation rather than explicitly written by the user.
bool Implicit : 1;
/// \brief Whether this declaration was "used", meaning that a definition is
/// required.
bool Used : 1;
protected:
/// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
unsigned IdentifierNamespace : 8;
private:
#ifndef NDEBUG
void CheckAccessDeclContext() const;
#else
@ -174,7 +180,7 @@ class Decl {
Decl(Kind DK, DeclContext *DC, SourceLocation L)
: NextDeclInContext(0), DeclCtx(DC),
Loc(L), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false),
HasAttrs(false), Implicit(false), Used(false),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)), Access(AS_none) {
if (Decl::CollectingStats()) addDeclKind(DK);
}
@ -182,6 +188,14 @@ class Decl {
virtual ~Decl();
public:
/// \brief Source range that this declaration covers.
virtual SourceRange getSourceRange() const {
return SourceRange(getLocation(), getLocation());
}
SourceLocation getLocStart() const { return getSourceRange().getBegin(); }
SourceLocation getLocEnd() const { return getSourceRange().getEnd(); }
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
@ -211,23 +225,23 @@ class Decl {
}
bool hasAttrs() const { return HasAttrs; }
void addAttr(Attr *attr);
const Attr *getAttrs() const {
void addAttr(ASTContext &Context, Attr *attr);
const Attr *getAttrs(ASTContext &Context) const {
if (!HasAttrs) return 0; // common case, no attributes.
return getAttrsImpl(); // Uncommon case, out of line hash lookup.
return getAttrsImpl(Context); // Uncommon case, out of line hash lookup.
}
void swapAttrs(Decl *D);
void invalidateAttrs();
void swapAttrs(ASTContext &Context, Decl *D);
void invalidateAttrs(ASTContext &Context);
template<typename T> const T *getAttr() const {
for (const Attr *attr = getAttrs(); attr; attr = attr->getNext())
template<typename T> const T *getAttr(ASTContext &Context) const {
for (const Attr *attr = getAttrs(Context); attr; attr = attr->getNext())
if (const T *V = dyn_cast<T>(attr))
return V;
return 0;
}
template<typename T> bool hasAttr() const {
return getAttr<T>() != 0;
template<typename T> bool hasAttr(ASTContext &Context) const {
return getAttr<T>(Context) != 0;
}
/// setInvalidDecl - Indicates the Decl had a semantic error. This
@ -241,6 +255,11 @@ class Decl {
bool isImplicit() const { return Implicit; }
void setImplicit(bool I = true) { Implicit = I; }
/// \brief Whether this declaration was used, meaning that a definition
/// is required.
bool isUsed() const { return Used; }
void setUsed(bool U = true) { Used = U; }
unsigned getIdentifierNamespace() const {
return IdentifierNamespace;
}
@ -268,6 +287,10 @@ class Decl {
const DeclContext *getLexicalDeclContext() const {
return const_cast<Decl*>(this)->getLexicalDeclContext();
}
bool isOutOfLine() const {
return getLexicalDeclContext() != getDeclContext();
}
/// setDeclContext - Set both the semantic and lexical DeclContext
/// to DC.
@ -325,7 +348,7 @@ class Decl {
void dump(ASTContext &Context);
private:
const Attr *getAttrsImpl() const;
const Attr *getAttrsImpl(ASTContext &Context) const;
};

View File

@ -439,6 +439,9 @@ class CXXRecordDecl : public RecordDecl {
TemplateOrInstantiation = Template;
}
/// getDefaultConstructor - Returns the default constructor for this class
CXXConstructorDecl *getDefaultConstructor(ASTContext &Context);
/// getDestructor - Returns the destructor decl for this class.
const CXXDestructorDecl *getDestructor(ASTContext &Context);
@ -477,10 +480,6 @@ class CXXMethodDecl : public FunctionDecl {
bool isStatic() const { return getStorageClass() == Static; }
bool isInstance() const { return !isStatic(); }
bool isOutOfLineDefinition() const {
return getLexicalDeclContext() != getDeclContext();
}
bool isVirtual() const {
return isVirtualAsWritten() ||
(begin_overridden_methods() != end_overridden_methods());
@ -535,6 +534,7 @@ class CXXMethodDecl : public FunctionDecl {
/// public:
/// B(A& a) : A(a), f(3.14159) { }
/// };
/// @endcode
class CXXBaseOrMemberInitializer {
/// BaseOrMember - This points to the entity being initialized,
/// which is either a base class (a Type) or a non-static data
@ -641,6 +641,10 @@ class CXXConstructorDecl : public CXXMethodDecl {
/// explicitly defaulted (i.e., defined with " = default") will have
/// @c !Implicit && ImplicitlyDefined.
bool ImplicitlyDefined : 1;
/// ImplicitMustBeDefined - Implicit constructor was used to create an
/// object of its class type. It must be defined.
bool ImplicitMustBeDefined : 1;
/// FIXME: Add support for base and member initializers.
@ -648,7 +652,8 @@ class CXXConstructorDecl : public CXXMethodDecl {
DeclarationName N, QualType T,
bool isExplicit, bool isInline, bool isImplicitlyDeclared)
: CXXMethodDecl(CXXConstructor, RD, L, N, T, false, isInline),
Explicit(isExplicit), ImplicitlyDefined(false) {
Explicit(isExplicit), ImplicitlyDefined(false),
ImplicitMustBeDefined(false) {
setImplicit(isImplicitlyDeclared);
}
@ -679,6 +684,17 @@ class CXXConstructorDecl : public CXXMethodDecl {
ImplicitlyDefined = ID;
}
/// isImplicitMustBeDefined - Whether a definition must be synthesized for
/// the implicit constructor.
bool isImplicitMustBeDefined() const {
return isImplicit() && ImplicitMustBeDefined;
}
/// setImplicitMustBeDefined - constructor must be implicitly defined.
void setImplicitMustBeDefined() {
ImplicitMustBeDefined = true;
}
/// isDefaultConstructor - Whether this constructor is a default
/// constructor (C++ [class.ctor]p5), which can be used to
/// default-initialize a class of this type.
@ -1033,6 +1049,61 @@ class NamespaceAliasDecl : public NamedDecl {
}
static bool classof(const NamespaceAliasDecl *D) { return true; }
};
/// UsingDecl - Represents a C++ using-declaration. For example:
/// using someNameSpace::someIdentifier;
class UsingDecl : public NamedDecl {
/// \brief The source range that covers the nested-name-specifier
/// preceding the declaration name.
SourceRange NestedNameRange;
/// \brief The source location of the target declaration name.
SourceLocation TargetNameLocation;
/// \brief The source location of the "using" location itself.
SourceLocation UsingLocation;
/// \brief Target declaration.
NamedDecl* TargetDecl;
/// \brief Target declaration.
NestedNameSpecifier* TargetNestedNameDecl;
// Had 'typename' keyword.
bool IsTypeName;
UsingDecl(DeclContext *DC, SourceLocation L, SourceRange NNR,
SourceLocation TargetNL, SourceLocation UL, NamedDecl* Target,
NestedNameSpecifier* TargetNNS, bool IsTypeNameArg)
: NamedDecl(Decl::Using, DC, L, Target->getDeclName()),
NestedNameRange(NNR), TargetNameLocation(TargetNL),
UsingLocation(UL), TargetDecl(Target),
TargetNestedNameDecl(TargetNNS), IsTypeName(IsTypeNameArg) {
this->IdentifierNamespace = TargetDecl->getIdentifierNamespace();
}
public:
/// \brief Returns the source range that covers the nested-name-specifier
/// preceding the namespace name.
SourceRange getNestedNameRange() { return(NestedNameRange); }
/// \brief Returns the source location of the target declaration name.
SourceLocation getTargetNameLocation() { return(TargetNameLocation); }
/// \brief Returns the source location of the "using" location itself.
SourceLocation getUsingLocation() { return(UsingLocation); }
/// \brief getTargetDecl - Returns target specified by using-decl.
NamedDecl *getTargetDecl() { return(TargetDecl); }
/// \brief Get target nested name declaration.
NestedNameSpecifier* getTargetNestedNameDecl() { return(TargetNestedNameDecl); }
/// isTypeName - Return true if using decl had 'typename'.
bool isTypeName() const { return(IsTypeName); }
static UsingDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, SourceRange NNR, SourceLocation TargetNL,
SourceLocation UL, NamedDecl* Target,
NestedNameSpecifier* TargetNNS, bool IsTypeNameArg);
static bool classof(const Decl *D) {
return D->getKind() == Decl::Using;
}
static bool classof(const UsingDecl *D) { return true; }
};
/// StaticAssertDecl - Represents a C++0x static_assert declaration.
class StaticAssertDecl : public Decl {

View File

@ -108,6 +108,7 @@ ABSTRACT_DECL(Named, Decl)
DECL(FunctionTemplate, TemplateDecl)
DECL(ClassTemplate, TemplateDecl)
DECL(TemplateTemplateParm, TemplateDecl)
DECL(Using, NamedDecl)
DECL(ObjCMethod, NamedDecl)
DECL(ObjCContainer, NamedDecl)
DECL(ObjCCategory, ObjCContainerDecl)

View File

@ -18,6 +18,7 @@
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerUnion.h"
#include <limits>
namespace clang {
@ -404,6 +405,11 @@ class TemplateArgument {
char Value[sizeof(llvm::APSInt)];
void *Type;
} Integer;
struct {
TemplateArgument *Args;
unsigned NumArgs;
bool CopyArgs;
} Args;
};
/// \brief Location of the beginning of this template argument.
@ -413,7 +419,7 @@ class TemplateArgument {
/// \brief The type of template argument we're storing.
enum ArgKind {
Null = 0,
/// The template argument is a type. It's value is stored in the
/// The template argument is a type. Its value is stored in the
/// TypeOrValue field.
Type = 1,
/// The template argument is a declaration
@ -422,7 +428,11 @@ class TemplateArgument {
Integral = 3,
/// The template argument is a value- or type-dependent expression
/// stored in an Expr*.
Expression = 4
Expression = 4,
/// The template argument is actually a parameter pack. Arguments are stored
/// in the Args struct.
Pack = 5
} Kind;
/// \brief Construct an empty, invalid template argument.
@ -459,11 +469,20 @@ class TemplateArgument {
/// occur in a non-dependent, canonical template argument list.
TemplateArgument(Expr *E);
/// \brief Construct a template argument pack.
TemplateArgument(SourceLocation Loc, TemplateArgument *Args,
unsigned NumArgs, bool CopyArgs);
/// \brief Copy constructor for a template argument.
TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
if (Kind == Integral) {
new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
Integer.Type = Other.Integer.Type;
} else if (Kind == Pack) {
Args.NumArgs = Other.Args.NumArgs;
Args.Args = new TemplateArgument[Args.NumArgs];
for (unsigned I = 0; I != Args.NumArgs; ++I)
Args.Args[I] = Other.Args.Args[I];
}
else
TypeOrValue = Other.TypeOrValue;
@ -475,6 +494,10 @@ class TemplateArgument {
// safety.
using llvm::APSInt;
// FIXME: Handle Packs
assert(Kind != Pack && "FIXME: Handle packs");
assert(Other.Kind != Pack && "FIXME: Handle packs");
if (Kind == Other.Kind && Kind == Integral) {
// Copy integral values.
*this->getAsIntegral() = *Other.getAsIntegral();
@ -502,6 +525,8 @@ class TemplateArgument {
if (Kind == Integral)
getAsIntegral()->~APSInt();
else if (Kind == Pack && Args.CopyArgs)
delete[] Args.Args;
}
/// \brief Return the kind of stored template argument.
@ -586,34 +611,44 @@ class TemplateArgument {
// FIXME: We need a canonical representation of expressions.
ID.AddPointer(getAsExpr());
break;
case Pack:
ID.AddInteger(Args.NumArgs);
for (unsigned I = 0; I != Args.NumArgs; ++I)
Args.Args[I].Profile(ID);
}
}
};
/// \brief A helper class for making template argument lists.
class TemplateArgumentListBuilder {
/// Args - contains the template arguments.
llvm::SmallVector<TemplateArgument, 16> Args;
/// FlatArgs - contains the template arguments in flat form.
llvm::SmallVector<TemplateArgument, 16> FlatArgs;
llvm::SmallVector<unsigned, 32> Indices;
llvm::SmallVector<TemplateArgument, 16> StructuredArgs;
ASTContext &Context;
unsigned PackBeginIndex;
/// isAddingFromParameterPack - Returns whether we're adding arguments from
/// a parameter pack.
bool isAddingFromParameterPack() const { return Indices.size() % 2; }
bool isAddingFromParameterPack() const {
return PackBeginIndex != std::numeric_limits<unsigned>::max();
}
public:
TemplateArgumentListBuilder(ASTContext &Context) : Context(Context) { }
TemplateArgumentListBuilder(ASTContext &Context) : Context(Context),
PackBeginIndex(std::numeric_limits<unsigned>::max()) { }
size_t size() const {
size_t structuredSize() const {
assert(!isAddingFromParameterPack() &&
"Size is not valid when adding from a parameter pack");
return Indices.size() / 2;
return StructuredArgs.size();
}
size_t flatSize() const { return Args.size(); }
size_t flatSize() const { return FlatArgs.size(); }
void push_back(const TemplateArgument& Arg);
@ -623,8 +658,12 @@ class TemplateArgumentListBuilder {
/// EndParameterPack - Finish adding arguments from a parameter pack.
void EndParameterPack();
const TemplateArgument *getFlatArgumentList() const { return Args.data(); }
TemplateArgument *getFlatArgumentList() { return Args.data(); }
const TemplateArgument *getFlatArgumentList() const {
return FlatArgs.data();
}
TemplateArgument *getFlatArgumentList() {
return FlatArgs.data();
}
};
/// \brief A template argument list.
@ -657,13 +696,6 @@ class TemplateArgumentList {
}
/// \brief Retrieve the template argument at a given index.
TemplateArgument &get(unsigned Idx) {
assert(Idx < NumArguments && "Invalid template argument index");
return getFlatArgumentList()[Idx];
}
/// \brief Retrieve the template argument at a given index.
TemplateArgument &operator[](unsigned Idx) { return get(Idx); }
const TemplateArgument &operator[](unsigned Idx) const { return get(Idx); }
/// \brief Retrieve the number of template arguments in this
@ -675,9 +707,6 @@ class TemplateArgumentList {
unsigned flat_size() const { return NumArguments; }
/// \brief Retrieve the flattened template argument list.
TemplateArgument *getFlatArgumentList() {
return Arguments.getPointer();
}
const TemplateArgument *getFlatArgumentList() const {
return Arguments.getPointer();
}

View File

@ -124,7 +124,7 @@ class Expr : public Stmt {
/// with location to warn on and the source range[s] to report with the
/// warning.
bool isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
SourceRange &R2) const;
SourceRange &R2, ASTContext &Context) const;
/// isLvalue - C99 6.3.2.1: an lvalue is an expression with an object type or
/// incomplete type other than void. Nonarray expressions that can be lvalues:
@ -2463,10 +2463,13 @@ class BlockExpr : public Expr {
class BlockDeclRefExpr : public Expr {
ValueDecl *D;
SourceLocation Loc;
bool IsByRef;
bool IsByRef : 1;
bool ConstQualAdded : 1;
public:
BlockDeclRefExpr(ValueDecl *d, QualType t, SourceLocation l, bool ByRef) :
Expr(BlockDeclRefExprClass, t), D(d), Loc(l), IsByRef(ByRef) {}
BlockDeclRefExpr(ValueDecl *d, QualType t, SourceLocation l, bool ByRef,
bool constAdded = false) :
Expr(BlockDeclRefExprClass, t), D(d), Loc(l), IsByRef(ByRef),
ConstQualAdded(constAdded) {}
// \brief Build an empty reference to a declared variable in a
// block.
@ -2484,6 +2487,9 @@ class BlockDeclRefExpr : public Expr {
bool isByRef() const { return IsByRef; }
void setByRef(bool BR) { IsByRef = BR; }
bool isConstQualAdded() const { return ConstQualAdded; }
void setConstQualAdded(bool C) { ConstQualAdded = C; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == BlockDeclRefExprClass;

View File

@ -1023,17 +1023,16 @@ class CXXExprWithTemporaries : public Expr {
CXXTemporary **Temps;
unsigned NumTemps;
bool DestroyTemps;
bool ShouldDestroyTemps;
CXXExprWithTemporaries(Expr *SubExpr, CXXTemporary **Temps,
unsigned NumTemps, bool DestroyTemps);
unsigned NumTemps, bool ShouldDestroyTemps);
~CXXExprWithTemporaries();
public:
static CXXExprWithTemporaries *Create(ASTContext &C, Expr *SubExpr,
CXXTemporary **Temps,
unsigned NumTemps,
bool DestroyTems);
CXXTemporary **Temps, unsigned NumTemps,
bool ShouldDestroyTemporaries);
void Destroy(ASTContext &C);
unsigned getNumTemporaries() const { return NumTemps; }
@ -1046,6 +1045,8 @@ class CXXExprWithTemporaries : public Expr {
return Temps[i];
}
bool shouldDestroyTemporaries() const { return ShouldDestroyTemps; }
void removeLastTemporary() { NumTemps--; }
Expr *getSubExpr() { return cast<Expr>(SubExpr); }

View File

@ -138,20 +138,20 @@ class ObjCSelectorExpr : public Expr {
/// obj conformsToProtocol:@protocol(foo)]
/// The return type is "Protocol*".
class ObjCProtocolExpr : public Expr {
ObjCProtocolDecl *Protocol;
ObjCProtocolDecl *TheProtocol;
SourceLocation AtLoc, RParenLoc;
public:
ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol,
SourceLocation at, SourceLocation rp)
: Expr(ObjCProtocolExprClass, T), Protocol(protocol),
: Expr(ObjCProtocolExprClass, T), TheProtocol(protocol),
AtLoc(at), RParenLoc(rp) {}
explicit ObjCProtocolExpr(EmptyShell Empty)
: Expr(ObjCProtocolExprClass, Empty) {}
ObjCProtocolExpr *Clone(ASTContext &C) const;
ObjCProtocolDecl *getProtocol() const { return Protocol; }
void setProtocol(ObjCProtocolDecl *P) { Protocol = P; }
ObjCProtocolDecl *getProtocol() const { return TheProtocol; }
void setProtocol(ObjCProtocolDecl *P) { TheProtocol = P; }
SourceLocation getAtLoc() const { return AtLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }

View File

@ -393,6 +393,7 @@ class Type {
bool isComplexIntegerType() const; // GCC _Complex integer type.
bool isVectorType() const; // GCC vector type.
bool isExtVectorType() const; // Extended vector type.
bool isObjCObjectPointerType() const; // Pointer to *any* ObjC object.
bool isObjCInterfaceType() const; // NSString or NSString<foo>
bool isObjCQualifiedInterfaceType() const; // NSString<foo>
bool isObjCQualifiedIdType() const; // id<foo>
@ -439,9 +440,10 @@ class Type {
const ComplexType *getAsComplexType() const;
const ComplexType *getAsComplexIntegerType() const; // GCC complex int type.
const ExtVectorType *getAsExtVectorType() const; // Extended vector type.
const ObjCObjectPointerType *getAsObjCObjectPointerType() const;
const ObjCInterfaceType *getAsObjCInterfaceType() const;
const ObjCQualifiedInterfaceType *getAsObjCQualifiedInterfaceType() const;
const ObjCQualifiedIdType *getAsObjCQualifiedIdType() const;
const ObjCObjectPointerType *getAsObjCQualifiedIdType() const;
const TemplateTypeParmType *getAsTemplateTypeParmType() const;
const TemplateSpecializationType *
@ -992,6 +994,41 @@ class DependentSizedArrayType : public ArrayType {
}
};
/// DependentSizedExtVectorType - This type represent an extended vector type
/// where either the type or size is dependent. For example:
/// @code
/// template<typename T, int Size>
/// class vector {
/// typedef T __attribute__((ext_vector_type(Size))) type;
/// }
/// @endcode
class DependentSizedExtVectorType : public Type {
Expr *SizeExpr;
/// ElementType - The element type of the array.
QualType ElementType;
SourceLocation loc;
DependentSizedExtVectorType(QualType ElementType, QualType can,
Expr *SizeExpr, SourceLocation loc)
: Type (DependentSizedExtVector, can, true),
SizeExpr(SizeExpr), ElementType(ElementType), loc(loc) {}
friend class ASTContext;
virtual void Destroy(ASTContext& C);
public:
const Expr *getSizeExpr() const { return SizeExpr; }
QualType getElementType() const { return ElementType; }
SourceLocation getAttributeLoc() const { return loc; }
virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
static bool classof(const Type *T) {
return T->getTypeClass() == DependentSizedExtVector;
}
static bool classof(const DependentSizedExtVectorType *) { return true; }
};
/// VectorType - GCC generic vector type. This type is created using
/// __attribute__((vector_size(n)), where "n" specifies the vector size in
/// bytes. Since the constructor takes the number of vector elements, the
@ -1403,36 +1440,40 @@ class EnumType : public TagType {
};
class TemplateTypeParmType : public Type, public llvm::FoldingSetNode {
unsigned Depth : 16;
unsigned Depth : 15;
unsigned Index : 16;
unsigned ParameterPack : 1;
IdentifierInfo *Name;
TemplateTypeParmType(unsigned D, unsigned I, IdentifierInfo *N,
TemplateTypeParmType(unsigned D, unsigned I, bool PP, IdentifierInfo *N,
QualType Canon)
: Type(TemplateTypeParm, Canon, /*Dependent=*/true),
Depth(D), Index(I), Name(N) { }
Depth(D), Index(I), ParameterPack(PP), Name(N) { }
TemplateTypeParmType(unsigned D, unsigned I)
TemplateTypeParmType(unsigned D, unsigned I, bool PP)
: Type(TemplateTypeParm, QualType(this, 0), /*Dependent=*/true),
Depth(D), Index(I), Name(0) { }
Depth(D), Index(I), ParameterPack(PP), Name(0) { }
friend class ASTContext; // ASTContext creates these
public:
unsigned getDepth() const { return Depth; }
unsigned getIndex() const { return Index; }
bool isParameterPack() const { return ParameterPack; }
IdentifierInfo *getName() const { return Name; }
virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, Depth, Index, Name);
Profile(ID, Depth, Index, ParameterPack, Name);
}
static void Profile(llvm::FoldingSetNodeID &ID, unsigned Depth,
unsigned Index, IdentifierInfo *Name) {
unsigned Index, bool ParameterPack,
IdentifierInfo *Name) {
ID.AddInteger(Depth);
ID.AddInteger(Index);
ID.AddBoolean(ParameterPack);
ID.AddPointer(Name);
}
@ -1644,6 +1685,53 @@ class TypenameType : public Type, public llvm::FoldingSetNode {
static bool classof(const TypenameType *T) { return true; }
};
/// ObjCObjectPointerType - Used to represent 'id', 'Interface *', 'id <p>',
/// and 'Interface <p> *'.
///
/// Duplicate protocols are removed and protocol list is canonicalized to be in
/// alphabetical order.
class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
ObjCInterfaceDecl *Decl;
// List of protocols for this protocol conforming object type
// List is sorted on protocol name. No protocol is entered more than once.
llvm::SmallVector<ObjCProtocolDecl*, 8> Protocols;
ObjCObjectPointerType(ObjCInterfaceDecl *D,
ObjCProtocolDecl **Protos, unsigned NumP) :
Type(ObjCObjectPointer, QualType(), /*Dependent=*/false),
Decl(D), Protocols(Protos, Protos+NumP) { }
friend class ASTContext; // ASTContext creates these.
public:
ObjCInterfaceDecl *getDecl() const { return Decl; }
/// isObjCQualifiedIdType - true for "id <p>".
bool isObjCQualifiedIdType() const { return Decl == 0 && Protocols.size(); }
/// qual_iterator and friends: this provides access to the (potentially empty)
/// list of protocols qualifying this interface.
typedef llvm::SmallVector<ObjCProtocolDecl*, 8>::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; }
/// getNumProtocols - Return the number of qualifying protocols in this
/// interface type, or 0 if there are none.
unsigned getNumProtocols() const { return Protocols.size(); }
void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID,
const ObjCInterfaceDecl *Decl,
ObjCProtocolDecl **protocols, unsigned NumProtocols);
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
static bool classof(const Type *T) {
return T->getTypeClass() == ObjCObjectPointer;
}
static bool classof(const ObjCObjectPointerType *) { return true; }
};
/// ObjCInterfaceType - Interfaces are the core concept in Objective-C for
/// object oriented design. They basically correspond to C++ classes. There
/// are two kinds of interface types, normal interfaces like "NSString" and
@ -1742,44 +1830,6 @@ inline unsigned ObjCInterfaceType::getNumProtocols() const {
return 0;
}
/// ObjCQualifiedIdType - to represent id<protocol-list>.
///
/// Duplicate protocols are removed and protocol list is canonicalized to be in
/// alphabetical order.
class ObjCQualifiedIdType : public Type,
public llvm::FoldingSetNode {
// List of protocols for this protocol conforming 'id' type
// List is sorted on protocol name. No protocol is enterred more than once.
llvm::SmallVector<ObjCProtocolDecl*, 8> Protocols;
ObjCQualifiedIdType(ObjCProtocolDecl **Protos, unsigned NumP)
: Type(ObjCQualifiedId, QualType()/*these are always canonical*/,
/*Dependent=*/false),
Protocols(Protos, Protos+NumP) { }
friend class ASTContext; // ASTContext creates these.
public:
unsigned getNumProtocols() const {
return Protocols.size();
}
typedef llvm::SmallVector<ObjCProtocolDecl*, 8>::const_iterator qual_iterator;
qual_iterator qual_begin() const { return Protocols.begin(); }
qual_iterator qual_end() const { return Protocols.end(); }
virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID,
ObjCProtocolDecl **protocols, unsigned NumProtocols);
static bool classof(const Type *T) {
return T->getTypeClass() == ObjCQualifiedId;
}
static bool classof(const ObjCQualifiedIdType *) { return true; }
};
// Inline function definitions.
/// getUnqualifiedType - Return the type without any qualifiers.
@ -1926,6 +1976,9 @@ inline bool Type::isVectorType() const {
inline bool Type::isExtVectorType() const {
return isa<ExtVectorType>(CanonicalType.getUnqualifiedType());
}
inline bool Type::isObjCObjectPointerType() const {
return isa<ObjCObjectPointerType>(CanonicalType.getUnqualifiedType());
}
inline bool Type::isObjCInterfaceType() const {
return isa<ObjCInterfaceType>(CanonicalType.getUnqualifiedType());
}
@ -1933,7 +1986,10 @@ inline bool Type::isObjCQualifiedInterfaceType() const {
return isa<ObjCQualifiedInterfaceType>(CanonicalType.getUnqualifiedType());
}
inline bool Type::isObjCQualifiedIdType() const {
return isa<ObjCQualifiedIdType>(CanonicalType.getUnqualifiedType());
if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType()) {
return OPT->isObjCQualifiedIdType();
}
return false;
}
inline bool Type::isTemplateTypeParmType() const {
return isa<TemplateTypeParmType>(CanonicalType.getUnqualifiedType());

View File

@ -60,6 +60,7 @@ TYPE(ConstantArray, ArrayType)
TYPE(IncompleteArray, ArrayType)
TYPE(VariableArray, ArrayType)
DEPENDENT_TYPE(DependentSizedArray, ArrayType)
DEPENDENT_TYPE(DependentSizedExtVector, Type)
TYPE(Vector, Type)
TYPE(ExtVector, VectorType)
ABSTRACT_TYPE(Function, Type)
@ -76,8 +77,8 @@ TYPE(TemplateSpecialization, Type)
NON_CANONICAL_TYPE(QualifiedName, Type)
DEPENDENT_TYPE(Typename, Type)
TYPE(ObjCInterface, Type)
TYPE(ObjCObjectPointer, Type)
TYPE(ObjCQualifiedInterface, ObjCInterfaceType)
TYPE(ObjCQualifiedId, Type)
#undef DEPENDENT_TYPE
#undef NON_CANONICAL_TYPE

View File

@ -0,0 +1,50 @@
//===--- TypeVisitor.h - Visitor for Stmt subclasses ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the TypeVisitor interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_TYPEVISITOR_H
#define LLVM_CLANG_AST_TYPEVISITOR_H
#include "clang/AST/Type.h"
namespace clang {
#define DISPATCH(CLASS) \
return static_cast<ImplClass*>(this)->Visit ## CLASS(static_cast<CLASS*>(T))
template<typename ImplClass, typename RetTy=void>
class TypeVisitor {
public:
RetTy Visit(Type *T) {
// Top switch stmt: dispatch to VisitFooStmt for each FooStmt.
switch (T->getTypeClass()) {
default: assert(0 && "Unknown type class!");
#define ABSTRACT_TYPE(CLASS, PARENT)
#define TYPE(CLASS, PARENT) case Type::CLASS: DISPATCH(CLASS##Type);
#include "clang/AST/TypeNodes.def"
}
}
// If the implementation chooses not to implement a certain visit method, fall
// back on superclass.
#define TYPE(CLASS, PARENT) RetTy Visit##CLASS##Type(CLASS##Type *T) { DISPATCH(PARENT); }
#include "clang/AST/TypeNodes.def"
// Base case, ignore it. :)
RetTy VisitType(Type*) { return RetTy(); }
};
#undef DISPATCH
} // end namespace clang
#endif

View File

@ -30,26 +30,25 @@ class SVal;
class ConstraintManager {
public:
virtual ~ConstraintManager();
virtual const GRState* Assume(const GRState* St, SVal Cond,
bool Assumption, bool& isFeasible) = 0;
virtual const GRState *Assume(const GRState *state, SVal Cond,
bool Assumption) = 0;
virtual const GRState* AssumeInBound(const GRState* St, SVal Idx,
SVal UpperBound, bool Assumption,
bool& isFeasible) = 0;
virtual const GRState *AssumeInBound(const GRState *state, SVal Idx,
SVal UpperBound, bool Assumption) = 0;
virtual const llvm::APSInt* getSymVal(const GRState* St, SymbolRef sym)
const = 0;
virtual const llvm::APSInt* getSymVal(const GRState *state,
SymbolRef sym) const = 0;
virtual bool isEqual(const GRState* St, SymbolRef sym,
virtual bool isEqual(const GRState *state, SymbolRef sym,
const llvm::APSInt& V) const = 0;
virtual const GRState* RemoveDeadBindings(const GRState* St,
virtual const GRState *RemoveDeadBindings(const GRState *state,
SymbolReaper& SymReaper) = 0;
virtual void print(const GRState* St, std::ostream& Out,
virtual void print(const GRState *state, std::ostream& Out,
const char* nl, const char *sep) = 0;
virtual void EndPath(const GRState* St) {}
virtual void EndPath(const GRState *state) {}
/// canReasonAbout - Not all ConstraintManagers can accurately reason about
/// all SVal values. This method returns true if the ConstraintManager can

View File

@ -30,13 +30,12 @@ class EnvironmentManager;
class BasicValueFactory;
class LiveVariables;
class Environment : public llvm::FoldingSetNode {
class Environment {
private:
friend class EnvironmentManager;
// Type definitions.
typedef llvm::ImmutableMap<Stmt*,SVal> BindingsTy;
typedef llvm::ImmutableMap<const Stmt*,SVal> BindingsTy;
// Data.
BindingsTy SubExprBindings;
@ -55,25 +54,25 @@ class Environment : public llvm::FoldingSetNode {
beb_iterator beb_begin() const { return BlkExprBindings.begin(); }
beb_iterator beb_end() const { return BlkExprBindings.end(); }
SVal LookupSubExpr(Stmt* E) const {
SVal LookupSubExpr(const Stmt* E) const {
const SVal* X = SubExprBindings.lookup(cast<Expr>(E));
return X ? *X : UnknownVal();
}
SVal LookupBlkExpr(Stmt* E) const {
SVal LookupBlkExpr(const Stmt* E) const {
const SVal* X = BlkExprBindings.lookup(E);
return X ? *X : UnknownVal();
}
SVal LookupExpr(Stmt* E) const {
SVal LookupExpr(const Stmt* E) const {
const SVal* X = SubExprBindings.lookup(E);
if (X) return *X;
X = BlkExprBindings.lookup(E);
return X ? *X : UnknownVal();
}
SVal GetSVal(Stmt* Ex, BasicValueFactory& BasicVals) const;
SVal GetBlkExprSVal(Stmt* Ex, BasicValueFactory& BasicVals) const;
SVal GetSVal(const Stmt* Ex, BasicValueFactory& BasicVals) const;
SVal GetBlkExprSVal(const Stmt* Ex, BasicValueFactory& BasicVals) const;
/// Profile - Profile the contents of an Environment object for use
/// in a FoldingSet.
@ -109,19 +108,19 @@ class EnvironmentManager {
/// removed. This method only removes bindings for block-level expressions.
/// Using this method on a non-block level expression will return the
/// same environment object.
Environment RemoveBlkExpr(const Environment& Env, Stmt* E) {
Environment RemoveBlkExpr(const Environment& Env, const Stmt* E) {
return Environment(Env.SubExprBindings, F.Remove(Env.BlkExprBindings, E));
}
Environment RemoveSubExpr(const Environment& Env, Stmt* E) {
Environment RemoveSubExpr(const Environment& Env, const Stmt* E) {
return Environment(F.Remove(Env.SubExprBindings, E), Env.BlkExprBindings);
}
Environment AddBlkExpr(const Environment& Env, Stmt* E, SVal V) {
Environment AddBlkExpr(const Environment& Env, const Stmt *E, SVal V) {
return Environment(Env.SubExprBindings, F.Add(Env.BlkExprBindings, E, V));
}
Environment AddSubExpr(const Environment& Env, Stmt* E, SVal V) {
Environment AddSubExpr(const Environment& Env, const Stmt *E, SVal V) {
return Environment(F.Add(Env.SubExprBindings, E, V), Env.BlkExprBindings);
}
@ -136,7 +135,7 @@ class EnvironmentManager {
return Environment(F.GetEmptyMap(), F.GetEmptyMap());
}
Environment BindExpr(const Environment& Env, Stmt* E, SVal V,
Environment BindExpr(const Environment& Env, const Stmt* E, SVal V,
bool isBlkExpr, bool Invalidate);
Environment

View File

@ -477,67 +477,14 @@ class GRExprEngine {
const SymbolManager& getSymbolManager() const { return SymMgr; }
protected:
const GRState* GetState(NodeTy* N) {
return N == EntryNode ? CleanedState : N->getState();
}
public:
const GRState* BindExpr(const GRState* St, Expr* Ex, SVal V) {
return StateMgr.BindExpr(St, Ex, V);
}
const GRState* BindExpr(const GRState* St, const Expr* Ex, SVal V) {
return BindExpr(St, const_cast<Expr*>(Ex), V);
}
protected:
const GRState* BindBlkExpr(const GRState* St, Expr* Ex, SVal V) {
return StateMgr.BindExpr(St, Ex, V, true, false);
}
const GRState* BindLoc(const GRState* St, Loc LV, SVal V) {
return StateMgr.BindLoc(St, LV, V);
}
SVal GetSVal(const GRState* St, Stmt* Ex) {
return StateMgr.GetSVal(St, Ex);
}
SVal GetSVal(const GRState* St, const Stmt* Ex) {
return GetSVal(St, const_cast<Stmt*>(Ex));
}
SVal GetBlkExprSVal(const GRState* St, Stmt* Ex) {
return StateMgr.GetBlkExprSVal(St, Ex);
}
SVal GetSVal(const GRState* St, Loc LV, QualType T = QualType()) {
return StateMgr.GetSVal(St, LV, T);
}
public:
inline NonLoc MakeConstantVal(uint64_t X, Expr* Ex) {
return NonLoc::MakeVal(getBasicVals(), X, Ex->getType());
}
/// Assume - Create new state by assuming that a given expression
/// is true or false.
const GRState* Assume(const GRState* St, SVal Cond, bool Assumption,
bool& isFeasible) {
return StateMgr.Assume(St, Cond, Assumption, isFeasible);
}
const GRState* Assume(const GRState* St, Loc Cond, bool Assumption,
bool& isFeasible) {
return StateMgr.Assume(St, Cond, Assumption, isFeasible);
}
const GRState* AssumeInBound(const GRState* St, SVal Idx, SVal UpperBound,
bool Assumption, bool& isFeasible) {
return StateMgr.AssumeInBound(St, Idx, UpperBound, Assumption, isFeasible);
}
}
public:
NodeTy* MakeNode(NodeSet& Dst, Stmt* S, NodeTy* Pred, const GRState* St,

View File

@ -83,11 +83,9 @@ class GRStmtNodeBuilderRef {
Dst.Add(Pred);
}
}
GRStateRef getState() {
return GRStateRef(state, Eng.getStateManager());
}
const GRState *getState() { return state; }
GRStateManager& getStateManager() {
return Eng.getStateManager();
}

View File

@ -64,6 +64,8 @@ template <typename T> struct GRStateTrait {
//===----------------------------------------------------------------------===//
// GRState- An ImmutableMap type Stmt*/Decl*/Symbols to SVals.
//===----------------------------------------------------------------------===//
class GRStateManager;
/// GRState - This class encapsulates the actual data values for
/// for a "state" in our symbolic value tracking. It is intended to be
@ -81,7 +83,8 @@ class GRState : public llvm::FoldingSetNode {
void operator=(const GRState& R) const;
friend class GRStateManager;
GRStateManager *Mgr;
Environment Env;
Store St;
@ -92,8 +95,10 @@ class GRState : public llvm::FoldingSetNode {
public:
/// This ctor is used when creating the first GRState object.
GRState(const Environment& env, Store st, GenericDataMap gdm)
: Env(env),
GRState(GRStateManager *mgr, const Environment& env, Store st,
GenericDataMap gdm)
: Mgr(mgr),
Env(env),
St(st),
GDM(gdm) {}
@ -101,10 +106,14 @@ class GRState : public llvm::FoldingSetNode {
/// in FoldingSetNode will also get copied.
GRState(const GRState& RHS)
: llvm::FoldingSetNode(),
Mgr(RHS.Mgr),
Env(RHS.Env),
St(RHS.St),
GDM(RHS.GDM) {}
/// getStateManager - Return the GRStateManager associated with this state.
GRStateManager &getStateManager() const { return *Mgr; }
/// getEnvironment - Return the environment associated with this state.
/// The environment is the mapping from expressions to values.
const Environment& getEnvironment() const { return Env; }
@ -134,6 +143,10 @@ class GRState : public llvm::FoldingSetNode {
return Env.LookupExpr(E);
}
/// makeWithStore - Return a GRState with the same values as the current
/// state with the exception of using the specified Store.
const GRState *makeWithStore(Store store) const;
// Iterators.
typedef Environment::seb_iterator seb_iterator;
seb_iterator seb_begin() const { return Env.seb_begin(); }
@ -142,10 +155,119 @@ class GRState : public llvm::FoldingSetNode {
typedef Environment::beb_iterator beb_iterator;
beb_iterator beb_begin() const { return Env.beb_begin(); }
beb_iterator beb_end() const { return Env.beb_end(); }
BasicValueFactory &getBasicVals() const;
SymbolManager &getSymbolManager() const;
GRTransferFuncs &getTransferFuncs() const;
//==---------------------------------------------------------------------==//
// Constraints on values.
//==---------------------------------------------------------------------==//
//
// Each GRState records constraints on symbolic values. These constraints
// are managed using the ConstraintManager associated with a GRStateManager.
// As constraints gradually accrue on symbolic values, added constraints
// may conflict and indicate that a state is infeasible (as no real values
// could satisfy all the constraints). This is the principal mechanism
// for modeling path-sensitivity in GRExprEngine/GRState.
//
// Various "Assume" methods form the interface for adding constraints to
// symbolic values. A call to "Assume" indicates an assumption being placed
// on one or symbolic values. Assume methods take the following inputs:
//
// (1) A GRState object representing the current state.
//
// (2) The assumed constraint (which is specific to a given "Assume" method).
//
// (3) A binary value "Assumption" that indicates whether the constraint is
// assumed to be true or false.
//
// The output of "Assume" are two values:
//
// (a) "isFeasible" is set to true or false to indicate whether or not
// the assumption is feasible.
//
// (b) A new GRState object with the added constraints.
//
// FIXME: (a) should probably disappear since it is redundant with (b).
// (i.e., (b) could just be set to NULL).
//
const GRState *assume(SVal condition, bool assumption) const;
const GRState *assumeInBound(SVal idx, SVal upperBound,
bool assumption) const;
//==---------------------------------------------------------------------==//
// Binding and retrieving values to/from the environment and symbolic store.
//==---------------------------------------------------------------------==//
/// BindCompoundLiteral - Return the state that has the bindings currently
/// in 'state' plus the bindings for the CompoundLiteral. 'R' is the region
/// for the compound literal and 'BegInit' and 'EndInit' represent an
/// array of initializer values.
const GRState* bindCompoundLiteral(const CompoundLiteralExpr* CL,
SVal V) const;
const GRState *bindExpr(const Stmt* Ex, SVal V, bool isBlkExpr,
bool Invalidate) const;
const GRState *bindExpr(const Stmt* Ex, SVal V, bool Invalidate = true) const;
const GRState *bindBlkExpr(const Stmt *Ex, SVal V) const {
return bindExpr(Ex, V, true, false);
}
const GRState *bindLoc(Loc location, SVal V) const;
const GRState *bindLoc(SVal location, SVal V) const;
const GRState *unbindLoc(Loc LV) const;
/// Get the lvalue for a variable reference.
SVal getLValue(const VarDecl *decl) const;
/// Get the lvalue for a StringLiteral.
SVal getLValue(const StringLiteral *literal) const;
SVal getLValue(const CompoundLiteralExpr *literal) const;
/// Get the lvalue for an ivar reference.
SVal getLValue(const ObjCIvarDecl *decl, SVal base) const;
/// Get the lvalue for a field reference.
SVal getLValue(SVal Base, const FieldDecl *decl) const;
/// Get the lvalue for an array index.
SVal getLValue(QualType ElementType, SVal Base, SVal Idx) const;
const llvm::APSInt *getSymVal(SymbolRef sym) const;
SVal getSVal(const Stmt* Ex) const;
SVal getBlkExprSVal(const Stmt* Ex) const;
SVal getSValAsScalarOrLoc(const Stmt *Ex) const;
SVal getSVal(Loc LV, QualType T = QualType()) const;
SVal getSVal(const MemRegion* R) const;
SVal getSValAsScalarOrLoc(const MemRegion *R) const;
bool scanReachableSymbols(SVal val, SymbolVisitor& visitor) const;
template <typename CB> CB scanReachableSymbols(SVal val) const;
//==---------------------------------------------------------------------==//
// Accessing the Generic Data Map (GDM).
//==---------------------------------------------------------------------==//
// Trait based GDM dispatch.
void* const* FindGDM(void* K) const;
template<typename T>
const GRState *add(typename GRStateTrait<T>::key_type K) const;
template <typename T>
typename GRStateTrait<T>::data_type
get() const {
@ -159,6 +281,29 @@ class GRState : public llvm::FoldingSetNode {
return GRStateTrait<T>::Lookup(GRStateTrait<T>::MakeData(d), key);
}
template <typename T>
typename GRStateTrait<T>::context_type get_context() const;
template<typename T>
const GRState *remove(typename GRStateTrait<T>::key_type K) const;
template<typename T>
const GRState *remove(typename GRStateTrait<T>::key_type K,
typename GRStateTrait<T>::context_type C) const;
template<typename T>
const GRState *set(typename GRStateTrait<T>::data_type D) const;
template<typename T>
const GRState *set(typename GRStateTrait<T>::key_type K,
typename GRStateTrait<T>::value_type E) const;
template<typename T>
const GRState *set(typename GRStateTrait<T>::key_type K,
typename GRStateTrait<T>::value_type E,
typename GRStateTrait<T>::context_type C) const;
template<typename T>
bool contains(typename GRStateTrait<T>::key_type key) const {
void* const* d = FindGDM(GRStateTrait<T>::GDMIndex());
@ -172,11 +317,14 @@ class GRState : public llvm::FoldingSetNode {
virtual void Print(std::ostream& Out, const GRState* state,
const char* nl, const char* sep) = 0;
};
// Pretty-printing.
void print(std::ostream& Out, const char *nl = "\n",
const char *sep = "") const;
void print(std::ostream& Out, StoreManager& StoreMgr,
ConstraintManager& ConstraintMgr,
Printer **Beg = 0, Printer **End = 0,
const char* nl = "\n", const char *sep = "") const;
void printStdErr() const;
void printDOT(std::ostream& Out) const;
// Tags used for the Generic Data Map.
struct NullDerefTag {
@ -233,11 +381,9 @@ class GRStateSet {
// GRStateManager - Factory object for GRStates.
//===----------------------------------------------------------------------===//
class GRStateRef;
class GRStateManager {
friend class GRExprEngine;
friend class GRStateRef;
friend class GRState;
private:
EnvironmentManager EnvMgr;
@ -361,15 +507,6 @@ class GRStateManager {
// Store manager should return a persistent state.
return StoreMgr->BindDeclWithNoInit(St, VD);
}
/// BindCompoundLiteral - Return the state that has the bindings currently
/// in 'state' plus the bindings for the CompoundLiteral. 'R' is the region
/// for the compound literal and 'BegInit' and 'EndInit' represent an
/// array of initializer values.
const GRState* BindCompoundLiteral(const GRState* St,
const CompoundLiteralExpr* CL, SVal V) {
return StoreMgr->BindCompoundLiteral(St, CL, V);
}
const GRState* RemoveDeadBindings(const GRState* St, Stmt* Loc,
SymbolReaper& SymReaper);
@ -391,38 +528,10 @@ class GRStateManager {
return StoreMgr->getSelfRegion(state->getStore());
}
// Get the lvalue for a variable reference.
SVal GetLValue(const GRState* St, const VarDecl* D) {
return StoreMgr->getLValueVar(St, D);
}
private:
// Get the lvalue for a StringLiteral.
SVal GetLValue(const GRState* St, const StringLiteral* E) {
return StoreMgr->getLValueString(St, E);
}
SVal GetLValue(const GRState* St, const CompoundLiteralExpr* CL) {
return StoreMgr->getLValueCompoundLiteral(St, CL);
}
// Get the lvalue for an ivar reference.
SVal GetLValue(const GRState* St, const ObjCIvarDecl* D, SVal Base) {
return StoreMgr->getLValueIvar(St, D, Base);
}
// Get the lvalue for a field reference.
SVal GetLValue(const GRState* St, SVal Base, const FieldDecl* D) {
return StoreMgr->getLValueField(St, Base, D);
}
// Get the lvalue for an array index.
SVal GetLValue(const GRState* St, QualType ElementType, SVal Base, SVal Idx) {
return StoreMgr->getLValueElement(St, ElementType, Base, Idx);
}
// Methods that query & manipulate the Environment.
SVal GetSVal(const GRState* St, Stmt* Ex) {
// Methods that query & manipulate the Environment.
SVal GetSVal(const GRState* St, const Stmt* Ex) {
return St->getEnvironment().GetSVal(Ex, getBasicVals());
}
@ -435,19 +544,12 @@ class GRStateManager {
return UnknownVal();
}
SVal GetSVal(const GRState* St, const Stmt* Ex) {
return St->getEnvironment().GetSVal(const_cast<Stmt*>(Ex), getBasicVals());
}
SVal GetBlkExprSVal(const GRState* St, Stmt* Ex) {
SVal GetBlkExprSVal(const GRState* St, const Stmt* Ex) {
return St->getEnvironment().GetBlkExprSVal(Ex, getBasicVals());
}
const GRState* BindExpr(const GRState* St, Stmt* Ex, SVal V,
const GRState* BindExpr(const GRState* St, const Stmt* Ex, SVal V,
bool isBlkExpr, bool Invalidate) {
const Environment& OldEnv = St->getEnvironment();
@ -461,7 +563,7 @@ class GRStateManager {
return getPersistentState(NewSt);
}
const GRState* BindExpr(const GRState* St, Stmt* Ex, SVal V,
const GRState* BindExpr(const GRState* St, const Stmt* Ex, SVal V,
bool Invalidate = true) {
bool isBlkExpr = false;
@ -478,6 +580,8 @@ class GRStateManager {
return BindExpr(St, Ex, V, isBlkExpr, Invalidate);
}
public:
SVal ArrayToPointer(Loc Array) {
return StoreMgr->ArrayToPointer(Array);
}
@ -533,13 +637,9 @@ class GRStateManager {
const GRState* getPersistentState(GRState& Impl);
// MakeStateWithStore - get a persistent state with the new store.
const GRState* MakeStateWithStore(const GRState* St, Store store);
bool isEqual(const GRState* state, Expr* Ex, const llvm::APSInt& V);
bool isEqual(const GRState* state, Expr* Ex, uint64_t);
//==---------------------------------------------------------------------==//
// Generic Data Map methods.
//==---------------------------------------------------------------------==//
@ -605,56 +705,6 @@ class GRStateManager {
return GRStateTrait<T>::MakeContext(p);
}
//==---------------------------------------------------------------------==//
// Constraints on values.
//==---------------------------------------------------------------------==//
//
// Each GRState records constraints on symbolic values. These constraints
// are managed using the ConstraintManager associated with a GRStateManager.
// As constraints gradually accrue on symbolic values, added constraints
// may conflict and indicate that a state is infeasible (as no real values
// could satisfy all the constraints). This is the principal mechanism
// for modeling path-sensitivity in GRExprEngine/GRState.
//
// Various "Assume" methods form the interface for adding constraints to
// symbolic values. A call to "Assume" indicates an assumption being placed
// on one or symbolic values. Assume methods take the following inputs:
//
// (1) A GRState object representing the current state.
//
// (2) The assumed constraint (which is specific to a given "Assume" method).
//
// (3) A binary value "Assumption" that indicates whether the constraint is
// assumed to be true or false.
//
// The output of "Assume" are two values:
//
// (a) "isFeasible" is set to true or false to indicate whether or not
// the assumption is feasible.
//
// (b) A new GRState object with the added constraints.
//
// FIXME: (a) should probably disappear since it is redundant with (b).
// (i.e., (b) could just be set to NULL).
//
const GRState* Assume(const GRState* St, SVal Cond, bool Assumption,
bool& isFeasible) {
const GRState *state =
ConstraintMgr->Assume(St, Cond, Assumption, isFeasible);
assert(!isFeasible || state);
return isFeasible ? state : NULL;
}
const GRState* AssumeInBound(const GRState* St, SVal Idx, SVal UpperBound,
bool Assumption, bool& isFeasible) {
const GRState *state =
ConstraintMgr->AssumeInBound(St, Idx, UpperBound, Assumption,
isFeasible);
assert(!isFeasible || state);
return isFeasible ? state : NULL;
}
const llvm::APSInt* getSymVal(const GRState* St, SymbolRef sym) {
return ConstraintMgr->getSymVal(St, sym);
@ -663,157 +713,158 @@ class GRStateManager {
void EndPath(const GRState* St) {
ConstraintMgr->EndPath(St);
}
bool scanReachableSymbols(SVal val, const GRState* state,
SymbolVisitor& visitor);
};
//===----------------------------------------------------------------------===//
// GRStateRef - A "fat" reference to GRState that also bundles GRStateManager.
// Out-of-line method definitions for GRState.
//===----------------------------------------------------------------------===//
class GRStateRef {
const GRState* St;
GRStateManager* Mgr;
public:
GRStateRef(const GRState* st, GRStateManager& mgr) : St(st), Mgr(&mgr) {}
const GRState* getState() const { return St; }
operator const GRState*() const { return St; }
GRStateManager& getManager() const { return *Mgr; }
SVal GetSVal(Expr* Ex) {
return Mgr->GetSVal(St, Ex);
}
SVal GetBlkExprSVal(Expr* Ex) {
return Mgr->GetBlkExprSVal(St, Ex);
}
SVal GetSValAsScalarOrLoc(const Expr *Ex) {
return Mgr->GetSValAsScalarOrLoc(St, Ex);
}
inline const GRState *GRState::assume(SVal Cond, bool Assumption) const {
return Mgr->ConstraintMgr->Assume(this, Cond, Assumption);
}
SVal GetSVal(Loc LV, QualType T = QualType()) {
return Mgr->GetSVal(St, LV, T);
}
SVal GetSVal(const MemRegion* R) {
return Mgr->GetSVal(St, R);
}
SVal GetSValAsScalarOrLoc(const MemRegion *R) {
return Mgr->GetSValAsScalarOrLoc(St, R);
}
inline const GRState *GRState::assumeInBound(SVal Idx, SVal UpperBound,
bool Assumption) const {
return Mgr->ConstraintMgr->AssumeInBound(this, Idx, UpperBound, Assumption);
}
GRStateRef BindExpr(Stmt* Ex, SVal V, bool isBlkExpr, bool Invalidate) {
return GRStateRef(Mgr->BindExpr(St, Ex, V, isBlkExpr, Invalidate), *Mgr);
}
inline const GRState *GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL,
SVal V) const {
return Mgr->StoreMgr->BindCompoundLiteral(this, CL, V);
}
GRStateRef BindExpr(Stmt* Ex, SVal V, bool Invalidate = true) {
return GRStateRef(Mgr->BindExpr(St, Ex, V, Invalidate), *Mgr);
}
GRStateRef BindDecl(const VarDecl* VD, SVal InitVal) {
return GRStateRef(Mgr->BindDecl(St, VD, InitVal), *Mgr);
}
GRStateRef BindLoc(Loc LV, SVal V) {
return GRStateRef(Mgr->BindLoc(St, LV, V), *Mgr);
}
GRStateRef BindLoc(SVal LV, SVal V) {
if (!isa<Loc>(LV)) return *this;
return BindLoc(cast<Loc>(LV), V);
}
GRStateRef Unbind(Loc LV) {
return GRStateRef(Mgr->Unbind(St, LV), *Mgr);
}
// Trait based GDM dispatch.
template<typename T>
typename GRStateTrait<T>::data_type get() const {
return St->get<T>();
}
template<typename T>
typename GRStateTrait<T>::lookup_type
get(typename GRStateTrait<T>::key_type key) const {
return St->get<T>(key);
}
template<typename T>
GRStateRef set(typename GRStateTrait<T>::data_type D) {
return GRStateRef(Mgr->set<T>(St, D), *Mgr);
}
inline const GRState *GRState::bindExpr(const Stmt* Ex, SVal V, bool isBlkExpr,
bool Invalidate) const {
return Mgr->BindExpr(this, Ex, V, isBlkExpr, Invalidate);
}
template <typename T>
typename GRStateTrait<T>::context_type get_context() {
return Mgr->get_context<T>();
}
inline const GRState *GRState::bindExpr(const Stmt* Ex, SVal V,
bool Invalidate) const {
return Mgr->BindExpr(this, Ex, V, Invalidate);
}
inline const GRState *GRState::bindLoc(Loc LV, SVal V) const {
return Mgr->BindLoc(this, LV, V);
}
template<typename T>
GRStateRef set(typename GRStateTrait<T>::key_type K,
typename GRStateTrait<T>::value_type E,
typename GRStateTrait<T>::context_type C) {
return GRStateRef(Mgr->set<T>(St, K, E, C), *Mgr);
}
inline const GRState *GRState::bindLoc(SVal LV, SVal V) const {
return !isa<Loc>(LV) ? this : bindLoc(cast<Loc>(LV), V);
}
template<typename T>
GRStateRef set(typename GRStateTrait<T>::key_type K,
typename GRStateTrait<T>::value_type E) {
return GRStateRef(Mgr->set<T>(St, K, E, get_context<T>()), *Mgr);
}
inline SVal GRState::getLValue(const VarDecl* VD) const {
return Mgr->StoreMgr->getLValueVar(this, VD);
}
template<typename T>
GRStateRef add(typename GRStateTrait<T>::key_type K) {
return GRStateRef(Mgr->add<T>(St, K, get_context<T>()), *Mgr);
}
inline SVal GRState::getLValue(const StringLiteral *literal) const {
return Mgr->StoreMgr->getLValueString(this, literal);
}
inline SVal GRState::getLValue(const CompoundLiteralExpr *literal) const {
return Mgr->StoreMgr->getLValueCompoundLiteral(this, literal);
}
template<typename T>
GRStateRef remove(typename GRStateTrait<T>::key_type K,
typename GRStateTrait<T>::context_type C) {
return GRStateRef(Mgr->remove<T>(St, K, C), *Mgr);
}
inline SVal GRState::getLValue(const ObjCIvarDecl *D, SVal Base) const {
return Mgr->StoreMgr->getLValueIvar(this, D, Base);
}
template<typename T>
GRStateRef remove(typename GRStateTrait<T>::key_type K) {
return GRStateRef(Mgr->remove<T>(St, K, get_context<T>()), *Mgr);
}
inline SVal GRState::getLValue(SVal Base, const FieldDecl* D) const {
return Mgr->StoreMgr->getLValueField(this, Base, D);
}
template<typename T>
bool contains(typename GRStateTrait<T>::key_type key) const {
return St->contains<T>(key);
}
inline SVal GRState::getLValue(QualType ElementType, SVal Base, SVal Idx) const{
return Mgr->StoreMgr->getLValueElement(this, ElementType, Base, Idx);
}
// Lvalue methods.
SVal GetLValue(const VarDecl* VD) {
return Mgr->GetLValue(St, VD);
}
GRStateRef Assume(SVal Cond, bool Assumption, bool& isFeasible) {
return GRStateRef(Mgr->Assume(St, Cond, Assumption, isFeasible), *Mgr);
}
inline const llvm::APSInt *GRState::getSymVal(SymbolRef sym) const {
return Mgr->getSymVal(this, sym);
}
template <typename CB>
CB scanReachableSymbols(SVal val) {
CB cb(*this);
Mgr->scanReachableSymbols(val, St, cb);
return cb;
}
inline SVal GRState::getSVal(const Stmt* Ex) const {
return Mgr->GetSVal(this, Ex);
}
inline SVal GRState::getBlkExprSVal(const Stmt* Ex) const {
return Mgr->GetBlkExprSVal(this, Ex);
}
inline SVal GRState::getSValAsScalarOrLoc(const Stmt *Ex) const {
return Mgr->GetSValAsScalarOrLoc(this, Ex);
}
inline SVal GRState::getSVal(Loc LV, QualType T) const {
return Mgr->GetSVal(this, LV, T);
}
inline SVal GRState::getSVal(const MemRegion* R) const {
return Mgr->GetSVal(this, R);
}
inline SVal GRState::getSValAsScalarOrLoc(const MemRegion *R) const {
return Mgr->GetSValAsScalarOrLoc(this, R);
}
SymbolManager& getSymbolManager() { return Mgr->getSymbolManager(); }
BasicValueFactory& getBasicVals() { return Mgr->getBasicVals(); }
inline BasicValueFactory &GRState::getBasicVals() const {
return Mgr->getBasicVals();
}
inline SymbolManager &GRState::getSymbolManager() const {
return Mgr->getSymbolManager();
}
// Pretty-printing.
void print(std::ostream& Out, const char* nl = "\n",
const char *sep = "") const;
inline GRTransferFuncs &GRState::getTransferFuncs() const {
return Mgr->getTransferFuncs();
}
template<typename T>
const GRState *GRState::add(typename GRStateTrait<T>::key_type K) const {
return Mgr->add<T>(this, K, get_context<T>());
}
void printStdErr() const;
template <typename T>
typename GRStateTrait<T>::context_type GRState::get_context() const {
return Mgr->get_context<T>();
}
void printDOT(std::ostream& Out) const;
};
template<typename T>
const GRState *GRState::remove(typename GRStateTrait<T>::key_type K) const {
return Mgr->remove<T>(this, K, get_context<T>());
}
template<typename T>
const GRState *GRState::remove(typename GRStateTrait<T>::key_type K,
typename GRStateTrait<T>::context_type C) const {
return Mgr->remove<T>(this, K, C);
}
template<typename T>
const GRState *GRState::set(typename GRStateTrait<T>::data_type D) const {
return Mgr->set<T>(this, D);
}
template<typename T>
const GRState *GRState::set(typename GRStateTrait<T>::key_type K,
typename GRStateTrait<T>::value_type E) const {
return Mgr->set<T>(this, K, E, get_context<T>());
}
template<typename T>
const GRState *GRState::set(typename GRStateTrait<T>::key_type K,
typename GRStateTrait<T>::value_type E,
typename GRStateTrait<T>::context_type C) const {
return Mgr->set<T>(this, K, E, C);
}
template <typename CB>
CB GRState::scanReachableSymbols(SVal val) const {
CB cb(this);
scanReachableSymbols(val, cb);
return cb;
}
inline const GRState *GRState::unbindLoc(Loc LV) const {
return Mgr->Unbind(this, LV);
}
} // end clang namespace

View File

@ -110,11 +110,9 @@ class GRTransferFuncs {
// Assumptions.
virtual const GRState* EvalAssume(GRStateManager& VMgr,
const GRState* St,
SVal Cond, bool Assumption,
bool& isFeasible) {
return St;
virtual const GRState* EvalAssume(const GRState *state,
SVal Cond, bool Assumption) {
return state;
}
};

View File

@ -620,7 +620,7 @@ class MemRegionManager {
/// getElementRegion - Retrieve the memory region associated with the
/// associated element type, index, and super region.
ElementRegion* getElementRegion(QualType elementType, SVal Idx,
const MemRegion* superRegion);
const MemRegion* superRegion,ASTContext &Ctx);
/// getFieldRegion - Retrieve or create the memory region associated with
/// a specified FieldDecl. 'superRegion' corresponds to the containing

View File

@ -181,7 +181,7 @@ class NonLoc : public SVal {
static NonLoc MakeVal(BasicValueFactory& BasicVals, uint64_t X, QualType T);
static NonLoc MakeVal(BasicValueFactory& BasicVals, IntegerLiteral* I);
static NonLoc MakeVal(BasicValueFactory& BasicVals, const IntegerLiteral *I);
static NonLoc MakeVal(BasicValueFactory& BasicVals, const llvm::APInt& I,
bool isUnsigned);
@ -212,7 +212,7 @@ class Loc : public SVal {
static Loc MakeVal(const MemRegion* R);
static Loc MakeVal(AddrLabelExpr* E);
static Loc MakeVal(const AddrLabelExpr* E);
static Loc MakeNull(BasicValueFactory &BasicVals);

View File

@ -14,12 +14,12 @@
#ifndef LLVM_CLANG_ANALYSIS_STORE_H
#define LLVM_CLANG_ANALYSIS_STORE_H
#include "clang/Analysis/PathSensitive/SVals.h"
#include "clang/Analysis/PathSensitive/MemRegion.h"
#include "clang/Analysis/PathSensitive/SVals.h"
#include "clang/Analysis/PathSensitive/ValueManager.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
#include <iosfwd>
@ -45,10 +45,10 @@ class StoreManager {
StoreManager(GRStateManager &stateMgr);
protected:
virtual const GRState* AddRegionView(const GRState* St,
const MemRegion* View,
const MemRegion* Base) {
return St;
virtual const GRState *AddRegionView(const GRState *state,
const MemRegion *view,
const MemRegion *base) {
return state;
}
public:
@ -61,7 +61,7 @@ class StoreManager {
/// expected type of the returned value. This is used if the value is
/// lazily computed.
/// \return The value bound to the location \c loc.
virtual SVal Retrieve(const GRState* state, Loc loc,
virtual SVal Retrieve(const GRState *state, Loc loc,
QualType T = QualType()) = 0;
/// Return a state with the specified value bound to the given location.
@ -71,7 +71,7 @@ class StoreManager {
/// \return A pointer to a GRState object that contains the same bindings as
/// \c state with the addition of having the value specified by \c val bound
/// to the location given for \c loc.
virtual const GRState* Bind(const GRState* state, Loc loc, SVal val) = 0;
virtual const GRState *Bind(const GRState *state, Loc loc, SVal val) = 0;
virtual Store Remove(Store St, Loc L) = 0;
@ -79,9 +79,9 @@ class StoreManager {
/// in 'store' plus the bindings for the CompoundLiteral. 'R' is the region
/// for the compound literal and 'BegInit' and 'EndInit' represent an
/// array of initializer values.
virtual const GRState* BindCompoundLiteral(const GRState* St,
const CompoundLiteralExpr* CL,
SVal V) = 0;
virtual const GRState *BindCompoundLiteral(const GRState *state,
const CompoundLiteralExpr* cl,
SVal v) = 0;
/// getInitialStore - Returns the initial "empty" store representing the
/// value bindings upon entry to an analyzed function.
@ -94,51 +94,52 @@ class StoreManager {
/// getSubRegionMap - Returns an opaque map object that clients can query
/// to get the subregions of a given MemRegion object. It is the
// caller's responsibility to 'delete' the returned map.
virtual SubRegionMap* getSubRegionMap(const GRState *state) = 0;
virtual SubRegionMap *getSubRegionMap(const GRState *state) = 0;
virtual SVal getLValueVar(const GRState* St, const VarDecl* VD) = 0;
virtual SVal getLValueVar(const GRState *state, const VarDecl *vd) = 0;
virtual SVal getLValueString(const GRState* St, const StringLiteral* S) = 0;
virtual SVal getLValueString(const GRState *state,
const StringLiteral* sl) = 0;
virtual SVal getLValueCompoundLiteral(const GRState* St,
const CompoundLiteralExpr* CL) = 0;
virtual SVal getLValueCompoundLiteral(const GRState *state,
const CompoundLiteralExpr* cl) = 0;
virtual SVal getLValueIvar(const GRState* St, const ObjCIvarDecl* D,
SVal Base) = 0;
virtual SVal getLValueIvar(const GRState *state, const ObjCIvarDecl* decl,
SVal base) = 0;
virtual SVal getLValueField(const GRState* St, SVal Base,
virtual SVal getLValueField(const GRState *state, SVal base,
const FieldDecl* D) = 0;
virtual SVal getLValueElement(const GRState* St, QualType elementType,
SVal Base, SVal Offset) = 0;
virtual SVal getLValueElement(const GRState *state, QualType elementType,
SVal base, SVal offset) = 0;
virtual SVal getSizeInElements(const GRState* St, const MemRegion* R) {
// FIXME: Make out-of-line.
virtual SVal getSizeInElements(const GRState *state, const MemRegion *region){
return UnknownVal();
}
/// ArrayToPointer - Used by GRExprEngine::VistCast to handle implicit
/// conversions between arrays and pointers.
virtual SVal ArrayToPointer(Loc Array) = 0;
class CastResult {
const GRState* State;
const MemRegion* R;
const GRState *state;
const MemRegion *region;
public:
const GRState* getState() const { return State; }
const MemRegion* getRegion() const { return R; }
CastResult(const GRState* s, const MemRegion* r = 0) : State(s), R(r) {}
const GRState *getState() const { return state; }
const MemRegion* getRegion() const { return region; }
CastResult(const GRState *s, const MemRegion* r = 0) : state(s), region(r){}
};
/// CastRegion - Used by GRExprEngine::VisitCast to handle casts from
/// a MemRegion* to a specific location type. 'R' is the region being
/// casted and 'CastToTy' the result type of the cast.
virtual CastResult CastRegion(const GRState* state, const MemRegion* R,
virtual CastResult CastRegion(const GRState *state, const MemRegion *region,
QualType CastToTy);
/// EvalBinOp - Perform pointer arithmetic.
virtual SVal EvalBinOp(const GRState *state,
BinaryOperator::Opcode Op, Loc L, NonLoc R) {
virtual SVal EvalBinOp(const GRState *state, BinaryOperator::Opcode Op,
Loc lhs, NonLoc rhs) {
return UnknownVal();
}
@ -147,24 +148,27 @@ class StoreManager {
/// method returns NULL.
virtual const MemRegion* getSelfRegion(Store store) = 0;
virtual Store
RemoveDeadBindings(const GRState* state, Stmt* Loc, SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) = 0;
virtual Store RemoveDeadBindings(const GRState *state,
Stmt* Loc, SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) = 0;
virtual const GRState* BindDecl(const GRState* St, const VarDecl* VD,
SVal InitVal) = 0;
virtual const GRState *BindDecl(const GRState *state, const VarDecl *vd,
SVal initVal) = 0;
virtual const GRState* BindDeclWithNoInit(const GRState* St,
const VarDecl* VD) = 0;
virtual const GRState *BindDeclWithNoInit(const GRState *state,
const VarDecl *vd) = 0;
virtual const GRState* setExtent(const GRState* St,
const MemRegion* R, SVal Extent) {
return St;
// FIXME: Make out-of-line.
virtual const GRState *setExtent(const GRState *state,
const MemRegion *region, SVal extent) {
return state;
}
virtual const GRState* setDefaultValue(const GRState* St,
const MemRegion* R, SVal V) {
return St;
// FIXME: Make out-of-line.
virtual const GRState *setDefaultValue(const GRState *state,
const MemRegion *region,
SVal val) {
return state;
}
virtual void print(Store store, std::ostream& Out,
@ -174,13 +178,14 @@ class StoreManager {
public:
virtual ~BindingsHandler();
virtual bool HandleBinding(StoreManager& SMgr, Store store,
const MemRegion* R, SVal val) = 0;
const MemRegion *region, SVal val) = 0;
};
/// iterBindings - Iterate over the bindings in the Store.
virtual void iterBindings(Store store, BindingsHandler& f) = 0;
};
// FIXME: Do we still need this?
/// SubRegionMap - An abstract interface that represents a queryable map
/// between MemRegion objects and their subregions.
class SubRegionMap {
@ -193,12 +198,14 @@ class SubRegionMap {
virtual bool Visit(const MemRegion* Parent, const MemRegion* SubRegion) = 0;
};
virtual bool iterSubRegions(const MemRegion* R, Visitor& V) const = 0;
virtual bool iterSubRegions(const MemRegion *region, Visitor& V) const = 0;
};
StoreManager* CreateBasicStoreManager(GRStateManager& StMgr);
StoreManager* CreateRegionStoreManager(GRStateManager& StMgr);
// FIXME: Do we need to pass GRStateManager anymore?
StoreManager *CreateBasicStoreManager(GRStateManager& StMgr);
StoreManager *CreateRegionStoreManager(GRStateManager& StMgr);
StoreManager *CreateFieldsOnlyRegionStoreManager(GRStateManager& StMgr);
} // end clang namespace
#endif

View File

@ -83,19 +83,25 @@ typedef const SymbolData* SymbolRef;
class SymbolRegionValue : public SymbolData {
const MemRegion *R;
// We may cast the region to another type, so the expected type of the symbol
// may be different from the region's original type.
QualType T;
public:
SymbolRegionValue(SymbolID sym, const MemRegion *r)
: SymbolData(RegionValueKind, sym), R(r) {}
SymbolRegionValue(SymbolID sym, const MemRegion *r, QualType t = QualType())
: SymbolData(RegionValueKind, sym), R(r), T(t) {}
const MemRegion* getRegion() const { return R; }
static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion* R) {
static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion* R,
QualType T) {
profile.AddInteger((unsigned) RegionValueKind);
profile.AddPointer(R);
T.Profile(profile);
}
virtual void Profile(llvm::FoldingSetNodeID& profile) {
Profile(profile, R);
Profile(profile, R, T);
}
QualType getType(ASTContext&) const;
@ -240,7 +246,8 @@ class SymbolManager {
static bool canSymbolicate(QualType T);
/// Make a unique symbol for MemRegion R according to its kind.
const SymbolRegionValue* getRegionValueSymbol(const MemRegion* R);
const SymbolRegionValue* getRegionValueSymbol(const MemRegion* R,
QualType T = QualType());
const SymbolConjured* getConjuredSymbol(const Stmt* E, QualType T,
unsigned VisitCount,
const void* SymbolTag = 0);

View File

@ -81,7 +81,7 @@ class ValueManager {
SVal makeZeroArrayIndex();
/// GetRegionValueSymbolVal - make a unique symbol for value of R.
SVal getRegionValueSymbolVal(const MemRegion* R);
SVal getRegionValueSymbolVal(const MemRegion* R, QualType T = QualType());
SVal getConjuredSymbolVal(const Expr *E, unsigned Count);
SVal getConjuredSymbolVal(const Expr* E, QualType T, unsigned Count);

View File

@ -53,13 +53,12 @@ class Context {
const Info *TSRecords;
unsigned NumTSRecords;
public:
Context() : TSRecords(0), NumTSRecords(0) {}
Context(const TargetInfo &Target);
/// InitializeBuiltins - Mark the identifiers for all the builtins with their
/// appropriate builtin ID # and mark any non-portable builtin identifiers as
/// such.
void InitializeBuiltins(IdentifierTable &Table, const TargetInfo &Target,
bool NoBuiltins = false);
void InitializeBuiltins(IdentifierTable &Table, bool NoBuiltins = false);
/// \brief Popular the vector with the names of all of the builtins.
void GetBuiltinNames(llvm::SmallVectorImpl<const char *> &Names,

View File

@ -30,6 +30,7 @@ def : DiagGroup<"conversion">;
def : DiagGroup<"declaration-after-statement">;
def : DiagGroup<"disabled-optimization">;
def : DiagGroup<"discard-qual">;
def : DiagGroup<"div-by-zero">;
def EmptyBody : DiagGroup<"empty-body">;
def ExtraTokens : DiagGroup<"extra-tokens">;
@ -40,6 +41,7 @@ def FourByteMultiChar : DiagGroup<"four-char-constants">;
def : DiagGroup<"init-self">;
def : DiagGroup<"inline">;
def : DiagGroup<"int-to-pointer-cast">;
def : DiagGroup<"invalid-pch">;
def : DiagGroup<"missing-braces">;
def : DiagGroup<"missing-declarations">;
def : DiagGroup<"missing-format-attribute">;
@ -91,6 +93,8 @@ def UnusedLabel : DiagGroup<"unused-label">;
def UnusedParameter : DiagGroup<"unused-parameter">;
def UnusedValue : DiagGroup<"unused-value">;
def UnusedVariable : DiagGroup<"unused-variable">;
def ReadOnlySetterAttrs : DiagGroup<"readonly-setter-attrs">;
def UndeclaredSelector : DiagGroup<"undeclared-selector">;
def : DiagGroup<"variadic-macros">;
def VectorConversions : DiagGroup<"vector-conversions">; // clang specific
def VolatileRegisterVar : DiagGroup<"volatile-register-var">;
@ -112,7 +116,9 @@ def Format2 : DiagGroup<"format=2",
[FormatNonLiteral, FormatSecurity, FormatY2K]>;
def Extra : DiagGroup<"extra">;
def Extra : DiagGroup<"extra", [
UnusedParameter
]>;
def Most : DiagGroup<"most", [
Comment,
@ -127,7 +133,9 @@ def Most : DiagGroup<"most", [
UnusedValue,
UnusedVariable,
VectorConversions,
VolatileRegisterVar
VolatileRegisterVar,
ReadOnlySetterAttrs,
UndeclaredSelector
]>;
// -Wall is -Wmost -Wparentheses

View File

@ -108,6 +108,8 @@ def err_expected_semi_after_method_proto : Error<
"expected ';' after method prototype">;
def err_expected_semi_after_namespace_name : Error<
"expected ';' after namespace name">;
def err_unexpected_namespace_attributes_alias : Error<
"attributes can not be specified on namespace alias">;
def err_expected_semi_after_attribute_list : Error<
"expected ';' after attribute list">;
def err_expected_semi_after_static_assert : Error<
@ -152,6 +154,10 @@ def err_unknown_typename : Error<
"unknown type name %0">;
def err_use_of_tag_name_without_tag : Error<
"use of tagged type %0 without '%1' tag">;
def err_expected_ident_in_using : Error<
"expected an identifier in using directive">;
def err_unexpected_template_spec_in_using : Error<
"use of template specialization in using directive not allowed">;
/// Objective-C parser diagnostics
@ -212,6 +218,8 @@ def ext_ellipsis_exception_spec : Extension<
"exception specification of '...' is a Microsoft extension">;
def err_expected_catch : Error<"expected catch">;
def err_expected_lbrace_or_comma : Error<"expected '{' or ','">;
def err_using_namespace_in_class : Error<
"'using namespace' in class not allowed">;
// C++ derived classes
def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
@ -287,5 +295,5 @@ def warn_pragma_unused_expected_var : Warning<
"expected '#pragma unused' argument to be a variable name">;
def warn_pragma_unused_expected_punc : Warning<
"expected ')' or ',' in '#pragma unused'">;
} // end of Parser diagnostics

View File

@ -72,6 +72,8 @@ def ext_anon_param_requires_type_specifier : Extension<
def err_bad_variable_name : Error<
"'%0' cannot be the name of a variable or data member">;
def err_parameter_name_omitted : Error<"parameter name omitted">;
def warn_unused_parameter : Warning<"unused parameter %0">,
InGroup<UnusedParameter>, DefaultIgnore;
def warn_decl_in_param_list : Warning<
"declaration of %0 will not be visible outside of this function">;
@ -90,6 +92,10 @@ def warn_use_out_of_scope_declaration : Warning<
"use of out-of-scope declaration of %0">;
def err_inline_non_function : Error<
"'inline' can only appear on functions">;
def err_using_requires_qualname : Error<
"using declaration requires a qualified name">;
def err_using_typename_non_type : Error<
"'typename' keyword used on a non-type">;
def err_invalid_thread : Error<
"'__thread' is only allowed on variable declarations">;
@ -240,7 +246,9 @@ def error_duplicate_ivar_use : Error<
def error_property_implemented : Error<"property %0 is already implemented">;
def warn_objc_property_attr_mutually_exclusive : Warning<
"property attributes '%0' and '%1' are mutually exclusive">,
InGroup<DiagGroup<"readonly-setter-attrs">>, DefaultIgnore;
InGroup<ReadOnlySetterAttrs>, DefaultIgnore;
def warn_undeclared_selector : Warning<
"undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore;
// C++ declarations
def err_static_assert_expression_is_not_constant : Error<
@ -571,6 +579,14 @@ def err_param_default_argument_references_this : Error<
def err_param_default_argument_nonfunc : Error<
"default arguments can only be specified for parameters in a function "
"declaration">;
def err_defining_default_ctor : Error<
"cannot define the default constructor for %0, because %select{base class|member}1 "
"%2 does not have any implicit default constructor">;
def note_previous_class_decl : Note<
"%0 declared here">;
def err_unintialized_member : Error<
"cannot define the implicit default constructor for %0, because "
"%select{reference|const}1 member %2 cannot be default-initialized">;
def err_use_of_default_argument_to_function_declared_later : Error<
"use of default argument to function %0 that is declared later in class %1">;

View File

@ -145,6 +145,10 @@ inline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) {
return LHS.getRawEncoding() < RHS.getRawEncoding();
}
inline bool operator<=(const SourceLocation &LHS, const SourceLocation &RHS) {
return LHS.getRawEncoding() <= RHS.getRawEncoding();
}
/// SourceRange - a trival tuple used to represent a source range.
class SourceRange {
SourceLocation B;

View File

@ -68,7 +68,12 @@ namespace SrcMgr {
/// NumLines - The number of lines in this ContentCache. This is only valid
/// if SourceLineCache is non-null.
unsigned NumLines;
/// FirstFID - First FileID that was created for this ContentCache.
/// Represents the first source inclusion of the file associated with this
/// ContentCache.
mutable FileID FirstFID;
/// getBuffer - Returns the memory buffer for the associated content.
const llvm::MemoryBuffer *getBuffer() const;
@ -624,6 +629,13 @@ class SourceManager {
//===--------------------------------------------------------------------===//
// Other miscellaneous methods.
//===--------------------------------------------------------------------===//
/// \brief Get the source location for the given file:line:col triplet.
///
/// If the source file is included multiple times, the source location will
/// be based upon the first inclusion.
SourceLocation getLocation(const FileEntry *SourceFile,
unsigned Line, unsigned Col) const;
// Iterators over FileInfos.
typedef llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>

View File

@ -565,9 +565,9 @@ OPTION("-print-file-name=", print_file_name_EQ, Joined, INVALID, INVALID, "", 0,
OPTION("-print-ivar-layout", print_ivar_layout, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-print-libgcc-file-name", print_libgcc_file_name, Flag, INVALID, INVALID, "", 0,
"Print the library path for \"libgcc.a\"", 0)
OPTION("-print-multi-directory", print_multi_directory, Flag, INVALID, INVALID, "u", 0, 0, 0)
OPTION("-print-multi-lib", print_multi_lib, Flag, INVALID, INVALID, "u", 0, 0, 0)
OPTION("-print-multi-os-directory", print_multi_os_directory, Flag, INVALID, INVALID, "u", 0, 0, 0)
OPTION("-print-multi-directory", print_multi_directory, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-print-multi-lib", print_multi_lib, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-print-multi-os-directory", print_multi_os_directory, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-print-prog-name=", print_prog_name_EQ, Joined, INVALID, INVALID, "", 0,
"Print the full program path of <name>", "<name>")
OPTION("-print-search-dirs", print_search_dirs, Flag, INVALID, INVALID, "", 0,

View File

@ -50,6 +50,8 @@ class ToolChain {
// Accessors
const HostInfo &getHost() const { return Host; }
const llvm::Triple &getTriple() const { return Triple; }
std::string getArchName() const { return Triple.getArchName(); }
std::string getPlatform() const { return Triple.getVendorName(); }
std::string getOS() const { return Triple.getOSName(); }

View File

@ -0,0 +1,75 @@
//===--- ASTUnit.h - ASTUnit utility ----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// ASTUnit utility class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_FRONTEND_ASTUNIT_H
#define LLVM_CLANG_FRONTEND_ASTUNIT_H
#include "llvm/ADT/OwningPtr.h"
#include <string>
namespace clang {
class FileManager;
class FileEntry;
class SourceManager;
class DiagnosticClient;
class Diagnostic;
class HeaderSearch;
class TargetInfo;
class Preprocessor;
class ASTContext;
class Decl;
/// \brief Utility class for loading a ASTContext from a PCH file.
///
class ASTUnit {
llvm::OwningPtr<SourceManager> SourceMgr;
llvm::OwningPtr<DiagnosticClient> DiagClient;
llvm::OwningPtr<Diagnostic> Diags;
llvm::OwningPtr<HeaderSearch> HeaderInfo;
llvm::OwningPtr<TargetInfo> Target;
llvm::OwningPtr<Preprocessor> PP;
llvm::OwningPtr<ASTContext> Ctx;
ASTUnit(const ASTUnit&); // do not implement
ASTUnit &operator=(const ASTUnit &); // do not implement
ASTUnit();
public:
~ASTUnit();
const SourceManager &getSourceManager() const { return *SourceMgr.get(); }
SourceManager &getSourceManager() { return *SourceMgr.get(); }
const Preprocessor &getPreprocessor() const { return *PP.get(); }
Preprocessor &getPreprocessor() { return *PP.get(); }
const ASTContext &getASTContext() const { return *Ctx.get(); }
ASTContext &getASTContext() { return *Ctx.get(); }
/// \brief Create a ASTUnit from a PCH file.
///
/// \param Filename PCH filename
///
/// \param FileMgr The FileManager to use
///
/// \param ErrMsg Error message to report if the PCH file could not be loaded
///
/// \returns the initialized ASTUnit or NULL if the PCH failed to load
static ASTUnit *LoadFromPCHFile(const std::string &Filename,
FileManager &FileMgr,
std::string *ErrMsg = 0);
};
} // namespace clang
#endif

View File

@ -0,0 +1,113 @@
//===-- DeclContextXML.def - Metadata about Context XML nodes ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the XML context info database as written in the
// <ReferenceSection>/<Contexts> sub-nodes of the XML document. Type nodes
// are referred by "context" reference attributes throughout the document.
// A context node never contains sub-nodes.
// The semantics of the attributes and enums are mostly self-documenting
// by looking at the appropriate internally used functions and values.
// The following macros are used:
//
// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete
// context of class CLASS where CLASS is a class name used internally by clang.
// After a NODE_XML the definition of all (optional) attributes of that context
// node and possible sub-nodes follows.
//
// END_NODE_XML - Closes the attribute definition of the current node.
//
// ID_ATTRIBUTE_XML - Context nodes have an "id" attribute containing a
// string, which value uniquely identify that statement. Other nodes may refer
// by "context" attributes to this value.
//
// TYPE_ATTRIBUTE_XML( FN ) - Context nodes may refer to the ids of type
// nodes by a "type" attribute, if they create a type during declaration.
// For instance 'struct S;' creates both a context 'S::' and a type 'S'.
// Contexts and types always have different ids, however declarations and
// contexts may share the same ids. FN is internally used by clang.
//
// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally
// used by clang. A boolean attribute have the values "0" or "1".
//
// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value
// is an enumeration defined with ENUM_XML macros immediately following after
// that macro. An optional attribute is ommited, if the particular enum is the
// empty string. FN is internally used by clang.
//
// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is
// internally used by clang.
//
// END_ENUM_XML - Closes the enumeration definition of the current attribute.
//
//===----------------------------------------------------------------------===//
#ifndef TYPE_ATTRIBUTE_XML
# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type")
#endif
#ifndef CONTEXT_ATTRIBUTE_XML
# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context")
#endif
NODE_XML(TranslationUnitDecl, "TranslationUnit")
ID_ATTRIBUTE_XML
END_NODE_XML
NODE_XML(FunctionDecl, "Function")
ID_ATTRIBUTE_XML
ATTRIBUTE_XML(getDeclContext(), "context")
ATTRIBUTE_XML(getNameAsString(), "name")
TYPE_ATTRIBUTE_XML(getType()->getAsFunctionType())
END_NODE_XML
NODE_XML(NamespaceDecl, "Namespace")
ID_ATTRIBUTE_XML
ATTRIBUTE_XML(getDeclContext(), "context")
ATTRIBUTE_XML(getNameAsString(), "name")
END_NODE_XML
NODE_XML(RecordDecl, "Record")
ID_ATTRIBUTE_XML
ATTRIBUTE_XML(getDeclContext(), "context")
ATTRIBUTE_XML(getNameAsString(), "name")
TYPE_ATTRIBUTE_XML(getTypeForDecl())
END_NODE_XML
NODE_XML(EnumDecl, "Enum")
ID_ATTRIBUTE_XML
ATTRIBUTE_XML(getDeclContext(), "context")
ATTRIBUTE_XML(getNameAsString(), "name")
TYPE_ATTRIBUTE_XML(getTypeForDecl())
END_NODE_XML
NODE_XML(LinkageSpecDecl, "LinkageSpec")
ID_ATTRIBUTE_XML
ATTRIBUTE_XML(getDeclContext(), "context")
ATTRIBUTE_ENUM_OPT_XML(getLanguage(), "lang")
ENUM_XML(LinkageSpecDecl::lang_c, "C")
ENUM_XML(LinkageSpecDecl::lang_cxx, "CXX")
END_ENUM_XML
END_NODE_XML
//===----------------------------------------------------------------------===//
#undef NODE_XML
#undef ID_ATTRIBUTE_XML
#undef TYPE_ATTRIBUTE_XML
#undef ATTRIBUTE_XML
#undef ATTRIBUTE_SPECIAL_XML
#undef ATTRIBUTE_OPT_XML
#undef ATTRIBUTE_ENUM_XML
#undef ATTRIBUTE_ENUM_OPT_XML
#undef ATTRIBUTE_FILE_LOCATION_XML
#undef ENUM_XML
#undef END_ENUM_XML
#undef END_NODE_XML
#undef SUB_NODE_XML
#undef SUB_NODE_SEQUENCE_XML
#undef SUB_NODE_OPT_XML

View File

@ -0,0 +1,250 @@
//===-- DeclXML.def - Metadata about Decl XML nodes ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the XML statement database structure as written in
// <TranslationUnit> sub-nodes of the XML document.
// The semantics of the attributes and enums are mostly self-documenting
// by looking at the appropriate internally used functions and values.
// The following macros are used:
//
// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete
// statement of class CLASS where CLASS is a class name used internally by clang.
// After a NODE_XML the definition of all (optional) attributes of that statement
// node and possible sub-nodes follows.
//
// END_NODE_XML - Closes the attribute definition of the current node.
//
// ID_ATTRIBUTE_XML - Some statement nodes have an "id" attribute containing a
// string, which value uniquely identify that statement. Other nodes may refer
// by reference attributes to this value (currently used only for Label).
//
// TYPE_ATTRIBUTE_XML( FN ) - Type nodes refer to the result type id of an
// expression by a "type" attribute. FN is internally used by clang.
//
// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally
// used by clang. A boolean attribute have the values "0" or "1".
//
// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves
// a special handling. See the appropriate documentations.
//
// ATTRIBUTE_FILE_LOCATION_XML - A bunch of attributes denoting the location of
// a statement in the source file(s).
//
// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME.
// Optional attributes are omitted for boolean types, if the value is false,
// for integral types, if the value is null and for strings,
// if the value is the empty string. FN is internally used by clang.
//
// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value
// is an enumeration defined with ENUM_XML macros immediately following after
// that macro. An optional attribute is ommited, if the particular enum is the
// empty string. FN is internally used by clang.
//
// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is
// internally used by clang.
//
// END_ENUM_XML - Closes the enumeration definition of the current attribute.
//
// SUB_NODE_XML( CLASS ) - A mandatory sub-node of class CLASS or its sub-classes.
//
// SUB_NODE_OPT_XML( CLASS ) - An optional sub-node of class CLASS or its sub-classes.
//
// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or
// its sub-classes.
//
//===----------------------------------------------------------------------===//
#ifndef ATTRIBUTE_FILE_LOCATION_XML
# define ATTRIBUTE_FILE_LOCATION_XML \
ATTRIBUTE_XML(getFilename(), "file") \
ATTRIBUTE_XML(getLine(), "line") \
ATTRIBUTE_XML(getColumn(), "col") \
ATTRIBUTE_OPT_XML(getFilename(), "endfile") \
ATTRIBUTE_OPT_XML(getLine(), "endline") \
ATTRIBUTE_OPT_XML(getColumn(), "endcol")
#endif
#ifndef TYPE_ATTRIBUTE_XML
# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type")
#endif
#ifndef CONTEXT_ATTRIBUTE_XML
# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context")
#endif
//NODE_XML(TranslationUnitDecl, "TranslationUnit")
// SUB_NODE_SEQUENCE_XML(Decl)
//END_NODE_XML
NODE_XML(Decl, "FIXME_Decl")
ATTRIBUTE_FILE_LOCATION_XML
END_NODE_XML
NODE_XML(FunctionDecl, "Function")
ID_ATTRIBUTE_XML
ATTRIBUTE_FILE_LOCATION_XML
ATTRIBUTE_XML(getDeclContext(), "context")
ATTRIBUTE_XML(getNameAsString(), "name")
TYPE_ATTRIBUTE_XML(getType()->getAsFunctionType()->getResultType())
ATTRIBUTE_XML(getType()->getAsFunctionType(), "function_type")
ATTRIBUTE_ENUM_OPT_XML(getStorageClass(), "storage_class")
ENUM_XML(FunctionDecl::None, "")
ENUM_XML(FunctionDecl::Extern, "extern")
ENUM_XML(FunctionDecl::Static, "static")
ENUM_XML(FunctionDecl::PrivateExtern, "__private_extern__")
END_ENUM_XML
ATTRIBUTE_OPT_XML(isInline(), "inline")
//ATTRIBUTE_OPT_XML(isVariadic(), "variadic") // in the type reference
ATTRIBUTE_XML(getNumParams(), "num_args")
SUB_NODE_SEQUENCE_XML(ParmVarDecl)
//SUB_NODE_OPT_XML("Body")
END_NODE_XML
NODE_XML(CXXMethodDecl, "CXXMethodDecl")
ID_ATTRIBUTE_XML
ATTRIBUTE_FILE_LOCATION_XML
ATTRIBUTE_XML(getDeclContext(), "context")
ATTRIBUTE_XML(getNameAsString(), "name")
TYPE_ATTRIBUTE_XML(getType()->getAsFunctionType()->getResultType())
ATTRIBUTE_XML(getType()->getAsFunctionType(), "function_type")
ATTRIBUTE_OPT_XML(isInline(), "inline")
ATTRIBUTE_OPT_XML(isStatic(), "static")
ATTRIBUTE_OPT_XML(isVirtual(), "virtual")
ATTRIBUTE_XML(getNumParams(), "num_args")
SUB_NODE_SEQUENCE_XML(ParmVarDecl)
//SUB_NODE_OPT_XML("Body")
END_NODE_XML
//NODE_XML("Body")
// SUB_NODE_XML(Stmt)
//END_NODE_XML
NODE_XML(NamespaceDecl, "Namespace")
ID_ATTRIBUTE_XML
ATTRIBUTE_FILE_LOCATION_XML
ATTRIBUTE_XML(getDeclContext(), "context")
ATTRIBUTE_XML(getNameAsString(), "name")
END_NODE_XML
NODE_XML(UsingDirectiveDecl, "UsingDirective")
ATTRIBUTE_FILE_LOCATION_XML
ATTRIBUTE_XML(getDeclContext(), "context")
ATTRIBUTE_XML(getNameAsString(), "name")
ATTRIBUTE_XML(getNominatedNamespace(), "ref")
END_NODE_XML
NODE_XML(NamespaceAliasDecl, "NamespaceAlias")
ATTRIBUTE_FILE_LOCATION_XML
ATTRIBUTE_XML(getDeclContext(), "context")
ATTRIBUTE_XML(getNameAsString(), "name")
ATTRIBUTE_XML(getNamespace(), "ref")
END_NODE_XML
NODE_XML(RecordDecl, "Record")
ID_ATTRIBUTE_XML
ATTRIBUTE_FILE_LOCATION_XML
ATTRIBUTE_XML(getDeclContext(), "context")
ATTRIBUTE_XML(getNameAsString(), "name")
ATTRIBUTE_OPT_XML(isDefinition() == false, "forward")
ATTRIBUTE_XML(getTypeForDecl(), "type") // refers to the type this decl creates
SUB_NODE_SEQUENCE_XML(FieldDecl)
END_NODE_XML
NODE_XML(EnumDecl, "Enum")
ID_ATTRIBUTE_XML
ATTRIBUTE_FILE_LOCATION_XML
ATTRIBUTE_XML(getDeclContext(), "context")
ATTRIBUTE_XML(getNameAsString(), "name")
ATTRIBUTE_OPT_XML(isDefinition() == false, "forward")
ATTRIBUTE_SPECIAL_XML(getIntegerType(), "type") // is NULL in pure declarations thus deserves special handling
SUB_NODE_SEQUENCE_XML(EnumConstantDecl) // only present in definition
END_NODE_XML
NODE_XML(EnumConstantDecl, "EnumConstant")
ID_ATTRIBUTE_XML
ATTRIBUTE_FILE_LOCATION_XML
ATTRIBUTE_XML(getDeclContext(), "context")
ATTRIBUTE_XML(getNameAsString(), "name")
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_XML(getInitVal().toString(10, true), "value") // integer
SUB_NODE_OPT_XML(Expr) // init expr of this constant
END_NODE_XML
NODE_XML(FieldDecl, "Field")
ID_ATTRIBUTE_XML
ATTRIBUTE_FILE_LOCATION_XML
ATTRIBUTE_XML(getDeclContext(), "context")
ATTRIBUTE_XML(getNameAsString(), "name")
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_OPT_XML(isMutable(), "mutable")
ATTRIBUTE_OPT_XML(isBitField(), "bitfield")
SUB_NODE_OPT_XML(Expr) // init expr of a bit field
END_NODE_XML
NODE_XML(TypedefDecl, "Typedef")
ID_ATTRIBUTE_XML
ATTRIBUTE_FILE_LOCATION_XML
ATTRIBUTE_XML(getDeclContext(), "context")
ATTRIBUTE_XML(getNameAsString(), "name")
TYPE_ATTRIBUTE_XML(getUnderlyingType())
END_NODE_XML
NODE_XML(VarDecl, "Var")
ID_ATTRIBUTE_XML
ATTRIBUTE_FILE_LOCATION_XML
ATTRIBUTE_XML(getDeclContext(), "context")
ATTRIBUTE_XML(getNameAsString(), "name")
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_ENUM_OPT_XML(getStorageClass(), "storage_class")
ENUM_XML(VarDecl::None, "")
ENUM_XML(VarDecl::Auto, "auto")
ENUM_XML(VarDecl::Register, "register")
ENUM_XML(VarDecl::Extern, "extern")
ENUM_XML(VarDecl::Static, "static")
ENUM_XML(VarDecl::PrivateExtern, "__private_extern__")
END_ENUM_XML
SUB_NODE_OPT_XML(Expr) // init expr
END_NODE_XML
NODE_XML(ParmVarDecl, "ParmVar")
ID_ATTRIBUTE_XML
ATTRIBUTE_FILE_LOCATION_XML
ATTRIBUTE_XML(getDeclContext(), "context")
ATTRIBUTE_XML(getNameAsString(), "name")
TYPE_ATTRIBUTE_XML(getType())
SUB_NODE_OPT_XML(Expr) // default argument expression
END_NODE_XML
NODE_XML(LinkageSpecDecl, "LinkageSpec")
ID_ATTRIBUTE_XML
ATTRIBUTE_FILE_LOCATION_XML
ATTRIBUTE_XML(getDeclContext(), "context")
ATTRIBUTE_ENUM_OPT_XML(getLanguage(), "lang")
ENUM_XML(LinkageSpecDecl::lang_c, "C")
ENUM_XML(LinkageSpecDecl::lang_cxx, "CXX")
END_ENUM_XML
END_NODE_XML
//===----------------------------------------------------------------------===//
#undef NODE_XML
#undef ID_ATTRIBUTE_XML
#undef TYPE_ATTRIBUTE_XML
#undef ATTRIBUTE_XML
#undef ATTRIBUTE_SPECIAL_XML
#undef ATTRIBUTE_OPT_XML
#undef ATTRIBUTE_ENUM_XML
#undef ATTRIBUTE_ENUM_OPT_XML
#undef ATTRIBUTE_FILE_LOCATION_XML
#undef ENUM_XML
#undef END_ENUM_XML
#undef END_NODE_XML
#undef SUB_NODE_XML
#undef SUB_NODE_SEQUENCE_XML
#undef SUB_NODE_OPT_XML

View File

@ -0,0 +1,75 @@
//===-- DocumentXML.def - Metadata about Document XML nodes -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the XML root database structure as written in
// an AST XML document.
// The following macros are used:
//
// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete
// statement of class CLASS where CLASS is a class name used internally by clang.
// After a NODE_XML the definition of all (optional) attributes of that statement
// node and possible sub-nodes follows.
//
// END_NODE_XML - Closes the attribute definition of the current node.
//
// ID_ATTRIBUTE_XML - Some nodes have an "id" attribute containing a
// string, which value uniquely identify the entity represented by that node.
// Other nodes may refer by reference attributes to this value.
//
// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves
// a special handling. See the appropriate documentations.
//
// SUB_NODE_XML( CLASS ) - A mandatory sub-node of class CLASS or its sub-classes.
//
// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or
// its sub-classes.
//
//===----------------------------------------------------------------------===//
ROOT_NODE_XML("CLANG_XML")
ATTRIBUTE_SPECIAL_XML(ignore, "version") // special retrieving needed
SUB_NODE_XML("TranslationUnit")
SUB_NODE_XML("ReferenceSection")
END_NODE_XML
NODE_XML("TranslationUnit")
SUB_NODE_SEQUENCE_XML(Decl)
END_NODE_XML
NODE_XML("ReferenceSection")
SUB_NODE_XML("Types")
SUB_NODE_XML("Contexts")
SUB_NODE_XML("Files")
END_NODE_XML
NODE_XML("Types")
SUB_NODE_SEQUENCE_XML(Type)
END_NODE_XML
NODE_XML("Contexts")
SUB_NODE_SEQUENCE_XML(DeclContext)
END_NODE_XML
NODE_XML("Files")
SUB_NODE_SEQUENCE_XML("File")
END_NODE_XML
NODE_XML("File")
ID_ATTRIBUTE_XML
ATTRIBUTE_SPECIAL_XML(ignore, "name") // special retrieving needed, denotes the source file name
END_NODE_XML
//===----------------------------------------------------------------------===//
#undef NODE_XML
#undef ID_ATTRIBUTE_XML
#undef ATTRIBUTE_SPECIAL_XML
#undef END_NODE_XML
#undef SUB_NODE_XML
#undef SUB_NODE_SEQUENCE_XML

View File

@ -17,6 +17,7 @@
#include <string>
#include <map>
#include <stack>
#include "clang/AST/Type.h"
#include "clang/AST/TypeOrdering.h"
#include "llvm/Support/raw_ostream.h"
@ -30,6 +31,7 @@ class Decl;
class NamedDecl;
class FunctionDecl;
class ASTContext;
class LabelStmt;
//---------------------------------------------------------
namespace XML
@ -50,26 +52,37 @@ class DocumentXML
{
public:
DocumentXML(const std::string& rootName, llvm::raw_ostream& out);
~DocumentXML();
void initialize(ASTContext &Context);
void PrintDecl(Decl *D);
void PrintStmt(const Stmt *S); // defined in StmtXML.cpp
void finalize();
DocumentXML& addSubNode(const std::string& name); // also enters the sub node, returns *this
DocumentXML& toParent(); // returns *this
void addAttribute(const char* pName, const QualType& pType);
void addAttribute(const char* pName, bool value);
template<class T>
void addAttribute(const char* pName, const T* value)
{
addPtrAttribute(pName, value);
}
template<class T>
void addAttribute(const char* pName, T* value)
{
addPtrAttribute(pName, value);
}
template<class T>
void addAttribute(const char* pName, const T& value);
void addTypeAttribute(const QualType& pType);
void addRefAttribute(const NamedDecl* D);
template<class T>
void addAttributeOptional(const char* pName, const T& value);
enum tContextUsage { CONTEXT_AS_CONTEXT, CONTEXT_AS_ID };
void addContextAttribute(const DeclContext *DC, tContextUsage usage = CONTEXT_AS_CONTEXT);
void addSourceFileAttribute(const std::string& fileName);
PresumedLoc addLocation(const SourceLocation& Loc);
@ -81,13 +94,9 @@ class DocumentXML
DocumentXML(const DocumentXML&); // not defined
DocumentXML& operator=(const DocumentXML&); // not defined
struct NodeXML;
NodeXML* Root;
NodeXML* CurrentNode; // always after Root
std::stack<std::string> NodeStack;
llvm::raw_ostream& Out;
ASTContext *Ctx;
int CurrentIndent;
bool HasCurrentNodeSubNodes;
@ -96,15 +105,38 @@ class DocumentXML
XML::IdMap<const Type*> BasicTypes;
XML::IdMap<std::string> SourceFiles;
XML::IdMap<const NamedDecl*> Decls;
XML::IdMap<const LabelStmt*> Labels;
void addContextsRecursively(const DeclContext *DC);
void addBasicTypeRecursively(const Type* pType);
void addTypeRecursively(const Type* pType);
void addTypeRecursively(const QualType& pType);
void PrintFunctionDecl(FunctionDecl *FD);
void addDeclIdAttribute(const NamedDecl* D);
void addTypeIdAttribute(const Type* pType);
void Indent();
// forced pointer dispatch:
void addPtrAttribute(const char* pName, const Type* pType);
void addPtrAttribute(const char* pName, const NamedDecl* D);
void addPtrAttribute(const char* pName, const DeclContext* D);
void addPtrAttribute(const char* pName, const NamespaceDecl* D); // disambiguation
void addPtrAttribute(const char* pName, const LabelStmt* L);
void addPtrAttribute(const char* pName, const char* text);
// defined in TypeXML.cpp:
void addParentTypes(const Type* pType);
void writeTypeToXML(const Type* pType);
void writeTypeToXML(const QualType& pType);
class TypeAdder;
friend class TypeAdder;
// defined in DeclXML.cpp:
void writeDeclToXML(Decl *D);
class DeclPrinter;
friend class DeclPrinter;
// for addAttributeOptional:
static bool isDefault(unsigned value) { return value == 0; }
static bool isDefault(bool value) { return !value; }
static bool isDefault(const std::string& value) { return value.empty(); }
};
//--------------------------------------------------------- inlines
@ -121,6 +153,28 @@ inline void DocumentXML::addAttribute(const char* pName, const T& value)
Out << ' ' << pName << "=\"" << value << "\"";
}
//---------------------------------------------------------
inline void DocumentXML::addPtrAttribute(const char* pName, const char* text)
{
Out << ' ' << pName << "=\"" << text << "\"";
}
//---------------------------------------------------------
inline void DocumentXML::addAttribute(const char* pName, bool value)
{
addPtrAttribute(pName, value ? "1" : "0");
}
//---------------------------------------------------------
template<class T>
inline void DocumentXML::addAttributeOptional(const char* pName, const T& value)
{
if (!isDefault(value))
{
addAttribute(pName, value);
}
}
//---------------------------------------------------------
} //namespace clang

View File

@ -386,8 +386,8 @@ namespace clang {
TYPE_OBJC_INTERFACE = 21,
/// \brief An ObjCQualifiedInterfaceType record.
TYPE_OBJC_QUALIFIED_INTERFACE = 22,
/// \brief An ObjCQualifiedIdType record.
TYPE_OBJC_QUALIFIED_ID = 23
/// \brief An ObjCObjectPointerType record.
TYPE_OBJC_OBJECT_POINTER = 23
};
/// \brief The type IDs for special types constructed by semantic

View File

@ -53,6 +53,82 @@ class NamedDecl;
class Preprocessor;
class Sema;
class SwitchCase;
class PCHReader;
class HeaderFileInfo;
/// \brief Abstract interface for callback invocations by the PCHReader.
///
/// While reading a PCH file, the PCHReader will call the methods of the
/// listener to pass on specific information. Some of the listener methods can
/// return true to indicate to the PCHReader that the information (and
/// consequently the PCH file) is invalid.
class PCHReaderListener {
public:
virtual ~PCHReaderListener();
/// \brief Receives the language options.
///
/// \returns true to indicate the options are invalid or false otherwise.
virtual bool ReadLanguageOptions(const LangOptions &LangOpts) {
return false;
}
/// \brief Receives the target triple.
///
/// \returns true to indicate the target triple is invalid or false otherwise.
virtual bool ReadTargetTriple(const std::string &Triple) {
return false;
}
/// \brief Receives the contents of the predefines buffer.
///
/// \param PCHPredef The start of the predefines buffer in the PCH
/// file.
///
/// \param PCHPredefLen The length of the predefines buffer in the PCH
/// file.
///
/// \param PCHBufferID The FileID for the PCH predefines buffer.
///
/// \param SuggestedPredefines If necessary, additional definitions are added
/// here.
///
/// \returns true to indicate the predefines are invalid or false otherwise.
virtual bool ReadPredefinesBuffer(const char *PCHPredef,
unsigned PCHPredefLen,
FileID PCHBufferID,
std::string &SuggestedPredefines) {
return false;
}
/// \brief Receives a HeaderFileInfo entry.
virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI) {}
/// \brief Receives __COUNTER__ value.
virtual void ReadCounter(unsigned Value) {}
};
/// \brief PCHReaderListener implementation to validate the information of
/// the PCH file against an initialized Preprocessor.
class PCHValidator : public PCHReaderListener {
Preprocessor &PP;
PCHReader &Reader;
unsigned NumHeaderInfos;
public:
PCHValidator(Preprocessor &PP, PCHReader &Reader)
: PP(PP), Reader(Reader), NumHeaderInfos(0) {}
virtual bool ReadLanguageOptions(const LangOptions &LangOpts);
virtual bool ReadTargetTriple(const std::string &Triple);
virtual bool ReadPredefinesBuffer(const char *PCHPredef,
unsigned PCHPredefLen,
FileID PCHBufferID,
std::string &SuggestedPredefines);
virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI);
virtual void ReadCounter(unsigned Value);
};
/// \brief Reads a precompiled head containing the contents of a
/// translation unit.
@ -75,12 +151,19 @@ class PCHReader
enum PCHReadResult { Success, Failure, IgnorePCH };
private:
/// \ brief The receiver of some callbacks invoked by PCHReader.
llvm::OwningPtr<PCHReaderListener> Listener;
SourceManager &SourceMgr;
FileManager &FileMgr;
Diagnostic &Diags;
/// \brief The semantic analysis object that will be processing the
/// PCH file and the translation unit that uses it.
Sema *SemaObj;
/// \brief The preprocessor that will be loading the source file.
Preprocessor &PP;
Preprocessor *PP;
/// \brief The AST context into which we'll read the PCH file.
ASTContext *Context;
@ -328,12 +411,33 @@ class PCHReader
public:
typedef llvm::SmallVector<uint64_t, 64> RecordData;
explicit PCHReader(Preprocessor &PP, ASTContext *Context);
/// \brief Load the PCH file and validate its contents against the given
/// Preprocessor.
PCHReader(Preprocessor &PP, ASTContext *Context);
/// \brief Load the PCH file without using any pre-initialized Preprocessor.
///
/// The necessary information to initialize a Preprocessor later can be
/// obtained by setting a PCHReaderListener.
PCHReader(SourceManager &SourceMgr, FileManager &FileMgr, Diagnostic &Diags);
~PCHReader();
/// \brief Load the precompiled header designated by the given file
/// name.
PCHReadResult ReadPCH(const std::string &FileName);
/// \brief Set the PCH callbacks listener.
void setListener(PCHReaderListener *listener) {
Listener.reset(listener);
}
/// \brief Set the Preprocessor to use.
void setPreprocessor(Preprocessor &pp) {
PP = &pp;
}
/// \brief Sets and initializes the given Context.
void InitializeContext(ASTContext &Context);
/// \brief Retrieve the name of the original source file name
const std::string &getOriginalSourceFile() { return OriginalFileName; }

View File

@ -0,0 +1,517 @@
//===-- StmtXML.def - Metadata about Stmt XML nodes ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the XML statement database structure as written in
// <TranslationUnit> sub-nodes of the XML document.
// The semantics of the attributes and enums are mostly self-documenting
// by looking at the appropriate internally used functions and values.
// The following macros are used:
//
// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete
// statement of class CLASS where CLASS is a class name used internally by clang.
// After a NODE_XML the definition of all (optional) attributes of that statement
// node and possible sub-nodes follows.
//
// END_NODE_XML - Closes the attribute definition of the current node.
//
// ID_ATTRIBUTE_XML - Some statement nodes have an "id" attribute containing a
// string, which value uniquely identify that statement. Other nodes may refer
// by reference attributes to this value (currently used only for Label).
//
// TYPE_ATTRIBUTE_XML( FN ) - Type nodes refer to the result type id of an
// expression by a "type" attribute. FN is internally used by clang.
//
// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally
// used by clang. A boolean attribute have the values "0" or "1".
//
// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves
// a special handling. See the appropriate documentations.
//
// ATTRIBUTE_FILE_LOCATION_XML - A bunch of attributes denoting the location of
// a statement in the source file(s).
//
// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME.
// Optional attributes are omitted for boolean types, if the value is false,
// for integral types, if the value is null and for strings,
// if the value is the empty string. FN is internally used by clang.
//
// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value
// is an enumeration defined with ENUM_XML macros immediately following after
// that macro. An optional attribute is ommited, if the particular enum is the
// empty string. FN is internally used by clang.
//
// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is
// internally used by clang.
//
// END_ENUM_XML - Closes the enumeration definition of the current attribute.
//
// SUB_NODE_XML( CLASS ) - A mandatory sub-node of class CLASS or its sub-classes.
//
// SUB_NODE_OPT_XML( CLASS ) - An optional sub-node of class CLASS or its sub-classes.
//
// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or
// its sub-classes.
//
//===----------------------------------------------------------------------===//
#ifndef ATTRIBUTE_FILE_LOCATION_XML
# define ATTRIBUTE_FILE_LOCATION_XML \
ATTRIBUTE_XML(getFilename(), "file") \
ATTRIBUTE_XML(getLine(), "line") \
ATTRIBUTE_XML(getColumn(), "col") \
ATTRIBUTE_OPT_XML(getFilename(), "endfile") \
ATTRIBUTE_OPT_XML(getLine(), "endline") \
ATTRIBUTE_OPT_XML(getColumn(), "endcol")
#endif
#ifndef TYPE_ATTRIBUTE_XML
# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type")
#endif
#ifndef CONTEXT_ATTRIBUTE_XML
# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context")
#endif
NODE_XML(NullStmt, "NullStmt")
ATTRIBUTE_FILE_LOCATION_XML
END_NODE_XML
NODE_XML(CompoundStmt, "CompoundStmt")
ATTRIBUTE_FILE_LOCATION_XML
ATTRIBUTE_XML(size(), "num_stmts")
SUB_NODE_SEQUENCE_XML(Stmt)
END_NODE_XML
NODE_XML(CaseStmt, "CaseStmt") // case expr: body;
ATTRIBUTE_FILE_LOCATION_XML
SUB_NODE_XML(Stmt) // body
SUB_NODE_XML(Expr) // expr
SUB_NODE_XML(Expr) // rhs expr in gc extension: case expr .. expr: body;
END_NODE_XML
NODE_XML(DefaultStmt, "DefaultStmt") // default: body;
ATTRIBUTE_FILE_LOCATION_XML
SUB_NODE_XML(Stmt) // body
END_NODE_XML
NODE_XML(LabelStmt, "LabelStmt") // Label: body;
ID_ATTRIBUTE_XML
ATTRIBUTE_FILE_LOCATION_XML
ATTRIBUTE_XML(getName(), "name") // string
SUB_NODE_XML(Stmt) // body
END_NODE_XML
NODE_XML(IfStmt, "IfStmt") // if (cond) stmt1; else stmt2;
ATTRIBUTE_FILE_LOCATION_XML
SUB_NODE_XML(Expr) // cond
SUB_NODE_XML(Stmt) // stmt1
SUB_NODE_XML(Stmt) // stmt2
END_NODE_XML
NODE_XML(SwitchStmt, "SwitchStmt") // switch (cond) body;
ATTRIBUTE_FILE_LOCATION_XML
SUB_NODE_XML(Expr) // cond
SUB_NODE_XML(Stmt) // body
END_NODE_XML
NODE_XML(WhileStmt, "WhileStmt") // while (cond) body;
ATTRIBUTE_FILE_LOCATION_XML
SUB_NODE_XML(Expr) // cond
SUB_NODE_XML(Stmt) // body
END_NODE_XML
NODE_XML(DoStmt, "DoStmt") // do body while (cond);
ATTRIBUTE_FILE_LOCATION_XML
SUB_NODE_XML(Expr) // cond
SUB_NODE_XML(Stmt) // body
END_NODE_XML
NODE_XML(ForStmt, "ForStmt") // for (init; cond; inc) body;
ATTRIBUTE_FILE_LOCATION_XML
SUB_NODE_XML(Stmt) // init
SUB_NODE_XML(Expr) // cond
SUB_NODE_XML(Expr) // inc
SUB_NODE_XML(Stmt) // body
END_NODE_XML
NODE_XML(GotoStmt, "GotoStmt") // goto label;
ATTRIBUTE_FILE_LOCATION_XML
ATTRIBUTE_XML(getLabel()->getName(), "name") // informal string
ATTRIBUTE_XML(getLabel(), "ref") // id string
END_NODE_XML
NODE_XML(IndirectGotoStmt, "IndirectGotoStmt") // goto expr;
ATTRIBUTE_FILE_LOCATION_XML
SUB_NODE_XML(Expr) // expr
END_NODE_XML
NODE_XML(ContinueStmt, "ContinueStmt") // continue
ATTRIBUTE_FILE_LOCATION_XML
END_NODE_XML
NODE_XML(BreakStmt, "BreakStmt") // break
ATTRIBUTE_FILE_LOCATION_XML
END_NODE_XML
NODE_XML(ReturnStmt, "ReturnStmt") // return expr;
ATTRIBUTE_FILE_LOCATION_XML
SUB_NODE_XML(Expr) // expr
END_NODE_XML
NODE_XML(AsmStmt, "AsmStmt") // GNU inline-assembly statement extension
ATTRIBUTE_FILE_LOCATION_XML
// FIXME
END_NODE_XML
NODE_XML(DeclStmt, "DeclStmt") // a declaration statement
ATTRIBUTE_FILE_LOCATION_XML
SUB_NODE_SEQUENCE_XML(Decl)
END_NODE_XML
// C++ statements
NODE_XML(CXXTryStmt, "CXXTryStmt") // try CompoundStmt CXXCatchStmt1 CXXCatchStmt2 ..
ATTRIBUTE_FILE_LOCATION_XML
ATTRIBUTE_XML(getNumHandlers(), "num_handlers")
SUB_NODE_XML(CompoundStmt)
SUB_NODE_SEQUENCE_XML(CXXCatchStmt)
END_NODE_XML
NODE_XML(CXXCatchStmt, "CXXCatchStmt") // catch (decl) Stmt
ATTRIBUTE_FILE_LOCATION_XML
SUB_NODE_XML(VarDecl)
SUB_NODE_XML(Stmt)
END_NODE_XML
// Expressions
NODE_XML(PredefinedExpr, "PredefinedExpr")
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_ENUM_XML(getIdentType(), "kind")
ENUM_XML(PredefinedExpr::Func, "__func__")
ENUM_XML(PredefinedExpr::Function, "__FUNCTION__")
ENUM_XML(PredefinedExpr::PrettyFunction, "__PRETTY_FUNCTION__")
END_ENUM_XML
END_NODE_XML
NODE_XML(DeclRefExpr, "DeclRefExpr") // an expression referring to a declared entity
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_XML(getDecl(), "ref") // id string of the declaration
ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // informal
//ATTRIBUTE_ENUM_XML(getDecl()->getKind(), "kind") // really needed here?
END_NODE_XML
NODE_XML(IntegerLiteral, "IntegerLiteral")
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_XML(getValue(), "value") // (signed) integer
END_NODE_XML
NODE_XML(CharacterLiteral, "CharacterLiteral")
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_XML(getValue(), "value") // unsigned
END_NODE_XML
NODE_XML(FloatingLiteral, "FloatingLiteral")
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
// FIXME: output float as written in source (no approximation or the like)
//ATTRIBUTE_XML(getValueAsApproximateDouble(), "value") // float
END_NODE_XML
NODE_XML(StringLiteral, "StringLiteral")
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_SPECIAL_XML(getStrData(), "value") // string, special handling for escaping needed
ATTRIBUTE_OPT_XML(isWide(), "is_wide") // boolean
END_NODE_XML
NODE_XML(UnaryOperator, "UnaryOperator") // op(expr) or (expr)op
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_ENUM_XML(getOpcode(), "kind")
ENUM_XML(UnaryOperator::PostInc, "postinc")
ENUM_XML(UnaryOperator::PostDec, "postdec")
ENUM_XML(UnaryOperator::PreInc, "preinc")
ENUM_XML(UnaryOperator::PreDec, "predec")
ENUM_XML(UnaryOperator::AddrOf, "addrof")
ENUM_XML(UnaryOperator::Deref, "deref")
ENUM_XML(UnaryOperator::Plus, "plus")
ENUM_XML(UnaryOperator::Minus, "minus")
ENUM_XML(UnaryOperator::Not, "not") // bitwise not
ENUM_XML(UnaryOperator::LNot, "lnot") // boolean not
ENUM_XML(UnaryOperator::Real, "__real")
ENUM_XML(UnaryOperator::Imag, "__imag")
ENUM_XML(UnaryOperator::Extension, "__extension__")
ENUM_XML(UnaryOperator::OffsetOf, "__builtin_offsetof")
END_ENUM_XML
SUB_NODE_XML(Expr) // expr
END_NODE_XML
NODE_XML(BinaryOperator, "BinaryOperator") // (expr1) op (expr2)
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_ENUM_XML(getOpcode(), "kind")
ENUM_XML(BinaryOperator::PtrMemD , "ptrmemd")
ENUM_XML(BinaryOperator::PtrMemI , "ptrmemi")
ENUM_XML(BinaryOperator::Mul , "mul")
ENUM_XML(BinaryOperator::Div , "div")
ENUM_XML(BinaryOperator::Rem , "rem")
ENUM_XML(BinaryOperator::Add , "add")
ENUM_XML(BinaryOperator::Sub , "sub")
ENUM_XML(BinaryOperator::Shl , "shl")
ENUM_XML(BinaryOperator::Shr , "shr")
ENUM_XML(BinaryOperator::LT , "lt")
ENUM_XML(BinaryOperator::GT , "gt")
ENUM_XML(BinaryOperator::LE , "le")
ENUM_XML(BinaryOperator::GE , "ge")
ENUM_XML(BinaryOperator::EQ , "eq")
ENUM_XML(BinaryOperator::NE , "ne")
ENUM_XML(BinaryOperator::And , "and") // bitwise and
ENUM_XML(BinaryOperator::Xor , "xor")
ENUM_XML(BinaryOperator::Or , "or") // bitwise or
ENUM_XML(BinaryOperator::LAnd , "land") // boolean and
ENUM_XML(BinaryOperator::LOr , "lor") // boolean or
ENUM_XML(BinaryOperator::Assign , "assign")
ENUM_XML(BinaryOperator::MulAssign, "mulassign")
ENUM_XML(BinaryOperator::DivAssign, "divassign")
ENUM_XML(BinaryOperator::RemAssign, "remassign")
ENUM_XML(BinaryOperator::AddAssign, "addassign")
ENUM_XML(BinaryOperator::SubAssign, "subassign")
ENUM_XML(BinaryOperator::ShlAssign, "shlassign")
ENUM_XML(BinaryOperator::ShrAssign, "shrassign")
ENUM_XML(BinaryOperator::AndAssign, "andassign")
ENUM_XML(BinaryOperator::XorAssign, "xorassign")
ENUM_XML(BinaryOperator::OrAssign , "orassign")
ENUM_XML(BinaryOperator::Comma , "comma")
END_ENUM_XML
SUB_NODE_XML(Expr) // expr1
SUB_NODE_XML(Expr) // expr2
END_NODE_XML
// FIXME: is there a special class needed or is BinaryOperator sufficient?
//NODE_XML(CompoundAssignOperator, "CompoundAssignOperator")
NODE_XML(ConditionalOperator, "ConditionalOperator") // expr1 ? expr2 : expr3
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
SUB_NODE_XML(Expr) // expr1
SUB_NODE_XML(Expr) // expr2
SUB_NODE_XML(Expr) // expr3
END_NODE_XML
NODE_XML(SizeOfAlignOfExpr, "SizeOfAlignOfExpr") // sizeof(expr) or alignof(expr)
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_XML(isSizeOf(), "is_sizeof")
ATTRIBUTE_XML(isArgumentType(), "is_type") // "1" if expr denotes a type
ATTRIBUTE_SPECIAL_XML(getArgumentType(), "type_ref") // optional, denotes the type of expr, if is_type=="1", special handling needed since getArgumentType() could assert
SUB_NODE_OPT_XML(Expr) // expr, if is_type=="0"
END_NODE_XML
NODE_XML(ArraySubscriptExpr, "ArraySubscriptExpr") // expr1[expr2]
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
SUB_NODE_XML(Expr) // expr1
SUB_NODE_XML(Expr) // expr2
END_NODE_XML
NODE_XML(CallExpr, "CallExpr") // fnexpr(arg1, arg2, ...)
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned
SUB_NODE_XML(Expr) // fnexpr
SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN
END_NODE_XML
NODE_XML(MemberExpr, "MemberExpr") // expr->F or expr.F
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_XML(isArrow(), "is_deref")
ATTRIBUTE_XML(getMemberDecl(), "ref") // refers to F
ATTRIBUTE_XML(getMemberDecl()->getNameAsString(), "name") // informal
SUB_NODE_XML(Expr) // expr
END_NODE_XML
NODE_XML(CStyleCastExpr, "CStyleCastExpr") // (type)expr
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_XML(getTypeAsWritten(), "type_ref") // denotes the type as written in the source code
SUB_NODE_XML(Expr) // expr
END_NODE_XML
NODE_XML(ImplicitCastExpr, "ImplicitCastExpr")
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
SUB_NODE_XML(Expr)
END_NODE_XML
NODE_XML(CompoundLiteralExpr, "CompoundLiteralExpr") // [C99 6.5.2.5]
SUB_NODE_XML(Expr) // init
END_NODE_XML
NODE_XML(ExtVectorElementExpr, "ExtVectorElementExpr")
SUB_NODE_XML(Expr) // base
END_NODE_XML
NODE_XML(InitListExpr, "InitListExpr") // struct foo x = { expr1, { expr2, expr3 } };
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_OPT_XML(getInitializedFieldInUnion(), "field_ref") // if a union is initialized, this refers to the initialized union field id
ATTRIBUTE_XML(getNumInits(), "num_inits") // unsigned
SUB_NODE_SEQUENCE_XML(Expr) // expr1..exprN
END_NODE_XML
NODE_XML(DesignatedInitExpr, "DesignatedInitExpr")
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
END_NODE_XML
NODE_XML(ImplicitValueInitExpr, "ImplicitValueInitExpr") // Implicit value initializations occur within InitListExpr
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
END_NODE_XML
NODE_XML(VAArgExpr, "VAArgExpr") // used for the builtin function __builtin_va_start(expr)
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
SUB_NODE_XML(Expr) // expr
END_NODE_XML
NODE_XML(ParenExpr, "ParenExpr") // this represents a parethesized expression "(expr)". Only formed if full location information is requested.
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
SUB_NODE_XML(Expr) // expr
END_NODE_XML
// GNU Extensions
NODE_XML(AddrLabelExpr, "AddrLabelExpr") // the GNU address of label extension, representing &&label.
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_XML(getLabel(), "ref") // id string
SUB_NODE_XML(LabelStmt) // expr
END_NODE_XML
NODE_XML(StmtExpr, "StmtExpr") // StmtExpr contains a single CompoundStmt node, which it evaluates and takes the value of the last subexpression.
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
SUB_NODE_XML(CompoundStmt)
END_NODE_XML
NODE_XML(TypesCompatibleExpr, "TypesCompatibleExpr") // GNU builtin-in function __builtin_types_compatible_p
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_XML(getArgType1(), "type1_ref") // id of type1
ATTRIBUTE_XML(getArgType2(), "type2_ref") // id of type2
END_NODE_XML
NODE_XML(ChooseExpr, "ChooseExpr") // GNU builtin-in function __builtin_choose_expr(expr1, expr2, expr3)
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
SUB_NODE_XML(Expr) // expr1
SUB_NODE_XML(Expr) // expr2
SUB_NODE_XML(Expr) // expr3
END_NODE_XML
NODE_XML(GNUNullExpr, "GNUNullExpr") // GNU __null extension
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
END_NODE_XML
// C++ Expressions
NODE_XML(CXXOperatorCallExpr, "CXXOperatorCallExpr") // fnexpr(arg1, arg2, ...)
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned
SUB_NODE_XML(Expr) // fnexpr
SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN
END_NODE_XML
NODE_XML(CXXNamedCastExpr, "CXXNamedCastExpr") // xxx_cast<type>(expr)
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_ENUM_XML(getStmtClass(), "kind")
ENUM_XML(Stmt::CXXStaticCastExprClass, "static_cast")
ENUM_XML(Stmt::CXXDynamicCastExprClass, "dynamic_cast")
ENUM_XML(Stmt::CXXReinterpretCastExprClass, "reinterpret_cast")
ENUM_XML(Stmt::CXXConstCastExprClass, "const_cast")
END_ENUM_XML
ATTRIBUTE_XML(getTypeAsWritten(), "type_ref") // denotes the type as written in the source code
SUB_NODE_XML(Expr) // expr
END_NODE_XML
NODE_XML(CXXMemberCallExpr, "CXXMemberCallExpr") // fnexpr(arg1, arg2, ...)
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned
SUB_NODE_XML(Expr) // fnexpr
SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN
END_NODE_XML
NODE_XML(CXXBoolLiteralExpr, "CXXBoolLiteralExpr")
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_XML(getValue(), "value") // boolean
END_NODE_XML
NODE_XML(CXXNullPtrLiteralExpr, "CXXNullPtrLiteralExpr") // [C++0x 2.14.7] C++ Pointer Literal
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
END_NODE_XML
NODE_XML(CXXTypeidExpr, "CXXTypeidExpr") // typeid(expr)
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_XML(isTypeOperand(), "is_type") // "1" if expr denotes a type
ATTRIBUTE_SPECIAL_XML(getTypeOperand(), "type_ref") // optional, denotes the type of expr, if is_type=="1", special handling needed since getTypeOperand() could assert
SUB_NODE_OPT_XML(Expr) // expr, if is_type=="0"
END_NODE_XML
NODE_XML(CXXThisExpr, "CXXThisExpr") // this
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
END_NODE_XML
NODE_XML(CXXThrowExpr, "CXXThrowExpr") // throw (expr);
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
SUB_NODE_XML(Expr) // NULL in case of "throw;"
END_NODE_XML
NODE_XML(CXXDefaultArgExpr, "CXXDefaultArgExpr")
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_XML(getParam(), "ref") // id of the parameter declaration (the expression is a subnode of the declaration)
END_NODE_XML
NODE_XML(CXXConditionDeclExpr, "CXXConditionDeclExpr")
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
SUB_NODE_XML(VarDecl) // a CXXConditionDeclExpr owns the declaration
END_NODE_XML
//===----------------------------------------------------------------------===//
#undef NODE_XML
#undef ID_ATTRIBUTE_XML
#undef TYPE_ATTRIBUTE_XML
#undef ATTRIBUTE_XML
#undef ATTRIBUTE_SPECIAL_XML
#undef ATTRIBUTE_OPT_XML
#undef ATTRIBUTE_ENUM_XML
#undef ATTRIBUTE_ENUM_OPT_XML
#undef ATTRIBUTE_FILE_LOCATION_XML
#undef ENUM_XML
#undef END_ENUM_XML
#undef END_NODE_XML
#undef SUB_NODE_XML
#undef SUB_NODE_SEQUENCE_XML
#undef SUB_NODE_OPT_XML

View File

@ -0,0 +1,277 @@
//===-- TypeXML.def - Metadata about Type XML nodes ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the XML type info database as written in the
// <ReferenceSection>/<Types> sub-nodes of the XML document. Type nodes
// are referred by "type" reference attributes throughout the document.
// A type node never contains sub-nodes.
// The semantics of the attributes and enums are mostly self-documenting
// by looking at the appropriate internally used functions and values.
// The following macros are used:
//
// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete
// type of class CLASS where CLASS is a class name used internally by clang.
// After a NODE_XML the definition of all (optional) attributes of that type
// node follows.
//
// END_NODE_XML - Closes the attribute definition of the current node.
//
// ID_ATTRIBUTE_XML - Each type node has an "id" attribute containing a
// string, which value uniquely identify the type. Other nodes may refer
// by "type" reference attributes to this value.
//
// TYPE_ATTRIBUTE_XML( FN ) - Type nodes may refer to the ids of other type
// nodes by a "type" attribute. FN is internally used by clang.
//
// CONTEXT_ATTRIBUTE_XML( FN ) - Type nodes may refer to the ids of their
// declaration contexts by a "context" attribute. FN is internally used by
// clang.
//
// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally
// used by clang. A boolean attribute have the values "0" or "1".
//
// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME.
// Optional attributes are omitted for boolean types, if the value is false,
// for integral types, if the value is null and for strings,
// if the value is the empty string. FN is internally used by clang.
//
// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value
// is an enumeration defined with ENUM_XML macros immediately following after
// that macro. An optional attribute is ommited, if the particular enum is the
// empty string. FN is internally used by clang.
//
// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is
// internally used by clang.
//
// END_ENUM_XML - Closes the enumeration definition of the current attribute.
//
//===----------------------------------------------------------------------===//
#ifndef TYPE_ATTRIBUTE_XML
# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type")
#endif
#ifndef CONTEXT_ATTRIBUTE_XML
# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context")
#endif
NODE_XML(QualType, "CvQualifiedType")
ID_ATTRIBUTE_XML
TYPE_ATTRIBUTE_XML(getTypePtr()) // the qualified type, e.g. for 'T* const' it's 'T*'
ATTRIBUTE_OPT_XML(isConstQualified(), "const") // boolean
ATTRIBUTE_OPT_XML(isVolatileQualified(), "volatile") // boolean
ATTRIBUTE_OPT_XML(isRestrictQualified(), "restrict") // boolean
END_NODE_XML
NODE_XML(ExtQualType, "ExtQualType")
ID_ATTRIBUTE_XML
TYPE_ATTRIBUTE_XML(getBaseType())
ATTRIBUTE_OPT_XML(getAddressSpace(), "adress_space") // unsigned: Address Space ID - The address space ID this type is qualified with.
ATTRIBUTE_ENUM_OPT_XML(getObjCGCAttr(), "objc_gc") // GC __weak/__strong attributes
ENUM_XML(QualType::GCNone, "")
ENUM_XML(QualType::Weak, "weak")
ENUM_XML(QualType::Strong, "strong")
END_ENUM_XML
END_NODE_XML
NODE_XML(BuiltinType, "FundamentalType")
ID_ATTRIBUTE_XML
ATTRIBUTE_ENUM_XML(getKind(), "kind")
ENUM_XML(BuiltinType::Void, "void")
ENUM_XML(BuiltinType::Bool, "bool")
ENUM_XML(BuiltinType::Char_U, "char") // not explicitely qualified char, depends on target platform
ENUM_XML(BuiltinType::Char_S, "char") // not explicitely qualified char, depends on target platform
ENUM_XML(BuiltinType::SChar, "signed char")
ENUM_XML(BuiltinType::Short, "short");
ENUM_XML(BuiltinType::Int, "int");
ENUM_XML(BuiltinType::Long, "long");
ENUM_XML(BuiltinType::LongLong, "long long");
ENUM_XML(BuiltinType::Int128, "__int128_t");
ENUM_XML(BuiltinType::UChar, "unsigned char");
ENUM_XML(BuiltinType::UShort, "unsigned short");
ENUM_XML(BuiltinType::UInt, "unsigned int");
ENUM_XML(BuiltinType::ULong, "unsigned long");
ENUM_XML(BuiltinType::ULongLong, "unsigned long long");
ENUM_XML(BuiltinType::UInt128, "__uint128_t");
ENUM_XML(BuiltinType::Float, "float");
ENUM_XML(BuiltinType::Double, "double");
ENUM_XML(BuiltinType::LongDouble, "long double");
ENUM_XML(BuiltinType::WChar, "wchar_t");
ENUM_XML(BuiltinType::NullPtr, "nullptr_t"); // This is the type of C++0x 'nullptr'.
ENUM_XML(BuiltinType::Overload, "overloaded");
ENUM_XML(BuiltinType::Dependent, "dependent");
END_ENUM_XML
END_NODE_XML
NODE_XML(FixedWidthIntType, "FixedWidthIntType")
ID_ATTRIBUTE_XML
ATTRIBUTE_XML(getWidth(), "width") // unsigned
ATTRIBUTE_XML(isSigned(), "is_signed") // boolean
END_NODE_XML
NODE_XML(PointerType, "PointerType")
ID_ATTRIBUTE_XML
TYPE_ATTRIBUTE_XML(getPointeeType())
END_NODE_XML
NODE_XML(LValueReferenceType, "ReferenceType")
ID_ATTRIBUTE_XML
TYPE_ATTRIBUTE_XML(getPointeeType())
END_NODE_XML
NODE_XML(RValueReferenceType, "ReferenceType")
ID_ATTRIBUTE_XML
TYPE_ATTRIBUTE_XML(getPointeeType())
END_NODE_XML
NODE_XML(FunctionNoProtoType, "FunctionNoProtoType")
ID_ATTRIBUTE_XML
END_NODE_XML
NODE_XML(FunctionProtoType, "FunctionType")
ID_ATTRIBUTE_XML
ATTRIBUTE_XML(getResultType(), "result_type")
ATTRIBUTE_OPT_XML(isVariadic(), "variadic")
END_NODE_XML
NODE_XML(TypedefType, "Typedef")
ID_ATTRIBUTE_XML
TYPE_ATTRIBUTE_XML(getDecl()->getUnderlyingType())
ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // string
CONTEXT_ATTRIBUTE_XML(getDecl()->getDeclContext())
END_NODE_XML
NODE_XML(ComplexType, "ComplexType") // C99 complex types (_Complex float etc)
ID_ATTRIBUTE_XML
TYPE_ATTRIBUTE_XML(getElementType())
END_NODE_XML
NODE_XML(BlockPointerType, "BlockPointerType")
ID_ATTRIBUTE_XML
TYPE_ATTRIBUTE_XML(getPointeeType()) // alway refers to a function type
END_NODE_XML
NODE_XML(MemberPointerType, "MemberPointerType")
ID_ATTRIBUTE_XML
TYPE_ATTRIBUTE_XML(getPointeeType())
ATTRIBUTE_XML(getClass(), "class_type") // refers to the class type id of which the pointee is a member
END_NODE_XML
NODE_XML(ConstantArrayType, "ArrayType")
ID_ATTRIBUTE_XML
TYPE_ATTRIBUTE_XML(getElementType())
ATTRIBUTE_XML(getSize(), "size") // unsigned
ATTRIBUTE_ENUM_OPT_XML(getSizeModifier(), "size_modifier")
ENUM_XML(ArrayType::Normal, "")
ENUM_XML(ArrayType::Static, "static")
ENUM_XML(ArrayType::Star, "star")
END_ENUM_XML
ATTRIBUTE_OPT_XML(getIndexTypeQualifier(), "index_type_qualifier") // unsigned
END_NODE_XML
NODE_XML(IncompleteArrayType, "IncompleteArrayType")
ID_ATTRIBUTE_XML
TYPE_ATTRIBUTE_XML(getElementType())
END_NODE_XML
NODE_XML(VariableArrayType, "VariableArrayType")
ID_ATTRIBUTE_XML
TYPE_ATTRIBUTE_XML(getElementType())
// note: the size expression is print at the point of declaration
END_NODE_XML
NODE_XML(DependentSizedArrayType, "DependentSizedArrayType")
ID_ATTRIBUTE_XML
TYPE_ATTRIBUTE_XML(getElementType())
// FIXME: how to deal with size expression?
END_NODE_XML
NODE_XML(VectorType, "VectorType")
ID_ATTRIBUTE_XML
TYPE_ATTRIBUTE_XML(getElementType())
ATTRIBUTE_XML(getNumElements(), "size") // unsigned
END_NODE_XML
NODE_XML(ExtVectorType, "ExtVectorType")
ID_ATTRIBUTE_XML
TYPE_ATTRIBUTE_XML(getElementType())
ATTRIBUTE_XML(getNumElements(), "size") // unsigned
END_NODE_XML
NODE_XML(TypeOfExprType, "TypeOfExprType")
ID_ATTRIBUTE_XML
// note: the typeof expression is print at the point of use
END_NODE_XML
NODE_XML(TypeOfType, "TypeOfType")
ID_ATTRIBUTE_XML
TYPE_ATTRIBUTE_XML(getUnderlyingType())
END_NODE_XML
NODE_XML(RecordType, "Record")
ID_ATTRIBUTE_XML
ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // string
ATTRIBUTE_ENUM_XML(getDecl()->getTagKind(), "kind")
ENUM_XML(TagDecl::TK_struct, "struct")
ENUM_XML(TagDecl::TK_union, "union")
ENUM_XML(TagDecl::TK_class, "class")
END_ENUM_XML
CONTEXT_ATTRIBUTE_XML(getDecl()->getDeclContext())
END_NODE_XML
NODE_XML(EnumType, "Enum")
ID_ATTRIBUTE_XML
ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // string
CONTEXT_ATTRIBUTE_XML(getDecl()->getDeclContext())
END_NODE_XML
NODE_XML(TemplateTypeParmType, "TemplateTypeParmType")
ID_ATTRIBUTE_XML
END_NODE_XML
NODE_XML(TemplateSpecializationType, "TemplateSpecializationType")
ID_ATTRIBUTE_XML
END_NODE_XML
NODE_XML(QualifiedNameType, "QualifiedNameType")
ID_ATTRIBUTE_XML
TYPE_ATTRIBUTE_XML(getNamedType())
END_NODE_XML
NODE_XML(TypenameType, "TypenameType")
ID_ATTRIBUTE_XML
END_NODE_XML
NODE_XML(ObjCInterfaceType, "ObjCInterfaceType")
ID_ATTRIBUTE_XML
END_NODE_XML
NODE_XML(ObjCQualifiedInterfaceType, "ObjCQualifiedInterfaceType")
ID_ATTRIBUTE_XML
END_NODE_XML
NODE_XML(ObjCObjectPointerType, "ObjCObjectPointerType")
ID_ATTRIBUTE_XML
END_NODE_XML
//===----------------------------------------------------------------------===//
#undef NODE_XML
#undef ID_ATTRIBUTE_XML
#undef TYPE_ATTRIBUTE_XML
#undef CONTEXT_ATTRIBUTE_XML
#undef ATTRIBUTE_XML
#undef ATTRIBUTE_OPT_XML
#undef ATTRIBUTE_ENUM_XML
#undef ATTRIBUTE_ENUM_OPT_XML
#undef ENUM_XML
#undef END_ENUM_XML
#undef END_NODE_XML

View File

@ -248,6 +248,19 @@ class Action : public ActionBase {
virtual void ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
}
/// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an
/// initializer for the declaration 'Dcl'.
/// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a
/// static data member of class X, names should be looked up in the scope of
/// class X.
virtual void ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl) {
}
/// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
/// initializer for the declaration 'Dcl'.
virtual void ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl) {
}
/// ActOnDeclarator - This callback is invoked when a declarator is parsed and
/// 'Init' specifies the initializer if any. This is for things like:
/// "int X = 4" or "typedef int foo".
@ -624,6 +637,18 @@ class Action : public ActionBase {
// Expression Parsing Callbacks.
//===--------------------------------------------------------------------===//
/// \brief Notifies the action when the parser is processing an unevaluated
/// operand.
///
/// \param UnevaluatedOperand true to indicate that the parser is processing
/// an unevaluated operand, or false otherwise.
///
/// \returns whether the the action module was previously in an unevaluated
/// operand.
virtual bool setUnevaluatedOperand(bool UnevaluatedOperand) {
return false;
}
// Primary Expressions.
/// \brief Retrieve the source range that corresponds to the given
@ -907,6 +932,15 @@ class Action : public ActionBase {
IdentifierInfo *Ident) {
return DeclPtrTy();
}
/// ActOnUsingDirective - This is called when using-directive is parsed.
virtual DeclPtrTy ActOnUsingDeclaration(Scope *CurScope,
SourceLocation UsingLoc,
const CXXScopeSpec &SS,
SourceLocation IdentLoc,
IdentifierInfo *TargetName,
AttributeList *AttrList,
bool IsTypeName);
/// ActOnParamDefaultArgument - Parse default argument for function parameter
virtual void ActOnParamDefaultArgument(DeclPtrTy param,

View File

@ -105,6 +105,24 @@ class Parser {
}
};
/// \brief RAII object that enters an unevaluated operand.
class EnterUnevaluatedOperand {
/// \brief The action object.
Action &Actions;
/// \brief Whether we were previously within an unevaluated operand.
bool PreviouslyInUnevaluatedOperand;
public:
explicit EnterUnevaluatedOperand(Action &Actions) : Actions(Actions) {
PreviouslyInUnevaluatedOperand = Actions.setUnevaluatedOperand(true);
}
~EnterUnevaluatedOperand() {
Actions.setUnevaluatedOperand(PreviouslyInUnevaluatedOperand);
}
};
public:
Parser(Preprocessor &PP, Action &Actions);
~Parser();

View File

@ -222,7 +222,7 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
unsigned ASTContext::getDeclAlignInBytes(const Decl *D) {
unsigned Align = Target.getCharWidth();
if (const AlignedAttr* AA = D->getAttr<AlignedAttr>())
if (const AlignedAttr* AA = D->getAttr<AlignedAttr>(*this))
Align = std::max(Align, AA->getAlignment());
if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
@ -369,7 +369,7 @@ ASTContext::getTypeInfo(const Type *T) {
// FIXME: Pointers into different addr spaces could have different sizes and
// alignment requirements: getPointerInfo should take an AddrSpace.
return getTypeInfo(QualType(cast<ExtQualType>(T)->getBaseType(), 0));
case Type::ObjCQualifiedId:
case Type::ObjCObjectPointer:
case Type::ObjCQualifiedInterface:
Width = Target.getPointerWidth(0);
Align = Target.getPointerAlign(0);
@ -445,7 +445,7 @@ ASTContext::getTypeInfo(const Type *T) {
case Type::Typedef: {
const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl();
if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>()) {
if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>(*this)) {
Align = Aligned->getAlignment();
Width = getTypeSize(Typedef->getUnderlyingType().getTypePtr());
} else
@ -505,7 +505,7 @@ void ASTRecordLayout::LayoutField(const FieldDecl *FD, unsigned FieldNo,
// FIXME: Should this override struct packing? Probably we want to
// take the minimum?
if (const PackedAttr *PA = FD->getAttr<PackedAttr>())
if (const PackedAttr *PA = FD->getAttr<PackedAttr>(Context))
FieldPacking = PA->getAlignment();
if (const Expr *BitWidthExpr = FD->getBitWidth()) {
@ -525,7 +525,7 @@ void ASTRecordLayout::LayoutField(const FieldDecl *FD, unsigned FieldNo,
FieldAlign = FieldInfo.second;
if (FieldPacking)
FieldAlign = std::min(FieldAlign, FieldPacking);
if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>())
if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>(Context))
FieldAlign = std::max(FieldAlign, AA->getAlignment());
// Check if we need to add padding to give the field the correct
@ -565,7 +565,7 @@ void ASTRecordLayout::LayoutField(const FieldDecl *FD, unsigned FieldNo,
// is smaller than the specified packing?
if (FieldPacking)
FieldAlign = std::min(FieldAlign, std::max(8U, FieldPacking));
if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>())
if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>(Context))
FieldAlign = std::max(FieldAlign, AA->getAlignment());
// Round up the current record size to the field's alignment boundary.
@ -731,10 +731,10 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
}
unsigned StructPacking = 0;
if (const PackedAttr *PA = D->getAttr<PackedAttr>())
if (const PackedAttr *PA = D->getAttr<PackedAttr>(*this))
StructPacking = PA->getAlignment();
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>(*this))
NewEntry->SetAlignment(std::max(NewEntry->getAlignment(),
AA->getAlignment()));
@ -783,10 +783,10 @@ const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D) {
bool IsUnion = D->isUnion();
unsigned StructPacking = 0;
if (const PackedAttr *PA = D->getAttr<PackedAttr>())
if (const PackedAttr *PA = D->getAttr<PackedAttr>(*this))
StructPacking = PA->getAlignment();
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>(*this))
NewEntry->SetAlignment(std::max(NewEntry->getAlignment(),
AA->getAlignment()));
@ -1269,6 +1269,18 @@ QualType ASTContext::getExtVectorType(QualType vecType, unsigned NumElts) {
return QualType(New, 0);
}
QualType ASTContext::getDependentSizedExtVectorType(QualType vecType,
Expr *SizeExpr,
SourceLocation AttrLoc) {
DependentSizedExtVectorType *New =
new (*this,8) DependentSizedExtVectorType(vecType, QualType(),
SizeExpr, AttrLoc);
DependentSizedExtVectorTypes.push_back(New);
Types.push_back(New);
return QualType(New, 0);
}
/// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
///
QualType ASTContext::getFunctionNoProtoType(QualType ResultTy) {
@ -1414,11 +1426,13 @@ QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl) {
}
/// \brief Retrieve the template type parameter type for a template
/// parameter with the given depth, index, and (optionally) name.
/// parameter or parameter pack with the given depth, index, and (optionally)
/// name.
QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index,
bool ParameterPack,
IdentifierInfo *Name) {
llvm::FoldingSetNodeID ID;
TemplateTypeParmType::Profile(ID, Depth, Index, Name);
TemplateTypeParmType::Profile(ID, Depth, Index, ParameterPack, Name);
void *InsertPos = 0;
TemplateTypeParmType *TypeParm
= TemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos);
@ -1426,11 +1440,12 @@ QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index,
if (TypeParm)
return QualType(TypeParm, 0);
if (Name)
TypeParm = new (*this, 8) TemplateTypeParmType(Depth, Index, Name,
getTemplateTypeParmType(Depth, Index));
else
TypeParm = new (*this, 8) TemplateTypeParmType(Depth, Index);
if (Name) {
QualType Canon = getTemplateTypeParmType(Depth, Index, ParameterPack);
TypeParm = new (*this, 8) TemplateTypeParmType(Depth, Index, ParameterPack,
Name, Canon);
} else
TypeParm = new (*this, 8) TemplateTypeParmType(Depth, Index, ParameterPack);
Types.push_back(TypeParm);
TemplateTypeParmTypes.InsertNode(TypeParm, InsertPos);
@ -1563,6 +1578,31 @@ static void SortAndUniqueProtocols(ObjCProtocolDecl **&Protocols,
NumProtocols = ProtocolsEnd-Protocols;
}
/// getObjCObjectPointerType - Return a ObjCObjectPointerType type for
/// the given interface decl and the conforming protocol list.
QualType ASTContext::getObjCObjectPointerType(ObjCInterfaceDecl *Decl,
ObjCProtocolDecl **Protocols,
unsigned NumProtocols) {
// Sort the protocol list alphabetically to canonicalize it.
if (NumProtocols)
SortAndUniqueProtocols(Protocols, NumProtocols);
llvm::FoldingSetNodeID ID;
ObjCObjectPointerType::Profile(ID, Decl, Protocols, NumProtocols);
void *InsertPos = 0;
if (ObjCObjectPointerType *QT =
ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(QT, 0);
// No Match;
ObjCObjectPointerType *QType =
new (*this,8) ObjCObjectPointerType(Decl, Protocols, NumProtocols);
Types.push_back(QType);
ObjCObjectPointerTypes.InsertNode(QType, InsertPos);
return QualType(QType, 0);
}
/// getObjCQualifiedInterfaceType - Return a ObjCQualifiedInterfaceType type for
/// the given interface decl and the conforming protocol list.
@ -1592,23 +1632,7 @@ QualType ASTContext::getObjCQualifiedInterfaceType(ObjCInterfaceDecl *Decl,
/// and the conforming protocol list.
QualType ASTContext::getObjCQualifiedIdType(ObjCProtocolDecl **Protocols,
unsigned NumProtocols) {
// Sort the protocol list alphabetically to canonicalize it.
SortAndUniqueProtocols(Protocols, NumProtocols);
llvm::FoldingSetNodeID ID;
ObjCQualifiedIdType::Profile(ID, Protocols, NumProtocols);
void *InsertPos = 0;
if (ObjCQualifiedIdType *QT =
ObjCQualifiedIdTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(QT, 0);
// No Match;
ObjCQualifiedIdType *QType =
new (*this,8) ObjCQualifiedIdType(Protocols, NumProtocols);
Types.push_back(QType);
ObjCQualifiedIdTypes.InsertNode(QType, InsertPos);
return QualType(QType, 0);
return getObjCObjectPointerType(0, Protocols, NumProtocols);
}
/// getTypeOfExprType - Unlike many "get<Type>" functions, we can't unique
@ -2398,9 +2422,9 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
if (FD || EncodingProperty) {
// Note that we do extended encoding of protocol qualifer list
// Only when doing ivar or property encoding.
const ObjCQualifiedIdType *QIDT = T->getAsObjCQualifiedIdType();
const ObjCObjectPointerType *QIDT = T->getAsObjCQualifiedIdType();
S += '"';
for (ObjCQualifiedIdType::qual_iterator I = QIDT->qual_begin(),
for (ObjCObjectPointerType::qual_iterator I = QIDT->qual_begin(),
E = QIDT->qual_end(); I != E; ++I) {
S += '<';
S += (*I)->getNameAsString();
@ -2758,7 +2782,7 @@ QualType ASTContext::getFromTargetType(unsigned Type) const {
bool ASTContext::isObjCNSObjectType(QualType Ty) const {
if (TypedefType *TDT = dyn_cast<TypedefType>(Ty)) {
if (TypedefDecl *TD = TDT->getDecl())
if (TD->getAttr<ObjCNSObjectAttr>())
if (TD->getAttr<ObjCNSObjectAttr>(*const_cast<ASTContext*>(this)))
return true;
}
return false;
@ -3283,7 +3307,8 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
return QualType();
}
case Type::ObjCQualifiedId:
case Type::ObjCObjectPointer:
// FIXME: finish
// Distinct qualified id's are not compatible.
return QualType();
case Type::FixedWidthInt:

View File

@ -315,6 +315,12 @@ void VarDecl::Destroy(ASTContext& C) {
VarDecl::~VarDecl() {
}
SourceRange VarDecl::getSourceRange() const {
if (getInit())
return SourceRange(getLocation(), getInit()->getLocEnd());
return SourceRange(getLocation(), getLocation());
}
bool VarDecl::isTentativeDefinition(ASTContext &Context) const {
if (!isFileVarDecl() || Context.getLangOptions().CPlusPlus)
return false;
@ -371,6 +377,12 @@ Stmt *FunctionDecl::getBodyIfAvailable() const {
return 0;
}
void FunctionDecl::setBody(Stmt *B) {
Body = B;
if (B && EndRangeLoc < B->getLocEnd())
EndRangeLoc = B->getLocEnd();
}
bool FunctionDecl::isMain() const {
return getDeclContext()->getLookupContext()->isTranslationUnit() &&
getIdentifier() && getIdentifier()->isStr("main");
@ -380,13 +392,14 @@ bool FunctionDecl::isExternC(ASTContext &Context) const {
// In C, any non-static, non-overloadable function has external
// linkage.
if (!Context.getLangOptions().CPlusPlus)
return getStorageClass() != Static && !getAttr<OverloadableAttr>();
return getStorageClass() != Static && !getAttr<OverloadableAttr>(Context);
for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit();
DC = DC->getParent()) {
if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) {
if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
return getStorageClass() != Static && !getAttr<OverloadableAttr>();
return getStorageClass() != Static &&
!getAttr<OverloadableAttr>(Context);
break;
}
@ -451,7 +464,7 @@ unsigned FunctionDecl::getBuiltinID(ASTContext &Context) const {
if (isa<LinkageSpecDecl>(getDeclContext()) &&
cast<LinkageSpecDecl>(getDeclContext())->getLanguage()
== LinkageSpecDecl::lang_c &&
!getAttr<OverloadableAttr>())
!getAttr<OverloadableAttr>(Context))
return BuiltinID;
// Not a builtin
@ -480,6 +493,10 @@ void FunctionDecl::setParams(ASTContext& C, ParmVarDecl **NewParamInfo,
void *Mem = C.Allocate(sizeof(ParmVarDecl*)*NumParams);
ParamInfo = new (Mem) ParmVarDecl*[NumParams];
memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams);
// Update source range.
if (EndRangeLoc < NewParamInfo[NumParams-1]->getLocEnd())
EndRangeLoc = NewParamInfo[NumParams-1]->getLocEnd();
}
}
@ -496,25 +513,25 @@ unsigned FunctionDecl::getMinRequiredArguments() const {
return NumRequiredArgs;
}
bool FunctionDecl::hasActiveGNUInlineAttribute() const {
if (!isInline() || !hasAttr<GNUInlineAttr>())
bool FunctionDecl::hasActiveGNUInlineAttribute(ASTContext &Context) const {
if (!isInline() || !hasAttr<GNUInlineAttr>(Context))
return false;
for (const FunctionDecl *FD = getPreviousDeclaration(); FD;
FD = FD->getPreviousDeclaration()) {
if (FD->isInline() && !FD->hasAttr<GNUInlineAttr>())
if (FD->isInline() && !FD->hasAttr<GNUInlineAttr>(Context))
return false;
}
return true;
}
bool FunctionDecl::isExternGNUInline() const {
if (!hasActiveGNUInlineAttribute())
bool FunctionDecl::isExternGNUInline(ASTContext &Context) const {
if (!hasActiveGNUInlineAttribute(Context))
return false;
for (const FunctionDecl *FD = this; FD; FD = FD->getPreviousDeclaration())
if (FD->getStorageClass() == Extern && FD->hasAttr<GNUInlineAttr>())
if (FD->getStorageClass() == Extern && FD->hasAttr<GNUInlineAttr>(Context))
return true;
return false;

View File

@ -38,12 +38,6 @@ using namespace clang;
static bool StatSwitch = false;
// This keeps track of all decl attributes. Since so few decls have attrs, we
// keep them in a hash map instead of wasting space in the Decl class.
typedef llvm::DenseMap<const Decl*, Attr*> DeclAttrMapTy;
static DeclAttrMapTy *DeclAttrs = 0;
const char *Decl::getDeclKindName() const {
switch (DeclKind) {
default: assert(0 && "Declaration not in DeclNodes.def!");
@ -170,6 +164,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case ParmVar:
case OriginalParmVar:
case NonTypeTemplateParm:
case Using:
case ObjCMethod:
case ObjCContainer:
case ObjCCategory:
@ -224,11 +219,8 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
}
}
void Decl::addAttr(Attr *NewAttr) {
if (!DeclAttrs)
DeclAttrs = new DeclAttrMapTy();
Attr *&ExistingAttr = (*DeclAttrs)[this];
void Decl::addAttr(ASTContext &Context, Attr *NewAttr) {
Attr *&ExistingAttr = Context.getDeclAttrs(this);
NewAttr->setNext(ExistingAttr);
ExistingAttr = NewAttr;
@ -236,25 +228,19 @@ void Decl::addAttr(Attr *NewAttr) {
HasAttrs = true;
}
void Decl::invalidateAttrs() {
void Decl::invalidateAttrs(ASTContext &Context) {
if (!HasAttrs) return;
HasAttrs = false;
(*DeclAttrs)[this] = 0;
DeclAttrs->erase(this);
if (DeclAttrs->empty()) {
delete DeclAttrs;
DeclAttrs = 0;
}
Context.eraseDeclAttrs(this);
}
const Attr *Decl::getAttrsImpl() const {
const Attr *Decl::getAttrsImpl(ASTContext &Context) const {
assert(HasAttrs && "getAttrs() should verify this!");
return (*DeclAttrs)[this];
return Context.getDeclAttrs(this);
}
void Decl::swapAttrs(Decl *RHS) {
void Decl::swapAttrs(ASTContext &Context, Decl *RHS) {
bool HasLHSAttr = this->HasAttrs;
bool HasRHSAttr = RHS->HasAttrs;
@ -263,17 +249,17 @@ void Decl::swapAttrs(Decl *RHS) {
// If 'this' has no attrs, swap the other way.
if (!HasLHSAttr)
return RHS->swapAttrs(this);
return RHS->swapAttrs(Context, this);
// Handle the case when both decls have attrs.
if (HasRHSAttr) {
std::swap((*DeclAttrs)[this], (*DeclAttrs)[RHS]);
std::swap(Context.getDeclAttrs(this), Context.getDeclAttrs(RHS));
return;
}
// Otherwise, LHS has an attr and RHS doesn't.
(*DeclAttrs)[RHS] = (*DeclAttrs)[this];
(*DeclAttrs).erase(this);
Context.getDeclAttrs(RHS) = Context.getDeclAttrs(this);
Context.eraseDeclAttrs(this);
this->HasAttrs = false;
RHS->HasAttrs = true;
}
@ -282,12 +268,8 @@ void Decl::swapAttrs(Decl *RHS) {
void Decl::Destroy(ASTContext &C) {
// Free attributes for this decl.
if (HasAttrs) {
DeclAttrMapTy::iterator it = DeclAttrs->find(this);
assert(it != DeclAttrs->end() && "No attrs found but HasAttrs is true!");
// release attributes.
it->second->Destroy(C);
invalidateAttrs();
C.getDeclAttrs(this)->Destroy(C);
invalidateAttrs(C);
HasAttrs = false;
}

View File

@ -128,36 +128,33 @@ bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context) const {
void
CXXRecordDecl::addedConstructor(ASTContext &Context,
CXXConstructorDecl *ConDecl) {
if (!ConDecl->isImplicit()) {
// Note that we have a user-declared constructor.
UserDeclaredConstructor = true;
assert(!ConDecl->isImplicit() && "addedConstructor - not for implicit decl");
// Note that we have a user-declared constructor.
UserDeclaredConstructor = true;
// C++ [dcl.init.aggr]p1:
// An aggregate is an array or a class (clause 9) with no
// user-declared constructors (12.1) [...].
Aggregate = false;
// C++ [dcl.init.aggr]p1:
// An aggregate is an array or a class (clause 9) with no
// user-declared constructors (12.1) [...].
Aggregate = false;
// C++ [class]p4:
// A POD-struct is an aggregate class [...]
PlainOldData = false;
// C++ [class]p4:
// A POD-struct is an aggregate class [...]
PlainOldData = false;
// C++ [class.ctor]p5:
// A constructor is trivial if it is an implicitly-declared default
// constructor.
HasTrivialConstructor = false;
// C++ [class.ctor]p5:
// A constructor is trivial if it is an implicitly-declared default
// constructor.
HasTrivialConstructor = false;
// Note when we have a user-declared copy constructor, which will
// suppress the implicit declaration of a copy constructor.
if (ConDecl->isCopyConstructor(Context))
UserDeclaredCopyConstructor = true;
}
// Note when we have a user-declared copy constructor, which will
// suppress the implicit declaration of a copy constructor.
if (ConDecl->isCopyConstructor(Context))
UserDeclaredCopyConstructor = true;
}
void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context,
CXXMethodDecl *OpDecl) {
// We're interested specifically in copy assignment operators.
// Unlike addedConstructor, this method is not called for implicit
// declarations.
const FunctionProtoType *FnType = OpDecl->getType()->getAsFunctionProtoType();
assert(FnType && "Overloaded operator has no proto function type.");
assert(FnType->getNumArgs() == 1 && !FnType->isVariadic());
@ -187,10 +184,28 @@ void CXXRecordDecl::addConversionFunction(ASTContext &Context,
Conversions.addOverload(ConvDecl);
}
CXXConstructorDecl *
CXXRecordDecl::getDefaultConstructor(ASTContext &Context) {
QualType ClassType = Context.getTypeDeclType(this);
DeclarationName ConstructorName
= Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(ClassType.getUnqualifiedType()));
DeclContext::lookup_const_iterator Con, ConEnd;
for (llvm::tie(Con, ConEnd) = lookup(Context, ConstructorName);
Con != ConEnd; ++Con) {
CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
if (Constructor->isDefaultConstructor())
return Constructor;
}
return 0;
}
const CXXDestructorDecl *
CXXRecordDecl::getDestructor(ASTContext &Context) {
QualType ClassType = Context.getTypeDeclType(this);
DeclarationName Name
= Context.DeclarationNames.getCXXDestructorName(ClassType);
@ -428,6 +443,14 @@ NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
Qualifier, IdentLoc, Namespace);
}
UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L, SourceRange NNR, SourceLocation TargetNL,
SourceLocation UL, NamedDecl* Target,
NestedNameSpecifier* TargetNNS, bool IsTypeNameArg) {
return new (C) UsingDecl(DC, L, NNR, TargetNL, UL, Target,
TargetNNS, IsTypeNameArg);
}
StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L, Expr *AssertExpr,
StringLiteral *Message) {

View File

@ -190,7 +190,7 @@ TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L, unsigned D, unsigned P,
IdentifierInfo *Id, bool Typename,
bool ParameterPack) {
QualType Type = C.getTemplateTypeParmType(D, P, Id);
QualType Type = C.getTemplateTypeParmType(D, P, ParameterPack, Id);
return new (C) TemplateTypeParmDecl(DC, L, Id, Typename, Type, ParameterPack);
}
@ -238,6 +238,22 @@ TemplateArgument::TemplateArgument(Expr *E) : Kind(Expression) {
StartLoc = E->getSourceRange().getBegin();
}
/// \brief Construct a template argument pack.
TemplateArgument::TemplateArgument(SourceLocation Loc, TemplateArgument *args,
unsigned NumArgs, bool CopyArgs)
: Kind(Pack) {
Args.NumArgs = NumArgs;
Args.CopyArgs = CopyArgs;
if (!Args.CopyArgs) {
Args.Args = args;
return;
}
Args.Args = new TemplateArgument[NumArgs];
for (unsigned I = 0; I != NumArgs; ++I)
Args.Args[I] = args[I];
}
//===----------------------------------------------------------------------===//
// TemplateArgumentListBuilder Implementation
//===----------------------------------------------------------------------===//
@ -249,25 +265,28 @@ void TemplateArgumentListBuilder::push_back(const TemplateArgument& Arg) {
break;
}
if (!isAddingFromParameterPack()) {
// Add begin and end indicies.
Indices.push_back(Args.size());
Indices.push_back(Args.size());
}
Args.push_back(Arg);
FlatArgs.push_back(Arg);
if (!isAddingFromParameterPack())
StructuredArgs.push_back(Arg);
}
void TemplateArgumentListBuilder::BeginParameterPack() {
assert(!isAddingFromParameterPack() && "Already adding to parameter pack!");
Indices.push_back(Args.size());
PackBeginIndex = FlatArgs.size();
}
void TemplateArgumentListBuilder::EndParameterPack() {
assert(isAddingFromParameterPack() && "Not adding to parameter pack!");
unsigned NumArgs = FlatArgs.size() - PackBeginIndex;
TemplateArgument *Args = NumArgs ? &FlatArgs[PackBeginIndex] : 0;
Indices.push_back(Args.size());
StructuredArgs.push_back(TemplateArgument(SourceLocation(), Args, NumArgs,
/*CopyArgs=*/false));
PackBeginIndex = std::numeric_limits<unsigned>::max();
}
//===----------------------------------------------------------------------===//

View File

@ -456,7 +456,7 @@ Stmt *BlockExpr::getBody() {
/// with location to warn on and the source range[s] to report with the
/// warning.
bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
SourceRange &R2) const {
SourceRange &R2, ASTContext &Context) const {
// Don't warn if the expr is type dependent. The type could end up
// instantiating to void.
if (isTypeDependent())
@ -469,7 +469,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
return true;
case ParenExprClass:
return cast<ParenExpr>(this)->getSubExpr()->
isUnusedResultAWarning(Loc, R1, R2);
isUnusedResultAWarning(Loc, R1, R2, Context);
case UnaryOperatorClass: {
const UnaryOperator *UO = cast<UnaryOperator>(this);
@ -492,7 +492,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
return false;
break;
case UnaryOperator::Extension:
return UO->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
return UO->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Context);
}
Loc = UO->getOperatorLoc();
R1 = UO->getSubExpr()->getSourceRange();
@ -502,8 +502,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
const BinaryOperator *BO = cast<BinaryOperator>(this);
// Consider comma to have side effects if the LHS or RHS does.
if (BO->getOpcode() == BinaryOperator::Comma)
return BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2) ||
BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2);
return BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Context) ||
BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Context);
if (BO->isAssignmentOp())
return false;
@ -519,9 +519,10 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
// The condition must be evaluated, but if either the LHS or RHS is a
// warning, warn about them.
const ConditionalOperator *Exp = cast<ConditionalOperator>(this);
if (Exp->getLHS() && Exp->getLHS()->isUnusedResultAWarning(Loc, R1, R2))
if (Exp->getLHS() &&
Exp->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Context))
return true;
return Exp->getRHS()->isUnusedResultAWarning(Loc, R1, R2);
return Exp->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Context);
}
case MemberExprClass:
@ -554,8 +555,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
// If the callee has attribute pure, const, or warn_unused_result, warn
// about it. void foo() { strlen("bar"); } should warn.
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeDRE->getDecl()))
if (FD->getAttr<WarnUnusedResultAttr>() ||
FD->getAttr<PureAttr>() || FD->getAttr<ConstAttr>()) {
if (FD->getAttr<WarnUnusedResultAttr>(Context) ||
FD->getAttr<PureAttr>(Context) || FD->getAttr<ConstAttr>(Context)) {
Loc = CE->getCallee()->getLocStart();
R1 = CE->getCallee()->getSourceRange();
@ -578,7 +579,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
const CompoundStmt *CS = cast<StmtExpr>(this)->getSubStmt();
if (!CS->body_empty())
if (const Expr *E = dyn_cast<Expr>(CS->body_back()))
return E->isUnusedResultAWarning(Loc, R1, R2);
return E->isUnusedResultAWarning(Loc, R1, R2, Context);
Loc = cast<StmtExpr>(this)->getLParenLoc();
R1 = getSourceRange();
@ -588,8 +589,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
// If this is a cast to void, check the operand. Otherwise, the result of
// the cast is unused.
if (getType()->isVoidType())
return cast<CastExpr>(this)->getSubExpr()->isUnusedResultAWarning(Loc,
R1, R2);
return cast<CastExpr>(this)->getSubExpr()
->isUnusedResultAWarning(Loc, R1, R2, Context);
Loc = cast<CStyleCastExpr>(this)->getLParenLoc();
R1 = cast<CStyleCastExpr>(this)->getSubExpr()->getSourceRange();
return true;
@ -597,8 +598,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
// If this is a cast to void, check the operand. Otherwise, the result of
// the cast is unused.
if (getType()->isVoidType())
return cast<CastExpr>(this)->getSubExpr()->isUnusedResultAWarning(Loc,
R1, R2);
return cast<CastExpr>(this)->getSubExpr()
->isUnusedResultAWarning(Loc, R1, R2, Context);
Loc = cast<CXXFunctionalCastExpr>(this)->getTypeBeginLoc();
R1 = cast<CXXFunctionalCastExpr>(this)->getSubExpr()->getSourceRange();
return true;
@ -606,11 +607,11 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
case ImplicitCastExprClass:
// Check the operand, since implicit casts are inserted by Sema
return cast<ImplicitCastExpr>(this)
->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Context);
case CXXDefaultArgExprClass:
return cast<CXXDefaultArgExpr>(this)
->getExpr()->isUnusedResultAWarning(Loc, R1, R2);
->getExpr()->isUnusedResultAWarning(Loc, R1, R2, Context);
case CXXNewExprClass:
// FIXME: In theory, there might be new expressions that don't have side
@ -619,7 +620,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
return false;
case CXXExprWithTemporariesClass:
return cast<CXXExprWithTemporaries>(this)
->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Context);
}
}
@ -1570,7 +1571,7 @@ ObjCSelectorExpr *ObjCSelectorExpr::Clone(ASTContext &C) const {
}
ObjCProtocolExpr *ObjCProtocolExpr::Clone(ASTContext &C) const {
return new (C) ObjCProtocolExpr(getType(), Protocol, AtLoc, RParenLoc);
return new (C) ObjCProtocolExpr(getType(), TheProtocol, AtLoc, RParenLoc);
}
// constructor for class messages.

View File

@ -306,10 +306,11 @@ void CXXConstructExpr::Destroy(ASTContext &C) {
CXXExprWithTemporaries::CXXExprWithTemporaries(Expr *subexpr,
CXXTemporary **temps,
unsigned numtemps,
bool destroytemps)
bool shoulddestroytemps)
: Expr(CXXExprWithTemporariesClass, subexpr->getType(),
subexpr->isTypeDependent(), subexpr->isValueDependent()),
SubExpr(subexpr), Temps(0), NumTemps(numtemps), DestroyTemps(destroytemps) {
SubExpr(subexpr), Temps(0), NumTemps(numtemps),
ShouldDestroyTemps(shoulddestroytemps) {
if (NumTemps > 0) {
Temps = new CXXTemporary*[NumTemps];
for (unsigned i = 0; i < NumTemps; ++i)
@ -321,9 +322,9 @@ CXXExprWithTemporaries *CXXExprWithTemporaries::Create(ASTContext &C,
Expr *SubExpr,
CXXTemporary **Temps,
unsigned NumTemps,
bool DestroyTemps) {
bool ShouldDestroyTemps){
return new (C) CXXExprWithTemporaries(SubExpr, Temps, NumTemps,
DestroyTemps);
ShouldDestroyTemps);
}
void CXXExprWithTemporaries::Destroy(ASTContext &C) {

View File

@ -643,7 +643,8 @@ void StmtPrinter::VisitUnaryOperator(UnaryOperator *Node) {
if (!Node->isPostfix()) {
OS << UnaryOperator::getOpcodeStr(Node->getOpcode());
// Print a space if this is an "identifier operator" like __real.
// Print a space if this is an "identifier operator" like __real, or if
// it might be concatenated incorrectly like '+'.
switch (Node->getOpcode()) {
default: break;
case UnaryOperator::Real:
@ -651,6 +652,11 @@ void StmtPrinter::VisitUnaryOperator(UnaryOperator *Node) {
case UnaryOperator::Extension:
OS << ' ';
break;
case UnaryOperator::Plus:
case UnaryOperator::Minus:
if (isa<UnaryOperator>(Node->getSubExpr()))
OS << ' ';
break;
}
}
PrintExpr(Node->getSubExpr());

View File

@ -50,6 +50,13 @@ void DependentSizedArrayType::Destroy(ASTContext& C) {
C.Deallocate(this);
}
void DependentSizedExtVectorType::Destroy(ASTContext& C) {
if (SizeExpr)
SizeExpr->Destroy(C);
this->~DependentSizedExtVectorType();
C.Deallocate(this);
}
/// getArrayElementTypeNoTypeQual - If this is an array type, return the
/// element type of the array, potentially with type qualifiers missing.
/// This method should never be used when type qualifiers are meaningful.
@ -555,6 +562,12 @@ const ObjCInterfaceType *Type::getAsObjCInterfaceType() const {
return dyn_cast<ObjCInterfaceType>(CanonicalType.getUnqualifiedType());
}
const ObjCObjectPointerType *Type::getAsObjCObjectPointerType() const {
// There is no sugar for ObjCObjectPointerType's, just return the
// canonical type pointer if it is the right class.
return dyn_cast<ObjCObjectPointerType>(CanonicalType.getUnqualifiedType());
}
const ObjCQualifiedInterfaceType *
Type::getAsObjCQualifiedInterfaceType() const {
// There is no sugar for ObjCQualifiedInterfaceType's, just return the
@ -562,10 +575,14 @@ Type::getAsObjCQualifiedInterfaceType() const {
return dyn_cast<ObjCQualifiedInterfaceType>(CanonicalType.getUnqualifiedType());
}
const ObjCQualifiedIdType *Type::getAsObjCQualifiedIdType() const {
const ObjCObjectPointerType *Type::getAsObjCQualifiedIdType() const {
// There is no sugar for ObjCQualifiedIdType's, just return the canonical
// type pointer if it is the right class.
return dyn_cast<ObjCQualifiedIdType>(CanonicalType.getUnqualifiedType());
if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType()) {
if (OPT->isObjCQualifiedIdType())
return OPT;
}
return 0;
}
const TemplateTypeParmType *Type::getAsTemplateTypeParmType() const {
@ -770,7 +787,7 @@ bool Type::isScalarType() const {
isa<BlockPointerType>(CanonicalType) ||
isa<MemberPointerType>(CanonicalType) ||
isa<ComplexType>(CanonicalType) ||
isa<ObjCQualifiedIdType>(CanonicalType);
isa<ObjCObjectPointerType>(CanonicalType);
}
/// \brief Determines whether the type is a C++ aggregate type or C
@ -857,7 +874,7 @@ bool Type::isPODType() const {
case MemberPointer:
case Vector:
case ExtVector:
case ObjCQualifiedId:
case ObjCObjectPointer:
return true;
case Enum:
@ -912,7 +929,7 @@ bool Type::isSpecifierType() const {
case Typename:
case ObjCInterface:
case ObjCQualifiedInterface:
case ObjCQualifiedId:
case ObjCObjectPointer:
return true;
default:
return false;
@ -973,6 +990,19 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID) {
getNumExceptions(), exception_begin());
}
void ObjCObjectPointerType::Profile(llvm::FoldingSetNodeID &ID,
const ObjCInterfaceDecl *Decl,
ObjCProtocolDecl **protocols,
unsigned NumProtocols) {
ID.AddPointer(Decl);
for (unsigned i = 0; i != NumProtocols; i++)
ID.AddPointer(protocols[i]);
}
void ObjCObjectPointerType::Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getDecl(), &Protocols[0], getNumProtocols());
}
void ObjCQualifiedInterfaceType::Profile(llvm::FoldingSetNodeID &ID,
const ObjCInterfaceDecl *Decl,
ObjCProtocolDecl **protocols,
@ -986,17 +1016,6 @@ void ObjCQualifiedInterfaceType::Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getDecl(), &Protocols[0], getNumProtocols());
}
void ObjCQualifiedIdType::Profile(llvm::FoldingSetNodeID &ID,
ObjCProtocolDecl **protocols,
unsigned NumProtocols) {
for (unsigned i = 0; i != NumProtocols; i++)
ID.AddPointer(protocols[i]);
}
void ObjCQualifiedIdType::Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, &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:
@ -1068,6 +1087,10 @@ anyDependentTemplateArguments(const TemplateArgument *Args, unsigned NumArgs) {
Args[Idx].getAsExpr()->isValueDependent())
return true;
break;
case TemplateArgument::Pack:
assert(0 && "FIXME: Implement!");
break;
}
}
@ -1352,6 +1375,19 @@ void DependentSizedArrayType::getAsStringInternal(std::string &S, const Printing
getElementType().getAsStringInternal(S, Policy);
}
void DependentSizedExtVectorType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
getElementType().getAsStringInternal(S, Policy);
S += " __attribute__((ext_vector_type(";
if (getSizeExpr()) {
std::string SStr;
llvm::raw_string_ostream s(SStr);
getSizeExpr()->printPretty(s, 0, Policy);
S += s.str();
}
S += ")))";
}
void VectorType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
// FIXME: We prefer to print the size directly here, but have no way
// to get the size of the type.
@ -1476,6 +1512,9 @@ TemplateSpecializationType::PrintTemplateArgumentList(
Args[Arg].getAsExpr()->printPretty(s, 0, Policy);
break;
}
case TemplateArgument::Pack:
assert(0 && "FIXME: Implement!");
break;
}
// If this is the first argument and its string representation
@ -1566,6 +1605,30 @@ void ObjCInterfaceType::getAsStringInternal(std::string &InnerString, const Prin
InnerString = getDecl()->getIdentifier()->getName() + InnerString;
}
void ObjCObjectPointerType::getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const {
if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
InnerString = ' ' + InnerString;
std::string ObjCQIString;
if (getDecl())
ObjCQIString = getDecl()->getNameAsString();
else
ObjCQIString = "id";
if (!qual_empty()) {
ObjCQIString += '<';
for (qual_iterator I = qual_begin(), E = qual_end(); I != E; ++I) {
ObjCQIString += (*I)->getNameAsString();
if (I+1 != E)
ObjCQIString += ',';
}
ObjCQIString += '>';
}
InnerString = ObjCQIString + InnerString;
}
void
ObjCQualifiedInterfaceType::getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const {
@ -1585,20 +1648,6 @@ ObjCQualifiedInterfaceType::getAsStringInternal(std::string &InnerString,
InnerString = ObjCQIString + InnerString;
}
void ObjCQualifiedIdType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
InnerString = ' ' + InnerString;
std::string ObjCQIString = "id";
ObjCQIString += '<';
for (qual_iterator I = qual_begin(), E = qual_end(); I != E; ++I) {
ObjCQIString += (*I)->getNameAsString();
if (I+1 != E)
ObjCQIString += ',';
}
ObjCQIString += '>';
InnerString = ObjCQIString + InnerString;
}
void TagType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
if (Policy.SuppressTag)
return;

View File

@ -51,39 +51,39 @@ class VISIBILITY_HIDDEN BasicConstraintManager
GRState::IntSetTy::Factory ISetFactory;
public:
BasicConstraintManager(GRStateManager& statemgr)
: SimpleConstraintManager(statemgr), ISetFactory(statemgr.getAllocator()) {}
: ISetFactory(statemgr.getAllocator()) {}
const GRState* AssumeSymNE(const GRState* St, SymbolRef sym,
const llvm::APSInt& V, bool& isFeasible);
const GRState* AssumeSymNE(const GRState* state, SymbolRef sym,
const llvm::APSInt& V);
const GRState* AssumeSymEQ(const GRState* St, SymbolRef sym,
const llvm::APSInt& V, bool& isFeasible);
const GRState* AssumeSymEQ(const GRState* state, SymbolRef sym,
const llvm::APSInt& V);
const GRState* AssumeSymLT(const GRState* St, SymbolRef sym,
const llvm::APSInt& V, bool& isFeasible);
const GRState* AssumeSymLT(const GRState* state, SymbolRef sym,
const llvm::APSInt& V);
const GRState* AssumeSymGT(const GRState* St, SymbolRef sym,
const llvm::APSInt& V, bool& isFeasible);
const GRState* AssumeSymGT(const GRState* state, SymbolRef sym,
const llvm::APSInt& V);
const GRState* AssumeSymGE(const GRState* St, SymbolRef sym,
const llvm::APSInt& V, bool& isFeasible);
const GRState* AssumeSymGE(const GRState* state, SymbolRef sym,
const llvm::APSInt& V);
const GRState* AssumeSymLE(const GRState* St, SymbolRef sym,
const llvm::APSInt& V, bool& isFeasible);
const GRState* AssumeSymLE(const GRState* state, SymbolRef sym,
const llvm::APSInt& V);
const GRState* AddEQ(const GRState* St, SymbolRef sym, const llvm::APSInt& V);
const GRState* AddEQ(const GRState* state, SymbolRef sym, const llvm::APSInt& V);
const GRState* AddNE(const GRState* St, SymbolRef sym, const llvm::APSInt& V);
const GRState* AddNE(const GRState* state, SymbolRef sym, const llvm::APSInt& V);
const llvm::APSInt* getSymVal(const GRState* St, SymbolRef sym) const;
bool isNotEqual(const GRState* St, SymbolRef sym, const llvm::APSInt& V)
const llvm::APSInt* getSymVal(const GRState* state, SymbolRef sym) const;
bool isNotEqual(const GRState* state, SymbolRef sym, const llvm::APSInt& V)
const;
bool isEqual(const GRState* St, SymbolRef sym, const llvm::APSInt& V)
bool isEqual(const GRState* state, SymbolRef sym, const llvm::APSInt& V)
const;
const GRState* RemoveDeadBindings(const GRState* St, SymbolReaper& SymReaper);
const GRState* RemoveDeadBindings(const GRState* state, SymbolReaper& SymReaper);
void print(const GRState* St, std::ostream& Out,
void print(const GRState* state, std::ostream& Out,
const char* nl, const char *sep);
};
@ -95,87 +95,77 @@ ConstraintManager* clang::CreateBasicConstraintManager(GRStateManager& StateMgr)
}
const GRState*
BasicConstraintManager::AssumeSymNE(const GRState* St, SymbolRef sym,
const llvm::APSInt& V, bool& isFeasible) {
BasicConstraintManager::AssumeSymNE(const GRState *state, SymbolRef sym,
const llvm::APSInt& V) {
// First, determine if sym == X, where X != V.
if (const llvm::APSInt* X = getSymVal(St, sym)) {
isFeasible = (*X != V);
return St;
if (const llvm::APSInt* X = getSymVal(state, sym)) {
bool isFeasible = (*X != V);
return isFeasible ? state : NULL;
}
// Second, determine if sym != V.
if (isNotEqual(St, sym, V)) {
isFeasible = true;
return St;
}
if (isNotEqual(state, sym, V))
return state;
// If we reach here, sym is not a constant and we don't know if it is != V.
// Make that assumption.
isFeasible = true;
return AddNE(St, sym, V);
return AddNE(state, sym, V);
}
const GRState*
BasicConstraintManager::AssumeSymEQ(const GRState* St, SymbolRef sym,
const llvm::APSInt& V, bool& isFeasible) {
const GRState *BasicConstraintManager::AssumeSymEQ(const GRState *state,
SymbolRef sym,
const llvm::APSInt &V) {
// First, determine if sym == X, where X != V.
if (const llvm::APSInt* X = getSymVal(St, sym)) {
isFeasible = *X == V;
return St;
if (const llvm::APSInt* X = getSymVal(state, sym)) {
bool isFeasible = *X == V;
return isFeasible ? state : NULL;
}
// Second, determine if sym != V.
if (isNotEqual(St, sym, V)) {
isFeasible = false;
return St;
}
if (isNotEqual(state, sym, V))
return NULL;
// If we reach here, sym is not a constant and we don't know if it is == V.
// Make that assumption.
isFeasible = true;
return AddEQ(St, sym, V);
return AddEQ(state, sym, V);
}
// These logic will be handled in another ConstraintManager.
const GRState*
BasicConstraintManager::AssumeSymLT(const GRState* St, SymbolRef sym,
const llvm::APSInt& V, bool& isFeasible) {
const GRState *BasicConstraintManager::AssumeSymLT(const GRState *state,
SymbolRef sym,
const llvm::APSInt& V) {
// Is 'V' the smallest possible value?
if (V == llvm::APSInt::getMinValue(V.getBitWidth(), V.isUnsigned())) {
// sym cannot be any value less than 'V'. This path is infeasible.
isFeasible = false;
return St;
return NULL;
}
// FIXME: For now have assuming x < y be the same as assuming sym != V;
return AssumeSymNE(St, sym, V, isFeasible);
return AssumeSymNE(state, sym, V);
}
const GRState*
BasicConstraintManager::AssumeSymGT(const GRState* St, SymbolRef sym,
const llvm::APSInt& V, bool& isFeasible) {
const GRState *BasicConstraintManager::AssumeSymGT(const GRState *state,
SymbolRef sym,
const llvm::APSInt& V) {
// Is 'V' the largest possible value?
if (V == llvm::APSInt::getMaxValue(V.getBitWidth(), V.isUnsigned())) {
// sym cannot be any value greater than 'V'. This path is infeasible.
isFeasible = false;
return St;
return NULL;
}
// FIXME: For now have assuming x > y be the same as assuming sym != V;
return AssumeSymNE(St, sym, V, isFeasible);
return AssumeSymNE(state, sym, V);
}
const GRState*
BasicConstraintManager::AssumeSymGE(const GRState* St, SymbolRef sym,
const llvm::APSInt& V, bool& isFeasible) {
const GRState *BasicConstraintManager::AssumeSymGE(const GRState *state,
SymbolRef sym,
const llvm::APSInt &V) {
// Reject a path if the value of sym is a constant X and !(X >= V).
if (const llvm::APSInt* X = getSymVal(St, sym)) {
isFeasible = *X >= V;
return St;
if (const llvm::APSInt *X = getSymVal(state, sym)) {
bool isFeasible = *X >= V;
return isFeasible ? state : NULL;
}
// Sym is not a constant, but it is worth looking to see if V is the
@ -183,28 +173,25 @@ BasicConstraintManager::AssumeSymGE(const GRState* St, SymbolRef sym,
if (V == llvm::APSInt::getMaxValue(V.getBitWidth(), V.isUnsigned())) {
// If we know that sym != V, then this condition is infeasible since
// there is no other value greater than V.
isFeasible = !isNotEqual(St, sym, V);
bool isFeasible = !isNotEqual(state, sym, V);
// If the path is still feasible then as a consequence we know that
// 'sym == V' because we cannot have 'sym > V' (no larger values).
// Add this constraint.
if (isFeasible)
return AddEQ(St, sym, V);
return isFeasible ? AddEQ(state, sym, V) : NULL;
}
else
isFeasible = true;
return St;
return state;
}
const GRState*
BasicConstraintManager::AssumeSymLE(const GRState* St, SymbolRef sym,
const llvm::APSInt& V, bool& isFeasible) {
BasicConstraintManager::AssumeSymLE(const GRState* state, SymbolRef sym,
const llvm::APSInt& V) {
// Reject a path if the value of sym is a constant X and !(X <= V).
if (const llvm::APSInt* X = getSymVal(St, sym)) {
isFeasible = *X <= V;
return St;
if (const llvm::APSInt* X = getSymVal(state, sym)) {
bool isFeasible = *X <= V;
return isFeasible ? state : NULL;
}
// Sym is not a constant, but it is worth looking to see if V is the
@ -212,64 +199,57 @@ BasicConstraintManager::AssumeSymLE(const GRState* St, SymbolRef sym,
if (V == llvm::APSInt::getMinValue(V.getBitWidth(), V.isUnsigned())) {
// If we know that sym != V, then this condition is infeasible since
// there is no other value less than V.
isFeasible = !isNotEqual(St, sym, V);
bool isFeasible = !isNotEqual(state, sym, V);
// If the path is still feasible then as a consequence we know that
// 'sym == V' because we cannot have 'sym < V' (no smaller values).
// Add this constraint.
if (isFeasible)
return AddEQ(St, sym, V);
return isFeasible ? AddEQ(state, sym, V) : NULL;
}
else
isFeasible = true;
return St;
return state;
}
const GRState* BasicConstraintManager::AddEQ(const GRState* St, SymbolRef sym,
const GRState* BasicConstraintManager::AddEQ(const GRState* state, SymbolRef sym,
const llvm::APSInt& V) {
// Create a new state with the old binding replaced.
GRStateRef state(St, StateMgr);
return state.set<ConstEq>(sym, &V);
return state->set<ConstEq>(sym, &V);
}
const GRState* BasicConstraintManager::AddNE(const GRState* St, SymbolRef sym,
const GRState* BasicConstraintManager::AddNE(const GRState* state, SymbolRef sym,
const llvm::APSInt& V) {
GRStateRef state(St, StateMgr);
// First, retrieve the NE-set associated with the given symbol.
ConstNotEqTy::data_type* T = state.get<ConstNotEq>(sym);
ConstNotEqTy::data_type* T = state->get<ConstNotEq>(sym);
GRState::IntSetTy S = T ? *T : ISetFactory.GetEmptySet();
// Now add V to the NE set.
S = ISetFactory.Add(S, &V);
// Create a new state with the old binding replaced.
return state.set<ConstNotEq>(sym, S);
return state->set<ConstNotEq>(sym, S);
}
const llvm::APSInt* BasicConstraintManager::getSymVal(const GRState* St,
const llvm::APSInt* BasicConstraintManager::getSymVal(const GRState* state,
SymbolRef sym) const {
const ConstEqTy::data_type* T = St->get<ConstEq>(sym);
const ConstEqTy::data_type* T = state->get<ConstEq>(sym);
return T ? *T : NULL;
}
bool BasicConstraintManager::isNotEqual(const GRState* St, SymbolRef sym,
bool BasicConstraintManager::isNotEqual(const GRState* state, SymbolRef sym,
const llvm::APSInt& V) const {
// Retrieve the NE-set associated with the given symbol.
const ConstNotEqTy::data_type* T = St->get<ConstNotEq>(sym);
const ConstNotEqTy::data_type* T = state->get<ConstNotEq>(sym);
// See if V is present in the NE-set.
return T ? T->contains(&V) : false;
}
bool BasicConstraintManager::isEqual(const GRState* St, SymbolRef sym,
bool BasicConstraintManager::isEqual(const GRState* state, SymbolRef sym,
const llvm::APSInt& V) const {
// Retrieve the EQ-set associated with the given symbol.
const ConstEqTy::data_type* T = St->get<ConstEq>(sym);
const ConstEqTy::data_type* T = state->get<ConstEq>(sym);
// See if V is present in the EQ-set.
return T ? **T == V : false;
}
@ -277,35 +257,34 @@ bool BasicConstraintManager::isEqual(const GRState* St, SymbolRef sym,
/// Scan all symbols referenced by the constraints. If the symbol is not alive
/// as marked in LSymbols, mark it as dead in DSymbols.
const GRState*
BasicConstraintManager::RemoveDeadBindings(const GRState* St,
BasicConstraintManager::RemoveDeadBindings(const GRState* state,
SymbolReaper& SymReaper) {
GRStateRef state(St, StateMgr);
ConstEqTy CE = state.get<ConstEq>();
ConstEqTy::Factory& CEFactory = state.get_context<ConstEq>();
ConstEqTy CE = state->get<ConstEq>();
ConstEqTy::Factory& CEFactory = state->get_context<ConstEq>();
for (ConstEqTy::iterator I = CE.begin(), E = CE.end(); I!=E; ++I) {
SymbolRef sym = I.getKey();
if (SymReaper.maybeDead(sym)) CE = CEFactory.Remove(CE, sym);
}
state = state.set<ConstEq>(CE);
state = state->set<ConstEq>(CE);
ConstNotEqTy CNE = state.get<ConstNotEq>();
ConstNotEqTy::Factory& CNEFactory = state.get_context<ConstNotEq>();
ConstNotEqTy CNE = state->get<ConstNotEq>();
ConstNotEqTy::Factory& CNEFactory = state->get_context<ConstNotEq>();
for (ConstNotEqTy::iterator I = CNE.begin(), E = CNE.end(); I != E; ++I) {
SymbolRef sym = I.getKey();
if (SymReaper.maybeDead(sym)) CNE = CNEFactory.Remove(CNE, sym);
}
return state.set<ConstNotEq>(CNE);
return state->set<ConstNotEq>(CNE);
}
void BasicConstraintManager::print(const GRState* St, std::ostream& Out,
void BasicConstraintManager::print(const GRState* state, std::ostream& Out,
const char* nl, const char *sep) {
// Print equality constraints.
ConstEqTy CE = St->get<ConstEq>();
ConstEqTy CE = state->get<ConstEq>();
if (!CE.isEmpty()) {
Out << nl << sep << "'==' constraints:";
@ -319,7 +298,7 @@ void BasicConstraintManager::print(const GRState* St, std::ostream& Out,
// Print != constraints.
ConstNotEqTy CNE = St->get<ConstNotEq>();
ConstNotEqTy CNE = state->get<ConstNotEq>();
if (!CNE.isEmpty()) {
Out << nl << sep << "'!=' constraints:";

View File

@ -66,9 +66,6 @@ class VISIBILITY_HIDDEN BasicObjCFoundationChecks : public GRSimpleAPICheck {
APIMisuse *BT;
BugReporter& BR;
ASTContext &Ctx;
GRStateManager* VMgr;
SVal GetSVal(const GRState* St, Expr* E) { return VMgr->GetSVal(St, E); }
bool isNSString(ObjCInterfaceType* T, const char* suffix);
bool AuditNSString(NodeTy* N, ObjCMessageExpr* ME);
@ -79,9 +76,8 @@ class VISIBILITY_HIDDEN BasicObjCFoundationChecks : public GRSimpleAPICheck {
bool CheckNilArg(NodeTy* N, unsigned Arg);
public:
BasicObjCFoundationChecks(ASTContext& ctx, GRStateManager* vmgr,
BugReporter& br)
: BT(0), BR(br), Ctx(ctx), VMgr(vmgr) {}
BasicObjCFoundationChecks(ASTContext& ctx, BugReporter& br)
: BT(0), BR(br), Ctx(ctx) {}
bool Audit(ExplodedNode<GRState>* N, GRStateManager&);
@ -106,10 +102,8 @@ class VISIBILITY_HIDDEN BasicObjCFoundationChecks : public GRSimpleAPICheck {
GRSimpleAPICheck*
clang::CreateBasicObjCFoundationChecks(ASTContext& Ctx,
GRStateManager* VMgr, BugReporter& BR) {
return new BasicObjCFoundationChecks(Ctx, VMgr, BR);
clang::CreateBasicObjCFoundationChecks(ASTContext& Ctx, BugReporter& BR) {
return new BasicObjCFoundationChecks(Ctx, BR);
}
@ -157,7 +151,7 @@ bool BasicObjCFoundationChecks::CheckNilArg(NodeTy* N, unsigned Arg) {
Expr * E = ME->getArg(Arg);
if (isNil(GetSVal(N->getState(), E))) {
if (isNil(N->getState()->getSVal(E))) {
WarnNilArg(N, ME, Arg);
return true;
}
@ -259,14 +253,11 @@ class VISIBILITY_HIDDEN AuditCFNumberCreate : public GRSimpleAPICheck {
// approach makes this class more stateless.
ASTContext& Ctx;
IdentifierInfo* II;
GRStateManager* VMgr;
BugReporter& BR;
SVal GetSVal(const GRState* St, Expr* E) { return VMgr->GetSVal(St, E); }
public:
AuditCFNumberCreate(ASTContext& ctx, GRStateManager* vmgr, BugReporter& br)
: BT(0), Ctx(ctx), II(&Ctx.Idents.get("CFNumberCreate")), VMgr(vmgr), BR(br){}
AuditCFNumberCreate(ASTContext& ctx, BugReporter& br)
: BT(0), Ctx(ctx), II(&Ctx.Idents.get("CFNumberCreate")), BR(br){}
~AuditCFNumberCreate() {}
@ -374,14 +365,14 @@ static const char* GetCFNumberTypeStr(uint64_t i) {
bool AuditCFNumberCreate::Audit(ExplodedNode<GRState>* N,GRStateManager&){
CallExpr* CE = cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt());
Expr* Callee = CE->getCallee();
SVal CallV = GetSVal(N->getState(), Callee);
SVal CallV = N->getState()->getSVal(Callee);
const FunctionDecl* FD = CallV.getAsFunctionDecl();
if (!FD || FD->getIdentifier() != II || CE->getNumArgs()!=3)
return false;
// Get the value of the "theType" argument.
SVal TheTypeVal = GetSVal(N->getState(), CE->getArg(1));
SVal TheTypeVal = N->getState()->getSVal(CE->getArg(1));
// FIXME: We really should allow ranges of valid theType values, and
// bifurcate the state appropriately.
@ -400,7 +391,7 @@ bool AuditCFNumberCreate::Audit(ExplodedNode<GRState>* N,GRStateManager&){
// Look at the value of the integer being passed by reference. Essentially
// we want to catch cases where the value passed in is not equal to the
// size of the type being created.
SVal TheValueExpr = GetSVal(N->getState(), CE->getArg(2));
SVal TheValueExpr = N->getState()->getSVal(CE->getArg(2));
// FIXME: Eventually we should handle arbitrary locations. We can do this
// by having an enhanced memory model that does low-level typing.
@ -469,9 +460,8 @@ void AuditCFNumberCreate::AddError(const TypedRegion* R, Expr* Ex,
}
GRSimpleAPICheck*
clang::CreateAuditCFNumberCreate(ASTContext& Ctx,
GRStateManager* VMgr, BugReporter& BR) {
return new AuditCFNumberCreate(Ctx, VMgr, BR);
clang::CreateAuditCFNumberCreate(ASTContext& Ctx, BugReporter& BR) {
return new AuditCFNumberCreate(Ctx, BR);
}
//===----------------------------------------------------------------------===//
@ -479,13 +469,12 @@ clang::CreateAuditCFNumberCreate(ASTContext& Ctx,
void clang::RegisterAppleChecks(GRExprEngine& Eng) {
ASTContext& Ctx = Eng.getContext();
GRStateManager* VMgr = &Eng.getStateManager();
BugReporter &BR = Eng.getBugReporter();
Eng.AddCheck(CreateBasicObjCFoundationChecks(Ctx, VMgr, BR),
Eng.AddCheck(CreateBasicObjCFoundationChecks(Ctx, BR),
Stmt::ObjCMessageExprClass);
Eng.AddCheck(CreateAuditCFNumberCreate(Ctx, VMgr, BR),
Eng.AddCheck(CreateAuditCFNumberCreate(Ctx, BR),
Stmt::CallExprClass);
RegisterNSErrorChecks(BR, Eng);

View File

@ -33,11 +33,9 @@ class BugReporter;
class GRExprEngine;
GRSimpleAPICheck* CreateBasicObjCFoundationChecks(ASTContext& Ctx,
GRStateManager* VMgr,
BugReporter& BR);
GRSimpleAPICheck* CreateAuditCFNumberCreate(ASTContext& Ctx,
GRStateManager* VMgr,
BugReporter& BR);
void RegisterNSErrorChecks(BugReporter& BR, GRExprEngine &Eng);

View File

@ -45,15 +45,14 @@ class VISIBILITY_HIDDEN BasicStoreManager : public StoreManager {
~BasicStoreManager() {}
SubRegionMap* getSubRegionMap(const GRState *state) {
SubRegionMap *getSubRegionMap(const GRState *state) {
return new BasicStoreSubRegionMap();
}
SVal Retrieve(const GRState *state, Loc loc, QualType T = QualType());
const GRState* Bind(const GRState* St, Loc L, SVal V) {
Store store = BindInternal(St->getStore(), L, V);
return StateMgr.MakeStateWithStore(St, store);
const GRState *Bind(const GRState *state, Loc L, SVal V) {
return state->makeWithStore(BindInternal(state->getStore(), L, V));
}
Store scanForIvars(Stmt *B, const Decl* SelfDecl, Store St);
@ -67,19 +66,19 @@ class VISIBILITY_HIDDEN BasicStoreManager : public StoreManager {
return Loc::MakeVal(MRMgr.getVarRegion(VD));
}
const GRState* BindCompoundLiteral(const GRState* St,
const CompoundLiteralExpr* CL,
SVal V) {
return St;
const GRState *BindCompoundLiteral(const GRState *state,
const CompoundLiteralExpr* cl,
SVal val) {
return state;
}
SVal getLValueVar(const GRState* St, const VarDecl* VD);
SVal getLValueString(const GRState* St, const StringLiteral* S);
SVal getLValueCompoundLiteral(const GRState* St,
SVal getLValueVar(const GRState *state, const VarDecl* VD);
SVal getLValueString(const GRState *state, const StringLiteral* S);
SVal getLValueCompoundLiteral(const GRState *state,
const CompoundLiteralExpr* CL);
SVal getLValueIvar(const GRState* St, const ObjCIvarDecl* D, SVal Base);
SVal getLValueField(const GRState* St, SVal Base, const FieldDecl* D);
SVal getLValueElement(const GRState* St, QualType elementType,
SVal getLValueIvar(const GRState *state, const ObjCIvarDecl* D, SVal Base);
SVal getLValueField(const GRState *state, SVal Base, const FieldDecl* D);
SVal getLValueElement(const GRState *state, QualType elementType,
SVal Base, SVal Offset);
/// ArrayToPointer - Used by GRExprEngine::VistCast to handle implicit
@ -92,23 +91,19 @@ class VISIBILITY_HIDDEN BasicStoreManager : public StoreManager {
const MemRegion* getSelfRegion(Store) { return SelfRegion; }
/// RemoveDeadBindings - Scans a BasicStore of 'state' for dead values.
/// It returns a new Store with these values removed, and populates LSymbols
/// and DSymbols with the known set of live and dead symbols respectively.
Store
RemoveDeadBindings(const GRState* state, Stmt* Loc,
/// It returns a new Store with these values removed.
Store RemoveDeadBindings(const GRState *state, Stmt* Loc,
SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots);
void iterBindings(Store store, BindingsHandler& f);
const GRState* BindDecl(const GRState* St, const VarDecl* VD, SVal InitVal) {
Store store = BindDeclInternal(St->getStore(), VD, &InitVal);
return StateMgr.MakeStateWithStore(St, store);
const GRState *BindDecl(const GRState *state, const VarDecl* VD, SVal InitVal) {
return state->makeWithStore(BindDeclInternal(state->getStore(),VD, &InitVal));
}
const GRState* BindDeclWithNoInit(const GRState* St, const VarDecl* VD) {
Store store = BindDeclInternal(St->getStore(), VD, 0);
return StateMgr.MakeStateWithStore(St, store);
const GRState *BindDeclWithNoInit(const GRState *state, const VarDecl* VD) {
return state->makeWithStore(BindDeclInternal(state->getStore(), VD, 0));
}
Store BindDeclInternal(Store store, const VarDecl* VD, SVal* InitVal);
@ -130,21 +125,21 @@ StoreManager* clang::CreateBasicStoreManager(GRStateManager& StMgr) {
return new BasicStoreManager(StMgr);
}
SVal BasicStoreManager::getLValueVar(const GRState* St, const VarDecl* VD) {
SVal BasicStoreManager::getLValueVar(const GRState *state, const VarDecl* VD) {
return Loc::MakeVal(MRMgr.getVarRegion(VD));
}
SVal BasicStoreManager::getLValueString(const GRState* St,
SVal BasicStoreManager::getLValueString(const GRState *state,
const StringLiteral* S) {
return Loc::MakeVal(MRMgr.getStringRegion(S));
}
SVal BasicStoreManager::getLValueCompoundLiteral(const GRState* St,
SVal BasicStoreManager::getLValueCompoundLiteral(const GRState *state,
const CompoundLiteralExpr* CL){
return Loc::MakeVal(MRMgr.getCompoundLiteralRegion(CL));
}
SVal BasicStoreManager::getLValueIvar(const GRState* St, const ObjCIvarDecl* D,
SVal BasicStoreManager::getLValueIvar(const GRState *state, const ObjCIvarDecl* D,
SVal Base) {
if (Base.isUnknownOrUndef())
@ -162,7 +157,7 @@ SVal BasicStoreManager::getLValueIvar(const GRState* St, const ObjCIvarDecl* D,
return UnknownVal();
}
SVal BasicStoreManager::getLValueField(const GRState* St, SVal Base,
SVal BasicStoreManager::getLValueField(const GRState *state, SVal Base,
const FieldDecl* D) {
if (Base.isUnknownOrUndef())
@ -194,7 +189,7 @@ SVal BasicStoreManager::getLValueField(const GRState* St, SVal Base,
return Loc::MakeVal(MRMgr.getFieldRegion(D, BaseR));
}
SVal BasicStoreManager::getLValueElement(const GRState* St,
SVal BasicStoreManager::getLValueElement(const GRState *state,
QualType elementType,
SVal Base, SVal Offset) {
@ -248,7 +243,7 @@ SVal BasicStoreManager::getLValueElement(const GRState* St,
if (BaseR)
return Loc::MakeVal(MRMgr.getElementRegion(elementType, UnknownVal(),
BaseR));
BaseR, getContext()));
else
return UnknownVal();
}
@ -274,7 +269,7 @@ static bool isHigherOrderRawPtr(QualType T, ASTContext &C) {
}
}
SVal BasicStoreManager::Retrieve(const GRState* state, Loc loc, QualType T) {
SVal BasicStoreManager::Retrieve(const GRState *state, Loc loc, QualType T) {
if (isa<UnknownVal>(loc))
return UnknownVal();
@ -390,7 +385,7 @@ Store BasicStoreManager::Remove(Store store, Loc loc) {
}
Store
BasicStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc,
BasicStoreManager::RemoveDeadBindings(const GRState *state, Stmt* Loc,
SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots)
{

View File

@ -336,7 +336,7 @@ GetMostRecentVarDeclBinding(const ExplodedNode<GRState>* N,
if (!DR)
continue;
SVal Y = VMgr.GetSVal(N->getState(), DR);
SVal Y = N->getState()->getSVal(DR);
if (X != Y)
continue;

View File

@ -971,8 +971,12 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
// FIXME: This should all be refactored into a chain of "summary lookup"
// filters.
assert (ScratchArgs.isEmpty());
switch (strlen(FName)) {
default: break;
case 17:
// Handle: id NSMakeCollectable(CFTypeRef)
if (!memcmp(FName, "NSMakeCollectable", 17)) {
@ -980,13 +984,55 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
? getUnarySummary(FT, cfmakecollectable)
: getPersistentStopSummary();
}
else if (!memcmp(FName, "IOBSDNameMatching", 17) ||
!memcmp(FName, "IOServiceMatching", 17)) {
// Part of <rdar://problem/6961230>. (IOKit)
// This should be addressed using a API table.
S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
DoNothing, DoNothing);
}
break;
case 21:
if (!memcmp(FName, "IOServiceNameMatching", 21)) {
// Part of <rdar://problem/6961230>. (IOKit)
// This should be addressed using a API table.
S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
DoNothing, DoNothing);
}
break;
case 24:
if (!memcmp(FName, "IOServiceAddNotification", 24)) {
// 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);
}
break;
case 25:
if (!memcmp(FName, "IORegistryEntryIDMatching", 25)) {
// Part of <rdar://problem/6961230>. (IOKit)
// This should be addressed using a API table.
S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
DoNothing, DoNothing);
}
break;
case 26:
if (!memcmp(FName, "IOOpenFirmwarePathMatching", 26)) {
// Part of <rdar://problem/6961230>. (IOKit)
// This should be addressed using a API table.
S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
DoNothing, DoNothing);
}
break;
case 27:
if (!memcmp(FName, "IOServiceGetMatchingService", 27)) {
// Part of <rdar://problem/6961230>.
// This should be addressed using a API table.
assert (ScratchArgs.isEmpty());
ScratchArgs = AF.Add(ScratchArgs, 1, DecRef);
S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
}
@ -997,11 +1043,19 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
// FIXES: <rdar://problem/6326900>
// This should be addressed using a API table. This strcmp is also
// a little gross, but there is no need to super optimize here.
assert (ScratchArgs.isEmpty());
ScratchArgs = AF.Add(ScratchArgs, 1, DecRef);
S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
}
break;
case 32:
if (!memcmp(FName, "IOServiceAddMatchingNotification", 32)) {
// Part of <rdar://problem/6961230>.
// This should be addressed using a API table.
ScratchArgs = AF.Add(ScratchArgs, 2, DecRef);
S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
}
break;
}
// Did we get a summary?
@ -1195,15 +1249,15 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ,
// Determine if there is a special return effect for this method.
if (isTrackedObjCObjectType(RetTy)) {
if (FD->getAttr<NSReturnsRetainedAttr>()) {
if (FD->getAttr<NSReturnsRetainedAttr>(Ctx)) {
Summ.setRetEffect(ObjCAllocRetE);
}
else if (FD->getAttr<CFReturnsRetainedAttr>()) {
else if (FD->getAttr<CFReturnsRetainedAttr>(Ctx)) {
Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
}
}
else if (RetTy->getAsPointerType()) {
if (FD->getAttr<CFReturnsRetainedAttr>()) {
if (FD->getAttr<CFReturnsRetainedAttr>(Ctx)) {
Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
}
}
@ -1217,10 +1271,10 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ,
// Determine if there is a special return effect for this method.
if (isTrackedObjCObjectType(MD->getResultType())) {
if (MD->getAttr<NSReturnsRetainedAttr>()) {
if (MD->getAttr<NSReturnsRetainedAttr>(Ctx)) {
Summ.setRetEffect(ObjCAllocRetE);
}
else if (MD->getAttr<CFReturnsRetainedAttr>()) {
else if (MD->getAttr<CFReturnsRetainedAttr>(Ctx)) {
Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
}
}
@ -1485,11 +1539,14 @@ void RetainSummaryManager::InitializeMethodSummaries() {
addInstMethSummary("QCView", AllocSumm,
"createSnapshotImageOfType", NULL);
// Create summaries for CIContext, 'createCGImage'.
// Create summaries for CIContext, 'createCGImage' and
// 'createCGLayerWithSize'.
addInstMethSummary("CIContext", AllocSumm,
"createCGImage", "fromRect", NULL);
addInstMethSummary("CIContext", AllocSumm,
"createCGImage", "fromRect", "format", "colorSpace", NULL);
"createCGImage", "fromRect", "format", "colorSpace", NULL);
addInstMethSummary("CIContext", AllocSumm, "createCGLayerWithSize",
"info", NULL);
}
//===----------------------------------------------------------------------===//
@ -1747,11 +1804,11 @@ static SymbolRef GetCurrentAutoreleasePool(const GRState* state) {
return stack.isEmpty() ? SymbolRef() : stack.getHead();
}
static GRStateRef SendAutorelease(GRStateRef state, ARCounts::Factory &F,
SymbolRef sym) {
static const GRState * SendAutorelease(const GRState *state,
ARCounts::Factory &F, SymbolRef sym) {
SymbolRef pool = GetCurrentAutoreleasePool(state);
const ARCounts *cnts = state.get<AutoreleasePoolContents>(pool);
const ARCounts *cnts = state->get<AutoreleasePoolContents>(pool);
ARCounts newCnts(0);
if (cnts) {
@ -1761,7 +1818,7 @@ static GRStateRef SendAutorelease(GRStateRef state, ARCounts::Factory &F,
else
newCnts = F.Add(F.GetEmptyMap(), sym, 1);
return state.set<AutoreleasePoolContents>(pool, newCnts);
return state->set<AutoreleasePoolContents>(pool, newCnts);
}
//===----------------------------------------------------------------------===//
@ -1794,7 +1851,7 @@ class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
BugType *returnNotOwnedForOwned;
BugReporter *BR;
GRStateRef Update(GRStateRef state, SymbolRef sym, RefVal V, ArgEffect E,
const GRState * Update(const GRState * state, SymbolRef sym, RefVal V, ArgEffect E,
RefVal::Kind& hasErr);
void ProcessNonLeakError(ExplodedNodeSet<GRState>& Dst,
@ -1804,10 +1861,10 @@ class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
const GRState* St,
RefVal::Kind hasErr, SymbolRef Sym);
GRStateRef HandleSymbolDeath(GRStateRef state, SymbolRef sid, RefVal V,
const GRState * HandleSymbolDeath(const GRState * state, SymbolRef sid, RefVal V,
llvm::SmallVectorImpl<SymbolRef> &Leaked);
ExplodedNode<GRState>* ProcessLeaks(GRStateRef state,
ExplodedNode<GRState>* ProcessLeaks(const GRState * state,
llvm::SmallVectorImpl<SymbolRef> &Leaked,
GenericNodeBuilder &Builder,
GRExprEngine &Eng,
@ -1882,8 +1939,8 @@ class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
Stmt* S, const GRState* state,
SymbolReaper& SymReaper);
std::pair<ExplodedNode<GRState>*, GRStateRef>
HandleAutoreleaseCounts(GRStateRef state, GenericNodeBuilder Bd,
std::pair<ExplodedNode<GRState>*, const GRState *>
HandleAutoreleaseCounts(const GRState * state, GenericNodeBuilder Bd,
ExplodedNode<GRState>* Pred, GRExprEngine &Eng,
SymbolRef Sym, RefVal V, bool &stop);
// Return statements.
@ -1896,9 +1953,8 @@ class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
// Assumptions.
virtual const GRState* EvalAssume(GRStateManager& VMgr,
const GRState* St, SVal Cond,
bool Assumption, bool& isFeasible);
virtual const GRState *EvalAssume(const GRState* state, SVal condition,
bool assumption);
};
} // end anonymous namespace
@ -2226,15 +2282,14 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N,
return NULL;
// Check if the type state has changed.
GRStateManager &StMgr = BRC.getStateManager();
GRStateRef PrevSt(PrevN->getState(), StMgr);
GRStateRef CurrSt(N->getState(), StMgr);
const GRState *PrevSt = PrevN->getState();
const GRState *CurrSt = N->getState();
const RefVal* CurrT = CurrSt.get<RefBindings>(Sym);
const RefVal* CurrT = CurrSt->get<RefBindings>(Sym);
if (!CurrT) return NULL;
const RefVal& CurrV = *CurrT;
const RefVal* PrevT = PrevSt.get<RefBindings>(Sym);
const RefVal &CurrV = *CurrT;
const RefVal *PrevT = PrevSt->get<RefBindings>(Sym);
// Create a string buffer to constain all the useful things we want
// to tell the user.
@ -2248,7 +2303,7 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N,
if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
// Get the name of the callee (if it is available).
SVal X = CurrSt.GetSValAsScalarOrLoc(CE->getCallee());
SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee());
if (const FunctionDecl* FD = X.getAsFunctionDecl())
os << "Call to function '" << FD->getNameAsString() <<'\'';
else
@ -2305,7 +2360,7 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N,
// Retrieve the value of the argument. Is it the symbol
// we are interested in?
if (CurrSt.GetSValAsScalarOrLoc(*AI).getAsLocSymbol() != Sym)
if (CurrSt->getSValAsScalarOrLoc(*AI).getAsLocSymbol() != Sym)
continue;
// We have an argument. Get the effect!
@ -2314,7 +2369,7 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N,
}
else if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) {
if (Expr *receiver = ME->getReceiver())
if (CurrSt.GetSValAsScalarOrLoc(receiver).getAsLocSymbol() == Sym) {
if (CurrSt->getSValAsScalarOrLoc(receiver).getAsLocSymbol() == Sym) {
// The symbol we are tracking is the receiver.
AEffects.push_back(Summ->getReceiverEffect());
}
@ -2342,7 +2397,7 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N,
if (contains(AEffects, MakeCollectable)) {
// Get the name of the function.
Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
SVal X = CurrSt.GetSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee());
SVal X = CurrSt->getSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee());
const FunctionDecl* FD = X.getAsFunctionDecl();
const std::string& FName = FD->getNameAsString();
@ -2453,7 +2508,7 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N,
// to Sym.
for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
if (Expr* Exp = dyn_cast_or_null<Expr>(*I))
if (CurrSt.GetSValAsScalarOrLoc(Exp).getAsLocSymbol() == Sym) {
if (CurrSt->getSValAsScalarOrLoc(Exp).getAsLocSymbol() == Sym) {
P->addRange(Exp->getSourceRange());
break;
}
@ -2705,7 +2760,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
// Get the state.
GRStateManager& StateMgr = Eng.getStateManager();
GRStateRef state(Builder.GetState(Pred), StateMgr);
const GRState *state = Builder.GetState(Pred);
ASTContext& Ctx = StateMgr.getContext();
ValueManager &ValMgr = Eng.getValueManager();
@ -2716,11 +2771,11 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
SymbolRef ErrorSym = 0;
for (ExprIterator I = arg_beg; I != arg_end; ++I, ++idx) {
SVal V = state.GetSValAsScalarOrLoc(*I);
SVal V = state->getSValAsScalarOrLoc(*I);
SymbolRef Sym = V.getAsLocSymbol();
if (Sym)
if (RefBindings::data_type* T = state.get<RefBindings>(Sym)) {
if (RefBindings::data_type* T = state->get<RefBindings>(Sym)) {
state = Update(state, Sym, *T, Summ.getArg(idx), hasErr);
if (hasErr) {
ErrorExpr = *I;
@ -2775,10 +2830,10 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
}
// Is the invalidated variable something that we were tracking?
SymbolRef Sym = state.GetSValAsScalarOrLoc(R).getAsLocSymbol();
SymbolRef Sym = state->getSValAsScalarOrLoc(R).getAsLocSymbol();
// Remove any existing reference-count binding.
if (Sym) state = state.remove<RefBindings>(Sym);
if (Sym) state = state->remove<RefBindings>(Sym);
if (R->isBoundable(Ctx)) {
// Set the value of the variable to be a conjured symbol.
@ -2788,7 +2843,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())){
ValueManager &ValMgr = Eng.getValueManager();
SVal V = ValMgr.getConjuredSymbolVal(*I, T, Count);
state = state.BindLoc(Loc::MakeVal(R), V);
state = state->bindLoc(Loc::MakeVal(R), V);
}
else if (const RecordType *RT = T->getAsStructureType()) {
// Handle structs in a not so awesome way. Here we just
@ -2802,7 +2857,8 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
if (!RD)
continue;
MemRegionManager &MRMgr = state.getManager().getRegionManager();
MemRegionManager &MRMgr =
state->getStateManager().getRegionManager();
// Iterate through the fields and construct new symbols.
for (RecordDecl::field_iterator FI=RD->field_begin(Ctx),
@ -2817,7 +2873,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
const FieldRegion* FR = MRMgr.getFieldRegion(FD, R);
SVal V = ValMgr.getConjuredSymbolVal(*I, FT, Count);
state = state.BindLoc(Loc::MakeVal(FR), V);
state = state->bindLoc(Loc::MakeVal(FR), V);
}
}
} else if (const ArrayType *AT = Ctx.getAsArrayType(T)) {
@ -2825,31 +2881,30 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
StoreManager& StoreMgr = Eng.getStateManager().getStoreManager();
SVal V = ValMgr.getConjuredSymbolVal(*I, AT->getElementType(),
Count);
state = GRStateRef(StoreMgr.setDefaultValue(state, R, V),
StateMgr);
state = StoreMgr.setDefaultValue(state, R, V);
} else {
// Just blast away other values.
state = state.BindLoc(*MR, UnknownVal());
state = state->bindLoc(*MR, UnknownVal());
}
}
}
else
state = state.BindLoc(*MR, UnknownVal());
state = state->bindLoc(*MR, UnknownVal());
}
else {
// Nuke all other arguments passed by reference.
state = state.Unbind(cast<Loc>(V));
state = state->unbindLoc(cast<Loc>(V));
}
}
else if (isa<nonloc::LocAsInteger>(V))
state = state.Unbind(cast<nonloc::LocAsInteger>(V).getLoc());
state = state->unbindLoc(cast<nonloc::LocAsInteger>(V).getLoc());
}
// Evaluate the effect on the message receiver.
if (!ErrorExpr && Receiver) {
SymbolRef Sym = state.GetSValAsScalarOrLoc(Receiver).getAsLocSymbol();
SymbolRef Sym = state->getSValAsScalarOrLoc(Receiver).getAsLocSymbol();
if (Sym) {
if (const RefVal* T = state.get<RefBindings>(Sym)) {
if (const RefVal* T = state->get<RefBindings>(Sym)) {
state = Update(state, Sym, *T, Summ.getReceiverEffect(), hasErr);
if (hasErr) {
ErrorExpr = Receiver;
@ -2871,10 +2926,10 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
if (RE.getKind() == RetEffect::OwnedWhenTrackedReceiver) {
assert(Receiver);
SVal V = state.GetSValAsScalarOrLoc(Receiver);
SVal V = state->getSValAsScalarOrLoc(Receiver);
bool found = false;
if (SymbolRef Sym = V.getAsLocSymbol())
if (state.get<RefBindings>(Sym)) {
if (state->get<RefBindings>(Sym)) {
found = true;
RE = Summaries.getObjAllocRetEffect();
}
@ -2902,7 +2957,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
unsigned Count = Builder.getCurrentBlockCount();
ValueManager &ValMgr = Eng.getValueManager();
SVal X = ValMgr.getConjuredSymbolVal(Ex, T, Count);
state = state.BindExpr(Ex, X, false);
state = state->bindExpr(Ex, X, false);
}
break;
@ -2912,15 +2967,15 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
unsigned idx = RE.getIndex();
assert (arg_end >= arg_beg);
assert (idx < (unsigned) (arg_end - arg_beg));
SVal V = state.GetSValAsScalarOrLoc(*(arg_beg+idx));
state = state.BindExpr(Ex, V, false);
SVal V = state->getSValAsScalarOrLoc(*(arg_beg+idx));
state = state->bindExpr(Ex, V, false);
break;
}
case RetEffect::ReceiverAlias: {
assert (Receiver);
SVal V = state.GetSValAsScalarOrLoc(Receiver);
state = state.BindExpr(Ex, V, false);
SVal V = state->getSValAsScalarOrLoc(Receiver);
state = state->bindExpr(Ex, V, false);
break;
}
@ -2930,9 +2985,9 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
ValueManager &ValMgr = Eng.getValueManager();
SymbolRef Sym = ValMgr.getConjuredSymbol(Ex, Count);
QualType RetT = GetReturnType(Ex, ValMgr.getContext());
state = state.set<RefBindings>(Sym, RefVal::makeOwned(RE.getObjKind(),
state = state->set<RefBindings>(Sym, RefVal::makeOwned(RE.getObjKind(),
RetT));
state = state.BindExpr(Ex, ValMgr.makeRegionVal(Sym), false);
state = state->bindExpr(Ex, ValMgr.makeRegionVal(Sym), false);
// FIXME: Add a flag to the checker where allocations are assumed to
// *not fail.
@ -2953,9 +3008,9 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
ValueManager &ValMgr = Eng.getValueManager();
SymbolRef Sym = ValMgr.getConjuredSymbol(Ex, Count);
QualType RetT = GetReturnType(Ex, ValMgr.getContext());
state = state.set<RefBindings>(Sym, RefVal::makeNotOwned(RE.getObjKind(),
state = state->set<RefBindings>(Sym, RefVal::makeNotOwned(RE.getObjKind(),
RetT));
state = state.BindExpr(Ex, ValMgr.makeRegionVal(Sym), false);
state = state->bindExpr(Ex, ValMgr.makeRegionVal(Sym), false);
break;
}
}
@ -3001,7 +3056,7 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst,
// FIXME: Is this really working as expected? There are cases where
// we just use the 'ID' from the message expression.
const GRState* St = Builder.GetState(Pred);
SVal V = Eng.getStateManager().GetSValAsScalarOrLoc(St, Receiver);
SVal V = St->getSValAsScalarOrLoc(Receiver);
SymbolRef Sym = V.getAsLocSymbol();
if (Sym) {
@ -3034,7 +3089,7 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst,
// This is a hack. When we have full-IP this should be removed.
if (isa<ObjCMethodDecl>(&Eng.getGraph().getCodeDecl())) {
if (Expr* Receiver = ME->getReceiver()) {
SVal X = Eng.getStateManager().GetSValAsScalarOrLoc(St, Receiver);
SVal X = St->getSValAsScalarOrLoc(Receiver);
if (loc::MemRegionVal* L = dyn_cast<loc::MemRegionVal>(&X))
if (L->getRegion() == Eng.getStateManager().getSelfRegion(St)) {
// Update the summary to make the default argument effect
@ -3057,17 +3112,15 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst,
namespace {
class VISIBILITY_HIDDEN StopTrackingCallback : public SymbolVisitor {
GRStateRef state;
const GRState *state;
public:
StopTrackingCallback(GRStateRef st) : state(st) {}
GRStateRef getState() { return state; }
StopTrackingCallback(const GRState *st) : state(st) {}
const GRState *getState() const { return state; }
bool VisitSymbol(SymbolRef sym) {
state = state.remove<RefBindings>(sym);
state = state->remove<RefBindings>(sym);
return true;
}
const GRState* getState() const { return state.getState(); }
};
} // end anonymous namespace
@ -3082,7 +3135,7 @@ void CFRefCount::EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) {
// (2) we are binding to a memregion that does not have stack storage
// (3) we are binding to a memregion with stack storage that the store
// does not understand.
GRStateRef state = B.getState();
const GRState *state = B.getState();
if (!isa<loc::MemRegionVal>(location))
escapes = true;
@ -3094,7 +3147,7 @@ void CFRefCount::EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) {
// To test (3), generate a new state with the binding removed. If it is
// the same state, then it escapes (since the store cannot represent
// the binding).
escapes = (state == (state.BindLoc(cast<Loc>(location), UnknownVal())));
escapes = (state == (state->bindLoc(cast<Loc>(location), UnknownVal())));
}
}
@ -3106,10 +3159,9 @@ void CFRefCount::EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) {
// Otherwise, find all symbols referenced by 'val' that we are tracking
// and stop tracking them.
B.MakeNode(state.scanReachableSymbols<StopTrackingCallback>(val).getState());
B.MakeNode(state->scanReachableSymbols<StopTrackingCallback>(val).getState());
}
// Return statements.
void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst,
@ -3122,14 +3174,14 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst,
if (!RetE)
return;
GRStateRef state(Builder.GetState(Pred), Eng.getStateManager());
SymbolRef Sym = state.GetSValAsScalarOrLoc(RetE).getAsLocSymbol();
const GRState *state = Builder.GetState(Pred);
SymbolRef Sym = state->getSValAsScalarOrLoc(RetE).getAsLocSymbol();
if (!Sym)
return;
// Get the reference count binding (if any).
const RefVal* T = state.get<RefBindings>(Sym);
const RefVal* T = state->get<RefBindings>(Sym);
if (!T)
return;
@ -3163,7 +3215,7 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst,
}
// Update the binding.
state = state.set<RefBindings>(Sym, X);
state = state->set<RefBindings>(Sym, X);
Pred = Builder.MakeNode(Dst, S, Pred, state);
// Did we cache out?
@ -3182,7 +3234,7 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst,
return;
// Get the updated binding.
T = state.get<RefBindings>(Sym);
T = state->get<RefBindings>(Sym);
assert(T);
X = *T;
@ -3217,7 +3269,7 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst,
if (hasError) {
// Generate an error node.
static int ReturnOwnLeakTag = 0;
state = state.set<RefBindings>(Sym, X);
state = state->set<RefBindings>(Sym, X);
ExplodedNode<GRState> *N =
Builder.generateNode(PostStmt(S, &ReturnOwnLeakTag), state, Pred);
if (N) {
@ -3238,7 +3290,7 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst,
// owned object.
static int ReturnNotOwnedForOwnedTag = 0;
state = state.set<RefBindings>(Sym, X ^ RefVal::ErrorReturnedNotOwned);
state = state->set<RefBindings>(Sym, X ^ RefVal::ErrorReturnedNotOwned);
if (ExplodedNode<GRState> *N =
Builder.generateNode(PostStmt(S, &ReturnNotOwnedForOwnedTag),
state, Pred)) {
@ -3254,10 +3306,8 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst,
// Assumptions.
const GRState* CFRefCount::EvalAssume(GRStateManager& VMgr,
const GRState* St,
SVal Cond, bool Assumption,
bool& isFeasible) {
const GRState* CFRefCount::EvalAssume(const GRState *state,
SVal Cond, bool Assumption) {
// FIXME: We may add to the interface of EvalAssume the list of symbols
// whose assumptions have changed. For now we just iterate through the
@ -3265,32 +3315,30 @@ const GRState* CFRefCount::EvalAssume(GRStateManager& VMgr,
// too bad since the number of symbols we will track in practice are
// probably small and EvalAssume is only called at branches and a few
// other places.
RefBindings B = St->get<RefBindings>();
RefBindings B = state->get<RefBindings>();
if (B.isEmpty())
return St;
return state;
bool changed = false;
GRStateRef state(St, VMgr);
RefBindings::Factory& RefBFactory = state.get_context<RefBindings>();
bool changed = false;
RefBindings::Factory& RefBFactory = state->get_context<RefBindings>();
for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
// Check if the symbol is null (or equal to any constant).
// If this is the case, stop tracking the symbol.
if (VMgr.getSymVal(St, I.getKey())) {
if (state->getSymVal(I.getKey())) {
changed = true;
B = RefBFactory.Remove(B, I.getKey());
}
}
if (changed)
state = state.set<RefBindings>(B);
state = state->set<RefBindings>(B);
return state;
}
GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym,
const GRState * CFRefCount::Update(const GRState * state, SymbolRef sym,
RefVal V, ArgEffect E,
RefVal::Kind& hasErr) {
@ -3308,7 +3356,7 @@ GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym,
if (!isGCEnabled() && V.getKind() == RefVal::Released) {
V = V ^ RefVal::ErrorUseAfterRelease;
hasErr = V.getKind();
return state.set<RefBindings>(sym, V);
return state->set<RefBindings>(sym, V);
}
switch (E) {
@ -3330,7 +3378,7 @@ GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym,
// The object immediately transitions to the released state.
V = V ^ RefVal::Released;
V.clearCounts();
return state.set<RefBindings>(sym, V);
return state->set<RefBindings>(sym, V);
case RefVal::NotOwned:
V = V ^ RefVal::ErrorDeallocNotOwned;
hasErr = V.getKind();
@ -3340,7 +3388,7 @@ GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym,
case NewAutoreleasePool:
assert(!isGCEnabled());
return state.add<AutoreleaseStack>(sym);
return state->add<AutoreleaseStack>(sym);
case MayEscape:
if (V.getKind() == RefVal::Owned) {
@ -3364,7 +3412,7 @@ GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym,
break;
case StopTracking:
return state.remove<RefBindings>(sym);
return state->remove<RefBindings>(sym);
case IncRef:
switch (V.getKind()) {
@ -3416,15 +3464,15 @@ GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym,
}
break;
}
return state.set<RefBindings>(sym, V);
return state->set<RefBindings>(sym, V);
}
//===----------------------------------------------------------------------===//
// Handle dead symbols and end-of-path.
//===----------------------------------------------------------------------===//
std::pair<ExplodedNode<GRState>*, GRStateRef>
CFRefCount::HandleAutoreleaseCounts(GRStateRef state, GenericNodeBuilder Bd,
std::pair<ExplodedNode<GRState>*, const GRState *>
CFRefCount::HandleAutoreleaseCounts(const GRState * state, GenericNodeBuilder Bd,
ExplodedNode<GRState>* Pred,
GRExprEngine &Eng,
SymbolRef Sym, RefVal V, bool &stop) {
@ -3456,7 +3504,7 @@ CFRefCount::HandleAutoreleaseCounts(GRStateRef state, GenericNodeBuilder Bd,
V.setCount(Cnt - ACnt);
V.setAutoreleaseCount(0);
}
state = state.set<RefBindings>(Sym, V);
state = state->set<RefBindings>(Sym, V);
ExplodedNode<GRState> *N = Bd.MakeNode(state, Pred);
stop = (N == 0);
return std::make_pair(N, state);
@ -3466,7 +3514,7 @@ CFRefCount::HandleAutoreleaseCounts(GRStateRef state, GenericNodeBuilder Bd,
// Emit hard error.
stop = true;
V = V ^ RefVal::ErrorOverAutorelease;
state = state.set<RefBindings>(Sym, V);
state = state->set<RefBindings>(Sym, V);
if (ExplodedNode<GRState> *N = Bd.MakeNode(state, Pred)) {
N->markAsSink();
@ -3492,22 +3540,22 @@ CFRefCount::HandleAutoreleaseCounts(GRStateRef state, GenericNodeBuilder Bd,
return std::make_pair((ExplodedNode<GRState>*)0, state);
}
GRStateRef
CFRefCount::HandleSymbolDeath(GRStateRef state, SymbolRef sid, RefVal V,
const GRState *
CFRefCount::HandleSymbolDeath(const GRState * state, SymbolRef sid, RefVal V,
llvm::SmallVectorImpl<SymbolRef> &Leaked) {
bool hasLeak = V.isOwned() ||
((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
if (!hasLeak)
return state.remove<RefBindings>(sid);
return state->remove<RefBindings>(sid);
Leaked.push_back(sid);
return state.set<RefBindings>(sid, V ^ RefVal::ErrorLeak);
return state->set<RefBindings>(sid, V ^ RefVal::ErrorLeak);
}
ExplodedNode<GRState>*
CFRefCount::ProcessLeaks(GRStateRef state,
CFRefCount::ProcessLeaks(const GRState * state,
llvm::SmallVectorImpl<SymbolRef> &Leaked,
GenericNodeBuilder &Builder,
GRExprEngine& Eng,
@ -3537,9 +3585,9 @@ CFRefCount::ProcessLeaks(GRStateRef state,
void CFRefCount::EvalEndPath(GRExprEngine& Eng,
GREndPathNodeBuilder<GRState>& Builder) {
GRStateRef state(Builder.getState(), Eng.getStateManager());
const GRState *state = Builder.getState();
GenericNodeBuilder Bd(Builder);
RefBindings B = state.get<RefBindings>();
RefBindings B = state->get<RefBindings>();
ExplodedNode<GRState> *Pred = 0;
for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
@ -3552,7 +3600,7 @@ void CFRefCount::EvalEndPath(GRExprEngine& Eng,
return;
}
B = state.get<RefBindings>();
B = state->get<RefBindings>();
llvm::SmallVector<SymbolRef, 10> Leaked;
for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I)
@ -3566,11 +3614,10 @@ void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<GRState>& Dst,
GRStmtNodeBuilder<GRState>& Builder,
ExplodedNode<GRState>* Pred,
Stmt* S,
const GRState* St,
const GRState* state,
SymbolReaper& SymReaper) {
GRStateRef state(St, Eng.getStateManager());
RefBindings B = state.get<RefBindings>();
RefBindings B = state->get<RefBindings>();
// Update counts from autorelease pools
for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
@ -3588,7 +3635,7 @@ void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<GRState>& Dst,
}
}
B = state.get<RefBindings>();
B = state->get<RefBindings>();
llvm::SmallVector<SymbolRef, 10> Leaked;
for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
@ -3608,12 +3655,12 @@ void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<GRState>& Dst,
return;
// Now generate a new node that nukes the old bindings.
RefBindings::Factory& F = state.get_context<RefBindings>();
RefBindings::Factory& F = state->get_context<RefBindings>();
for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
E = SymReaper.dead_end(); I!=E; ++I) B = F.Remove(B, *I);
state = state.set<RefBindings>(B);
state = state->set<RefBindings>(B);
Builder.MakeNode(Dst, S, Pred, state);
}

View File

@ -85,7 +85,7 @@ class VISIBILITY_HIDDEN DeadStoreObs : public LiveVariables::ObserverTy {
const LiveVariables::AnalysisDataTy& AD,
const LiveVariables::ValTy& Live) {
if (VD->hasLocalStorage() && !Live(VD, AD) && !VD->getAttr<UnusedAttr>())
if (VD->hasLocalStorage() && !Live(VD, AD) && !VD->getAttr<UnusedAttr>(Ctx))
Report(VD, dsk, Ex->getSourceRange().getBegin(),
Val->getSourceRange());
}
@ -190,7 +190,7 @@ class VISIBILITY_HIDDEN DeadStoreObs : public LiveVariables::ObserverTy {
// A dead initialization is a variable that is dead after it
// is initialized. We don't flag warnings for those variables
// marked 'unused'.
if (!Live(V, AD) && V->getAttr<UnusedAttr>() == 0) {
if (!Live(V, AD) && V->getAttr<UnusedAttr>(Ctx) == 0) {
// Special case: check for initializations with constants.
//
// e.g. : int x = 0;

View File

@ -41,7 +41,7 @@ class VISIBILITY_HIDDEN NSErrorCheck : public BugType {
bool CheckNSErrorArgument(QualType ArgTy);
bool CheckCFErrorArgument(QualType ArgTy);
void CheckParamDeref(VarDecl* V, GRStateRef state, BugReporter& BR);
void CheckParamDeref(VarDecl* V, const GRState *state, BugReporter& BR);
void EmitRetTyWarning(BugReporter& BR, Decl& CodeDecl);
@ -94,8 +94,7 @@ void NSErrorCheck::FlushReports(BugReporter& BR) {
// Scan the parameters for an implicit null dereference.
for (llvm::SmallVectorImpl<VarDecl*>::iterator I=ErrorParams.begin(),
E=ErrorParams.end(); I!=E; ++I)
CheckParamDeref(*I, GRStateRef((*RI)->getState(),Eng.getStateManager()),
BR);
CheckParamDeref(*I, (*RI)->getState(), BR);
}
}
@ -186,13 +185,13 @@ bool NSErrorCheck::CheckCFErrorArgument(QualType ArgTy) {
return TT->getDecl()->getIdentifier() == II;
}
void NSErrorCheck::CheckParamDeref(VarDecl* Param, GRStateRef rootState,
void NSErrorCheck::CheckParamDeref(VarDecl* Param, const GRState *rootState,
BugReporter& BR) {
SVal ParamL = rootState.GetLValue(Param);
SVal ParamL = rootState->getLValue(Param);
const MemRegion* ParamR = cast<loc::MemRegionVal>(ParamL).getRegionAs<VarRegion>();
assert (ParamR && "Parameters always have VarRegions.");
SVal ParamSVal = rootState.GetSVal(ParamR);
SVal ParamSVal = rootState->getSVal(ParamR);
// FIXME: For now assume that ParamSVal is symbolic. We need to generalize
// this later.
@ -204,8 +203,8 @@ void NSErrorCheck::CheckParamDeref(VarDecl* Param, GRStateRef rootState,
for (GRExprEngine::null_deref_iterator I=Eng.implicit_null_derefs_begin(),
E=Eng.implicit_null_derefs_end(); I!=E; ++I) {
GRStateRef state = GRStateRef((*I)->getState(), Eng.getStateManager());
const SVal* X = state.get<GRState::NullDerefTag>();
const GRState *state = (*I)->getState();
const SVal* X = state->get<GRState::NullDerefTag>();
if (!X || X->getAsSymbol() != ParamSym)
continue;

View File

@ -109,7 +109,7 @@ void clang::CheckObjCDealloc(ObjCImplementationDecl* D,
QualType T = ID->getType();
if (!Ctx.isObjCObjectPointerType(T) ||
ID->getAttr<IBOutletAttr>()) // Skip IBOutlets.
ID->getAttr<IBOutletAttr>(Ctx)) // Skip IBOutlets.
continue;
containsPointerIvar = true;

View File

@ -74,7 +74,7 @@ void clang::CheckObjCUnusedIvar(ObjCImplementationDecl* D, BugReporter& BR) {
continue;
// Skip IB Outlets.
if (ID->getAttr<IBOutletAttr>())
if (ID->getAttr<IBOutletAttr>(Ctx))
continue;
M[ID] = Unused;

View File

@ -18,7 +18,7 @@
using namespace clang;
SVal Environment::GetSVal(Stmt* E, BasicValueFactory& BasicVals) const {
SVal Environment::GetSVal(const Stmt *E, BasicValueFactory& BasicVals) const {
for (;;) {
@ -34,7 +34,7 @@ SVal Environment::GetSVal(Stmt* E, BasicValueFactory& BasicVals) const {
continue;
case Stmt::CharacterLiteralClass: {
CharacterLiteral* C = cast<CharacterLiteral>(E);
const CharacterLiteral* C = cast<CharacterLiteral>(E);
return NonLoc::MakeVal(BasicVals, C->getValue(), C->getType());
}
@ -48,7 +48,7 @@ SVal Environment::GetSVal(Stmt* E, BasicValueFactory& BasicVals) const {
case Stmt::ImplicitCastExprClass:
case Stmt::CStyleCastExprClass: {
CastExpr* C = cast<CastExpr>(E);
const CastExpr* C = cast<CastExpr>(E);
QualType CT = C->getType();
if (CT->isVoidType())
@ -69,7 +69,8 @@ SVal Environment::GetSVal(Stmt* E, BasicValueFactory& BasicVals) const {
return LookupExpr(E);
}
SVal Environment::GetBlkExprSVal(Stmt* E, BasicValueFactory& BasicVals) const {
SVal Environment::GetBlkExprSVal(const Stmt *E,
BasicValueFactory& BasicVals) const {
while (1) {
switch (E->getStmtClass()) {
@ -78,7 +79,7 @@ SVal Environment::GetBlkExprSVal(Stmt* E, BasicValueFactory& BasicVals) const {
continue;
case Stmt::CharacterLiteralClass: {
CharacterLiteral* C = cast<CharacterLiteral>(E);
const CharacterLiteral* C = cast<CharacterLiteral>(E);
return NonLoc::MakeVal(BasicVals, C->getValue(), C->getType());
}
@ -92,8 +93,9 @@ SVal Environment::GetBlkExprSVal(Stmt* E, BasicValueFactory& BasicVals) const {
}
}
Environment EnvironmentManager::BindExpr(const Environment& Env, Stmt* E,SVal V,
bool isBlkExpr, bool Invalidate) {
Environment EnvironmentManager::BindExpr(const Environment& Env, const Stmt* E,
SVal V, bool isBlkExpr,
bool Invalidate) {
assert (E);
if (V.isUnknown()) {
@ -136,7 +138,7 @@ EnvironmentManager::RemoveDeadBindings(Environment Env, Stmt* Loc,
// Iterate over the block-expr bindings.
for (Environment::beb_iterator I = Env.beb_begin(), E = Env.beb_end();
I != E; ++I) {
Stmt* BlkExpr = I.getKey();
const Stmt *BlkExpr = I.getKey();
if (SymReaper.isLive(Loc, BlkExpr)) {
SVal X = I.getData();
@ -147,7 +149,7 @@ EnvironmentManager::RemoveDeadBindings(Environment Env, Stmt* Loc,
// Mark all symbols in the block expr's value live.
MarkLiveCallback cb(SymReaper);
StateMgr.scanReachableSymbols(X, state, cb);
state->scanReachableSymbols(X, cb);
} else {
// The block expr is dead.
SVal X = I.getData();

File diff suppressed because it is too large Load Diff

View File

@ -347,9 +347,7 @@ class VISIBILITY_HIDDEN RetStack : public BuiltinBug {
assert (E && "Return expression cannot be NULL");
// Get the value associated with E.
loc::MemRegionVal V =
cast<loc::MemRegionVal>(Eng.getStateManager().GetSVal(N->getState(),
E));
loc::MemRegionVal V = cast<loc::MemRegionVal>(N->getState()->getSVal(E));
// Generate a report for this bug.
std::string buf;
@ -427,7 +425,7 @@ class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
return Ex;
}
bool MatchesCriteria(Expr* Ex) { return VM.GetSVal(St, Ex).isUndef(); }
bool MatchesCriteria(Expr* Ex) { return St->getSVal(Ex).isUndef(); }
};
public:
@ -519,8 +517,7 @@ class VISIBILITY_HIDDEN BadSizeVLA : public BuiltinBug {
"variable-length array (VLA) '"
<< VD->getNameAsString() << "' evaluates to ";
bool isUndefined = Eng.getStateManager().GetSVal(N->getState(),
SizeExpr).isUndef();
bool isUndefined = N->getState()->getSVal(SizeExpr).isUndef();
if (isUndefined)
os << "an undefined or garbage value.";
@ -563,13 +560,13 @@ class VISIBILITY_HIDDEN CheckAttrNonNull : public GRSimpleAPICheck {
CallExpr* CE = cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt());
const GRState* state = N->getState();
SVal X = VMgr.GetSVal(state, CE->getCallee());
SVal X = state->getSVal(CE->getCallee());
const FunctionDecl* FD = X.getAsFunctionDecl();
if (!FD)
return false;
const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
const NonNullAttr* Att = FD->getAttr<NonNullAttr>(BR.getContext());
if (!Att)
return false;
@ -819,24 +816,15 @@ class VISIBILITY_HIDDEN TrackConstraintBRVisitor : public BugReporterVisitor {
// Check if in the previous state it was feasible for this constraint
// to *not* be true.
GRStateManager &StateMgr = BRC.getStateManager();
bool isFeasible = false;
if (StateMgr.Assume(PrevN->getState(), Constraint, !Assumption,
isFeasible)) {
assert(isFeasible); // Eventually we don't need 'isFeasible'.
if (PrevN->getState()->assume(Constraint, !Assumption)) {
isSatisfied = true;
// As a sanity check, make sure that the negation of the constraint
// was infeasible in the current state. If it is feasible, we somehow
// missed the transition point.
isFeasible = false;
if (StateMgr.Assume(N->getState(), Constraint, !Assumption,
isFeasible)) {
assert(isFeasible);
if (N->getState()->assume(Constraint, !Assumption))
return NULL;
}
// We found the transition point for the constraint. We now need to
// pretty-print the constraint. (work-in-progress)
@ -897,7 +885,7 @@ static void registerTrackNullOrUndefValue(BugReporterContext& BRC,
StateMgr.getRegionManager().getVarRegion(VD);
// What did we load?
SVal V = StateMgr.GetSVal(state, S);
SVal V = state->getSVal(S);
if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)
|| V.isUndef()) {
@ -906,7 +894,7 @@ static void registerTrackNullOrUndefValue(BugReporterContext& BRC,
}
}
SVal V = StateMgr.GetSValAsScalarOrLoc(state, S);
SVal V = state->getSValAsScalarOrLoc(S);
// Uncomment this to find cases where we aren't properly getting the
// base value that was dereferenced.

View File

@ -363,11 +363,13 @@ void GRSimpleVals::EvalCall(ExplodedNodeSet<GRState>& Dst,
for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
I != E; ++I) {
SVal V = StateMgr.GetSVal(St, *I);
SVal V = St->getSVal(*I);
if (isa<loc::MemRegionVal>(V))
St = StateMgr.BindLoc(St, cast<Loc>(V), UnknownVal());
else if (isa<nonloc::LocAsInteger>(V))
if (isa<loc::MemRegionVal>(V)) {
const MemRegion *R = cast<loc::MemRegionVal>(V).getRegion();
if (R->isBoundable(Eng.getContext()))
St = StateMgr.BindLoc(St, cast<Loc>(V), UnknownVal());
} else if (isa<nonloc::LocAsInteger>(V))
St = StateMgr.BindLoc(St, cast<nonloc::LocAsInteger>(V).getLoc(),
UnknownVal());
@ -380,7 +382,7 @@ void GRSimpleVals::EvalCall(ExplodedNodeSet<GRState>& Dst,
if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())) {
unsigned Count = Builder.getCurrentBlockCount();
SVal X = Eng.getValueManager().getConjuredSymbolVal(CE, Count);
St = StateMgr.BindExpr(St, CE, X, Eng.getCFG().isBlkExpr(CE), false);
St = St->bindExpr(CE, X, Eng.getCFG().isBlkExpr(CE), false);
}
Builder.MakeNode(Dst, CE, Pred, St);
@ -398,18 +400,16 @@ void GRSimpleVals::EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst,
// The basic transfer function logic for message expressions does nothing.
// We just invalidate all arguments passed in by references.
GRStateManager& StateMgr = Eng.getStateManager();
const GRState* St = Builder.GetState(Pred);
// We just invalidate all arguments passed in by references.
const GRState *St = Builder.GetState(Pred);
for (ObjCMessageExpr::arg_iterator I = ME->arg_begin(), E = ME->arg_end();
I != E; ++I) {
SVal V = StateMgr.GetSVal(St, *I);
SVal V = St->getSVal(*I);
if (isa<Loc>(V))
St = StateMgr.BindLoc(St, cast<Loc>(V), UnknownVal());
St = St->bindLoc(cast<Loc>(V), UnknownVal());
}
Builder.MakeNode(Dst, ME, Pred, St);

View File

@ -69,8 +69,7 @@ const GRState* GRStateManager::Unbind(const GRState* St, Loc LV) {
}
const GRState* GRStateManager::getInitialState() {
GRState StateImpl(EnvMgr.getInitialEnvironment(),
GRState StateImpl(this, EnvMgr.getInitialEnvironment(),
StoreMgr->getInitialStore(),
GDMFactory.GetEmptyMap());
@ -92,25 +91,19 @@ const GRState* GRStateManager::getPersistentState(GRState& State) {
return I;
}
const GRState* GRStateManager::MakeStateWithStore(const GRState* St,
Store store) {
GRState NewSt = *St;
const GRState* GRState::makeWithStore(Store store) const {
GRState NewSt = *this;
NewSt.St = store;
return getPersistentState(NewSt);
return Mgr->getPersistentState(NewSt);
}
//===----------------------------------------------------------------------===//
// State pretty-printing.
//===----------------------------------------------------------------------===//
void GRState::print(std::ostream& Out, StoreManager& StoreMgr,
ConstraintManager& ConstraintMgr,
Printer** Beg, Printer** End,
const char* nl, const char* sep) const {
void GRState::print(std::ostream& Out, const char* nl, const char* sep) const {
// Print the store.
StoreMgr.print(getStore(), Out, nl, sep);
Mgr->getStoreManager().print(getStore(), Out, nl, sep);
// Print Subexpression bindings.
bool isFirst = true;
@ -150,24 +143,21 @@ void GRState::print(std::ostream& Out, StoreManager& StoreMgr,
I.getData().print(Out);
}
ConstraintMgr.print(this, Out, nl, sep);
Mgr->getConstraintManager().print(this, Out, nl, sep);
// Print checker-specific data.
for ( ; Beg != End ; ++Beg) (*Beg)->Print(Out, this, nl, sep);
// Print checker-specific data.
for (std::vector<Printer*>::iterator I = Mgr->Printers.begin(),
E = Mgr->Printers.end(); I != E; ++I) {
(*I)->Print(Out, this, nl, sep);
}
}
void GRStateRef::printDOT(std::ostream& Out) const {
void GRState::printDOT(std::ostream& Out) const {
print(Out, "\\l", "\\|");
}
void GRStateRef::printStdErr() const {
void GRState::printStdErr() const {
print(*llvm::cerr);
}
void GRStateRef::print(std::ostream& Out, const char* nl, const char* sep)const{
GRState::Printer **beg = Mgr->Printers.empty() ? 0 : &Mgr->Printers[0];
GRState::Printer **end = !beg ? 0 : beg + Mgr->Printers.size();
St->print(Out, *Mgr->StoreMgr, *Mgr->ConstraintMgr, beg, end, nl, sep);
}
//===----------------------------------------------------------------------===//
@ -213,13 +203,13 @@ class VISIBILITY_HIDDEN ScanReachableSymbols : public SubRegionMap::Visitor {
typedef llvm::DenseSet<const MemRegion*> VisitedRegionsTy;
VisitedRegionsTy visited;
GRStateRef state;
const GRState *state;
SymbolVisitor &visitor;
llvm::OwningPtr<SubRegionMap> SRM;
public:
ScanReachableSymbols(GRStateManager* sm, const GRState *st, SymbolVisitor& v)
: state(st, *sm), visitor(v) {}
ScanReachableSymbols(const GRState *st, SymbolVisitor& v)
: state(st), visitor(v) {}
bool scan(nonloc::CompoundVal val);
bool scan(SVal val);
@ -270,19 +260,18 @@ bool ScanReachableSymbols::scan(const MemRegion *R) {
return false;
// Now look at the binding to this region (if any).
if (!scan(state.GetSValAsScalarOrLoc(R)))
if (!scan(state->getSValAsScalarOrLoc(R)))
return false;
// Now look at the subregions.
if (!SRM.get())
SRM.reset(state.getManager().getStoreManager().getSubRegionMap(state));
SRM.reset(state->getStateManager().getStoreManager().getSubRegionMap(state));
return SRM->iterSubRegions(R, *this);
}
bool GRStateManager::scanReachableSymbols(SVal val, const GRState* state,
SymbolVisitor& visitor) {
ScanReachableSymbols S(this, state, visitor);
bool GRState::scanReachableSymbols(SVal val, SymbolVisitor& visitor) const {
ScanReachableSymbols S(this, visitor);
return S.scan(val);
}

View File

@ -23,6 +23,5 @@ void GRTransferFuncs::EvalBinOpNN(GRStateSet& OStates,
BinaryOperator::Opcode Op,
NonLoc L, NonLoc R, QualType T) {
OStates.Add(Eng.getStateManager().BindExpr(St, Ex,
DetermEvalBinOpNN(Eng, Op, L, R, T)));
OStates.Add(St->bindExpr(Ex, DetermEvalBinOpNN(Eng, Op, L, R, T)));
}

View File

@ -296,10 +296,12 @@ MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr* CL) {
ElementRegion*
MemRegionManager::getElementRegion(QualType elementType, SVal Idx,
const MemRegion* superRegion){
const MemRegion* superRegion, ASTContext& Ctx){
QualType T = Ctx.getCanonicalType(elementType);
llvm::FoldingSetNodeID ID;
ElementRegion::ProfileRegion(ID, elementType, Idx, superRegion);
ElementRegion::ProfileRegion(ID, T, Idx, superRegion);
void* InsertPos;
MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
@ -307,7 +309,7 @@ MemRegionManager::getElementRegion(QualType elementType, SVal Idx,
if (!R) {
R = (ElementRegion*) A.Allocate<ElementRegion>();
new (R) ElementRegion(elementType, Idx, superRegion);
new (R) ElementRegion(T, Idx, superRegion);
Regions.InsertNode(R, InsertPos);
}

View File

@ -233,28 +233,27 @@ struct GRStateTrait<ConstraintRange>
namespace {
class VISIBILITY_HIDDEN RangeConstraintManager : public SimpleConstraintManager{
RangeSet GetRange(GRStateRef state, SymbolRef sym);
RangeSet GetRange(const GRState *state, SymbolRef sym);
public:
RangeConstraintManager(GRStateManager& statemgr)
: SimpleConstraintManager(statemgr) {}
RangeConstraintManager() {}
const GRState* AssumeSymNE(const GRState* St, SymbolRef sym,
const llvm::APSInt& V, bool& isFeasible);
const llvm::APSInt& V);
const GRState* AssumeSymEQ(const GRState* St, SymbolRef sym,
const llvm::APSInt& V, bool& isFeasible);
const llvm::APSInt& V);
const GRState* AssumeSymLT(const GRState* St, SymbolRef sym,
const llvm::APSInt& V, bool& isFeasible);
const llvm::APSInt& V);
const GRState* AssumeSymGT(const GRState* St, SymbolRef sym,
const llvm::APSInt& V, bool& isFeasible);
const llvm::APSInt& V);
const GRState* AssumeSymGE(const GRState* St, SymbolRef sym,
const llvm::APSInt& V, bool& isFeasible);
const llvm::APSInt& V);
const GRState* AssumeSymLE(const GRState* St, SymbolRef sym,
const llvm::APSInt& V, bool& isFeasible);
const llvm::APSInt& V);
const llvm::APSInt* getSymVal(const GRState* St, SymbolRef sym) const;
@ -275,9 +274,8 @@ class VISIBILITY_HIDDEN RangeConstraintManager : public SimpleConstraintManager{
} // end anonymous namespace
ConstraintManager* clang::CreateRangeConstraintManager(GRStateManager& StateMgr)
{
return new RangeConstraintManager(StateMgr);
ConstraintManager* clang::CreateRangeConstraintManager(GRStateManager&) {
return new RangeConstraintManager();
}
const llvm::APSInt* RangeConstraintManager::getSymVal(const GRState* St,
@ -289,12 +287,11 @@ const llvm::APSInt* RangeConstraintManager::getSymVal(const GRState* St,
/// Scan all symbols referenced by the constraints. If the symbol is not alive
/// as marked in LSymbols, mark it as dead in DSymbols.
const GRState*
RangeConstraintManager::RemoveDeadBindings(const GRState* St,
RangeConstraintManager::RemoveDeadBindings(const GRState* state,
SymbolReaper& SymReaper) {
GRStateRef state(St, StateMgr);
ConstraintRangeTy CR = state.get<ConstraintRange>();
ConstraintRangeTy::Factory& CRFactory = state.get_context<ConstraintRange>();
ConstraintRangeTy CR = state->get<ConstraintRange>();
ConstraintRangeTy::Factory& CRFactory = state->get_context<ConstraintRange>();
for (ConstraintRangeTy::iterator I = CR.begin(), E = CR.end(); I != E; ++I) {
SymbolRef sym = I.getKey();
@ -302,7 +299,7 @@ RangeConstraintManager::RemoveDeadBindings(const GRState* St,
CR = CRFactory.Remove(CR, sym);
}
return state.set<ConstraintRange>(CR);
return state->set<ConstraintRange>(CR);
}
//===------------------------------------------------------------------------===
@ -310,14 +307,14 @@ RangeConstraintManager::RemoveDeadBindings(const GRState* St,
//===------------------------------------------------------------------------===/
RangeSet
RangeConstraintManager::GetRange(GRStateRef state, SymbolRef sym) {
if (ConstraintRangeTy::data_type* V = state.get<ConstraintRange>(sym))
RangeConstraintManager::GetRange(const GRState *state, SymbolRef sym) {
if (ConstraintRangeTy::data_type* V = state->get<ConstraintRange>(sym))
return *V;
// Lazily generate a new RangeSet representing all possible values for the
// given symbol type.
QualType T = state.getSymbolManager().getType(sym);
BasicValueFactory& BV = state.getBasicVals();
QualType T = state->getSymbolManager().getType(sym);
BasicValueFactory& BV = state->getBasicVals();
return RangeSet(F, BV.getMinValue(T), BV.getMaxValue(T));
}
@ -327,12 +324,10 @@ RangeConstraintManager::GetRange(GRStateRef state, SymbolRef sym) {
#define AssumeX(OP)\
const GRState*\
RangeConstraintManager::AssumeSym ## OP(const GRState* St, SymbolRef sym,\
const llvm::APSInt& V, bool& isFeasible){\
GRStateRef state(St, StateMgr);\
const RangeSet& R = GetRange(state, sym).Add##OP(state.getBasicVals(), F, V);\
isFeasible = !R.isEmpty();\
return isFeasible ? state.set<ConstraintRange>(sym, R).getState() : 0;\
RangeConstraintManager::AssumeSym ## OP(const GRState* state, SymbolRef sym,\
const llvm::APSInt& V){\
const RangeSet& R = GetRange(state, sym).Add##OP(state->getBasicVals(), F, V);\
return !R.isEmpty() ? state->set<ConstraintRange>(sym, R) : NULL;\
}
AssumeX(EQ)

File diff suppressed because it is too large Load Diff

View File

@ -294,7 +294,7 @@ NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, uint64_t X, QualType T) {
return nonloc::ConcreteInt(BasicVals.getValue(X, T));
}
NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, IntegerLiteral* I) {
NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, const IntegerLiteral* I) {
return nonloc::ConcreteInt(BasicVals.getValue(APSInt(I->getValue(),
I->getType()->isUnsignedIntegerType())));
@ -322,11 +322,12 @@ NonLoc NonLoc::MakeCompoundVal(QualType T, llvm::ImmutableList<SVal> Vals,
return nonloc::CompoundVal(BasicVals.getCompoundValData(T, Vals));
}
SVal ValueManager::getRegionValueSymbolVal(const MemRegion* R) {
SymbolRef sym = SymMgr.getRegionValueSymbol(R);
SVal ValueManager::getRegionValueSymbolVal(const MemRegion* R, QualType T) {
SymbolRef sym = SymMgr.getRegionValueSymbol(R, T);
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R)) {
QualType T = TR->getValueType(SymMgr.getContext());
if (T.isNull())
T = TR->getValueType(SymMgr.getContext());
// If T is of function pointer type, create a CodeTextRegion wrapping a
// symbol.
@ -401,7 +402,9 @@ nonloc::LocAsInteger nonloc::LocAsInteger::Make(BasicValueFactory& Vals, Loc V,
Loc Loc::MakeVal(const MemRegion* R) { return loc::MemRegionVal(R); }
Loc Loc::MakeVal(AddrLabelExpr* E) { return loc::GotoLabel(E->getLabel()); }
Loc Loc::MakeVal(const AddrLabelExpr *E) {
return loc::GotoLabel(E->getLabel());
}
Loc Loc::MakeNull(BasicValueFactory &BasicVals) {
return loc::ConcreteInt(BasicVals.getZeroWithPtrWidth());

View File

@ -55,60 +55,55 @@ bool SimpleConstraintManager::canReasonAbout(SVal X) const {
return true;
}
const GRState*
SimpleConstraintManager::Assume(const GRState* St, SVal Cond, bool Assumption,
bool& isFeasible) {
const GRState *SimpleConstraintManager::Assume(const GRState *state,
SVal Cond, bool Assumption) {
if (Cond.isUnknown()) {
isFeasible = true;
return St;
return state;
}
if (isa<NonLoc>(Cond))
return Assume(St, cast<NonLoc>(Cond), Assumption, isFeasible);
return Assume(state, cast<NonLoc>(Cond), Assumption);
else
return Assume(St, cast<Loc>(Cond), Assumption, isFeasible);
return Assume(state, cast<Loc>(Cond), Assumption);
}
const GRState*
SimpleConstraintManager::Assume(const GRState* St, Loc Cond, bool Assumption,
bool& isFeasible) {
St = AssumeAux(St, Cond, Assumption, isFeasible);
if (!isFeasible)
return St;
const GRState *SimpleConstraintManager::Assume(const GRState *state, Loc Cond,
bool Assumption) {
state = AssumeAux(state, Cond, Assumption);
// EvalAssume is used to call into the GRTransferFunction object to perform
// any checker-specific update of the state based on this assumption being
// true or false.
return StateMgr.getTransferFuncs().EvalAssume(StateMgr, St, Cond, Assumption,
isFeasible);
// true or false.
return state ? state->getTransferFuncs().EvalAssume(state, Cond, Assumption)
: NULL;
}
const GRState*
SimpleConstraintManager::AssumeAux(const GRState* St, Loc Cond, bool Assumption,
bool& isFeasible) {
BasicValueFactory& BasicVals = StateMgr.getBasicVals();
const GRState *SimpleConstraintManager::AssumeAux(const GRState *state,
Loc Cond, bool Assumption) {
BasicValueFactory &BasicVals = state->getBasicVals();
switch (Cond.getSubKind()) {
default:
assert (false && "'Assume' not implemented for this Loc.");
return St;
return state;
case loc::MemRegionKind: {
// FIXME: Should this go into the storemanager?
const MemRegion* R = cast<loc::MemRegionVal>(Cond).getRegion();
const SubRegion* SubR = dyn_cast<SubRegion>(R);
const MemRegion *R = cast<loc::MemRegionVal>(Cond).getRegion();
const SubRegion *SubR = dyn_cast<SubRegion>(R);
while (SubR) {
// FIXME: now we only find the first symbolic region.
if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(SubR)) {
if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SubR)) {
if (Assumption)
return AssumeSymNE(St, SymR->getSymbol(),
BasicVals.getZeroWithPtrWidth(), isFeasible);
return AssumeSymNE(state, SymR->getSymbol(),
BasicVals.getZeroWithPtrWidth());
else
return AssumeSymEQ(St, SymR->getSymbol(),
BasicVals.getZeroWithPtrWidth(), isFeasible);
return AssumeSymEQ(state, SymR->getSymbol(),
BasicVals.getZeroWithPtrWidth());
}
SubR = dyn_cast<SubRegion>(SubR->getSuperRegion());
}
@ -117,43 +112,42 @@ SimpleConstraintManager::AssumeAux(const GRState* St, Loc Cond, bool Assumption,
}
case loc::GotoLabelKind:
isFeasible = Assumption;
return St;
return Assumption ? state : NULL;
case loc::ConcreteIntKind: {
bool b = cast<loc::ConcreteInt>(Cond).getValue() != 0;
isFeasible = b ? Assumption : !Assumption;
return St;
bool b = cast<loc::ConcreteInt>(Cond).getValue() != 0;
bool isFeasible = b ? Assumption : !Assumption;
return isFeasible ? state : NULL;
}
} // end switch
}
const GRState*
SimpleConstraintManager::Assume(const GRState* St, NonLoc Cond, bool Assumption,
bool& isFeasible) {
St = AssumeAux(St, Cond, Assumption, isFeasible);
if (!isFeasible)
return St;
const GRState *SimpleConstraintManager::Assume(const GRState *state,
NonLoc Cond,
bool Assumption) {
state = AssumeAux(state, Cond, Assumption);
// EvalAssume is used to call into the GRTransferFunction object to perform
// any checker-specific update of the state based on this assumption being
// true or false.
return StateMgr.getTransferFuncs().EvalAssume(StateMgr, St, Cond, Assumption,
isFeasible);
// true or false.
return state ? state->getTransferFuncs().EvalAssume(state, Cond, Assumption)
: NULL;
}
const GRState*
SimpleConstraintManager::AssumeAux(const GRState* St,NonLoc Cond,
bool Assumption, bool& isFeasible) {
const GRState *SimpleConstraintManager::AssumeAux(const GRState *state,
NonLoc Cond,
bool Assumption) {
// We cannot reason about SymIntExpr and SymSymExpr.
if (!canReasonAbout(Cond)) {
isFeasible = true;
return St;
// Just return the current state indicating that the path is feasible.
// This may be an over-approximation of what is possible.
return state;
}
BasicValueFactory& BasicVals = StateMgr.getBasicVals();
SymbolManager& SymMgr = StateMgr.getSymbolManager();
BasicValueFactory &BasicVals = state->getBasicVals();
SymbolManager &SymMgr = state->getSymbolManager();
switch (Cond.getSubKind()) {
default:
@ -162,38 +156,38 @@ SimpleConstraintManager::AssumeAux(const GRState* St,NonLoc Cond,
case nonloc::SymbolValKind: {
nonloc::SymbolVal& SV = cast<nonloc::SymbolVal>(Cond);
SymbolRef sym = SV.getSymbol();
QualType T = SymMgr.getType(sym);
if (Assumption)
return AssumeSymNE(St, sym, BasicVals.getValue(0, T), isFeasible);
else
return AssumeSymEQ(St, sym, BasicVals.getValue(0, T), isFeasible);
QualType T = SymMgr.getType(sym);
const llvm::APSInt &zero = BasicVals.getValue(0, T);
return Assumption ? AssumeSymNE(state, sym, zero)
: AssumeSymEQ(state, sym, zero);
}
case nonloc::SymExprValKind: {
nonloc::SymExprVal V = cast<nonloc::SymExprVal>(Cond);
if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(V.getSymbolicExpression()))
return AssumeSymInt(St, Assumption, SE, isFeasible);
return AssumeSymInt(state, Assumption, SE);
isFeasible = true;
return St;
// For all other symbolic expressions, over-approximate and consider
// the constraint feasible.
return state;
}
case nonloc::ConcreteIntKind: {
bool b = cast<nonloc::ConcreteInt>(Cond).getValue() != 0;
isFeasible = b ? Assumption : !Assumption;
return St;
bool isFeasible = b ? Assumption : !Assumption;
return isFeasible ? state : NULL;
}
case nonloc::LocAsIntegerKind:
return AssumeAux(St, cast<nonloc::LocAsInteger>(Cond).getLoc(),
Assumption, isFeasible);
return AssumeAux(state, cast<nonloc::LocAsInteger>(Cond).getLoc(),
Assumption);
} // end switch
}
const GRState*
SimpleConstraintManager::AssumeSymInt(const GRState* St, bool Assumption,
const SymIntExpr *SE, bool& isFeasible) {
const GRState *SimpleConstraintManager::AssumeSymInt(const GRState *state,
bool Assumption,
const SymIntExpr *SE) {
// Here we assume that LHS is a symbol. This is consistent with the
@ -203,47 +197,44 @@ SimpleConstraintManager::AssumeSymInt(const GRState* St, bool Assumption,
switch (SE->getOpcode()) {
default:
// No logic yet for other operators.
isFeasible = true;
return St;
// No logic yet for other operators. Assume the constraint is feasible.
return state;
case BinaryOperator::EQ:
return Assumption ? AssumeSymEQ(St, Sym, Int, isFeasible)
: AssumeSymNE(St, Sym, Int, isFeasible);
return Assumption ? AssumeSymEQ(state, Sym, Int)
: AssumeSymNE(state, Sym, Int);
case BinaryOperator::NE:
return Assumption ? AssumeSymNE(St, Sym, Int, isFeasible)
: AssumeSymEQ(St, Sym, Int, isFeasible);
return Assumption ? AssumeSymNE(state, Sym, Int)
: AssumeSymEQ(state, Sym, Int);
case BinaryOperator::GT:
return Assumption ? AssumeSymGT(St, Sym, Int, isFeasible)
: AssumeSymLE(St, Sym, Int, isFeasible);
return Assumption ? AssumeSymGT(state, Sym, Int)
: AssumeSymLE(state, Sym, Int);
case BinaryOperator::GE:
return Assumption ? AssumeSymGE(St, Sym, Int, isFeasible)
: AssumeSymLT(St, Sym, Int, isFeasible);
return Assumption ? AssumeSymGE(state, Sym, Int)
: AssumeSymLT(state, Sym, Int);
case BinaryOperator::LT:
return Assumption ? AssumeSymLT(St, Sym, Int, isFeasible)
: AssumeSymGE(St, Sym, Int, isFeasible);
return Assumption ? AssumeSymLT(state, Sym, Int)
: AssumeSymGE(state, Sym, Int);
case BinaryOperator::LE:
return Assumption ? AssumeSymLE(St, Sym, Int, isFeasible)
: AssumeSymGT(St, Sym, Int, isFeasible);
return Assumption ? AssumeSymLE(state, Sym, Int)
: AssumeSymGT(state, Sym, Int);
} // end switch
}
const GRState*
SimpleConstraintManager::AssumeInBound(const GRState* St, SVal Idx,
SVal UpperBound, bool Assumption,
bool& isFeasible) {
// Only support ConcreteInt for now.
if (!(isa<nonloc::ConcreteInt>(Idx) && isa<nonloc::ConcreteInt>(UpperBound))){
isFeasible = true;
return St;
}
const GRState *SimpleConstraintManager::AssumeInBound(const GRState *state,
SVal Idx,
SVal UpperBound,
bool Assumption) {
const llvm::APSInt& Zero = getBasicVals().getZeroWithPtrWidth(false);
// Only support ConcreteInt for now.
if (!(isa<nonloc::ConcreteInt>(Idx) && isa<nonloc::ConcreteInt>(UpperBound)))
return state;
const llvm::APSInt& Zero = state->getBasicVals().getZeroWithPtrWidth(false);
llvm::APSInt IdxV = cast<nonloc::ConcreteInt>(Idx).getValue();
// IdxV might be too narrow.
if (IdxV.getBitWidth() < Zero.getBitWidth())
@ -254,10 +245,8 @@ SimpleConstraintManager::AssumeInBound(const GRState* St, SVal Idx,
UBV.extend(Zero.getBitWidth());
bool InBound = (Zero <= IdxV) && (IdxV < UBV);
isFeasible = Assumption ? InBound : !InBound;
return St;
bool isFeasible = Assumption ? InBound : !InBound;
return isFeasible ? state : NULL;
}
} // end of namespace clang

View File

@ -20,63 +20,59 @@
namespace clang {
class SimpleConstraintManager : public ConstraintManager {
protected:
GRStateManager& StateMgr;
public:
SimpleConstraintManager(GRStateManager& statemgr)
: StateMgr(statemgr) {}
virtual ~SimpleConstraintManager();
SimpleConstraintManager() {}
virtual ~SimpleConstraintManager();
//===------------------------------------------------------------------===//
// Common implementation for the interface provided by ConstraintManager.
//===------------------------------------------------------------------===//
bool canReasonAbout(SVal X) const;
const GRState *Assume(const GRState *state, SVal Cond, bool Assumption);
const GRState *Assume(const GRState *state, Loc Cond, bool Assumption);
const GRState *Assume(const GRState *state, NonLoc Cond, bool Assumption);
const GRState *AssumeSymInt(const GRState *state, bool Assumption,
const SymIntExpr *SE);
virtual const GRState* Assume(const GRState* St, SVal Cond, bool Assumption,
bool& isFeasible);
const GRState *AssumeInBound(const GRState *state, SVal Idx, SVal UpperBound,
bool Assumption);
protected:
//===------------------------------------------------------------------===//
// Interface that subclasses must implement.
//===------------------------------------------------------------------===//
virtual const GRState *AssumeSymNE(const GRState *state, SymbolRef sym,
const llvm::APSInt& V) = 0;
const GRState* Assume(const GRState* St, Loc Cond, bool Assumption,
bool& isFeasible);
virtual const GRState *AssumeSymEQ(const GRState *state, SymbolRef sym,
const llvm::APSInt& V) = 0;
const GRState* AssumeAux(const GRState* St, Loc Cond,bool Assumption,
bool& isFeasible);
virtual const GRState *AssumeSymLT(const GRState *state, SymbolRef sym,
const llvm::APSInt& V) = 0;
const GRState* Assume(const GRState* St, NonLoc Cond, bool Assumption,
bool& isFeasible);
virtual const GRState *AssumeSymGT(const GRState *state, SymbolRef sym,
const llvm::APSInt& V) = 0;
const GRState* AssumeAux(const GRState* St, NonLoc Cond, bool Assumption,
bool& isFeasible);
virtual const GRState *AssumeSymLE(const GRState *state, SymbolRef sym,
const llvm::APSInt& V) = 0;
const GRState* AssumeSymInt(const GRState* St, bool Assumption,
const SymIntExpr *SE, bool& isFeasible);
virtual const GRState* AssumeSymNE(const GRState* St, SymbolRef sym,
const llvm::APSInt& V,
bool& isFeasible) = 0;
virtual const GRState* AssumeSymEQ(const GRState* St, SymbolRef sym,
const llvm::APSInt& V,
bool& isFeasible) = 0;
virtual const GRState* AssumeSymLT(const GRState* St, SymbolRef sym,
const llvm::APSInt& V,
bool& isFeasible) = 0;
virtual const GRState* AssumeSymGT(const GRState* St, SymbolRef sym,
const llvm::APSInt& V,
bool& isFeasible) = 0;
virtual const GRState* AssumeSymLE(const GRState* St, SymbolRef sym,
const llvm::APSInt& V,
bool& isFeasible) = 0;
virtual const GRState* AssumeSymGE(const GRState* St, SymbolRef sym,
const llvm::APSInt& V,
bool& isFeasible) = 0;
const GRState* AssumeInBound(const GRState* St, SVal Idx, SVal UpperBound,
bool Assumption, bool& isFeasible);
private:
BasicValueFactory& getBasicVals() { return StateMgr.getBasicVals(); }
SymbolManager& getSymbolManager() const { return StateMgr.getSymbolManager(); }
virtual const GRState *AssumeSymGE(const GRState *state, SymbolRef sym,
const llvm::APSInt& V) = 0;
//===------------------------------------------------------------------===//
// Internal implementation.
//===------------------------------------------------------------------===//
const GRState *AssumeAux(const GRState *state, Loc Cond,bool Assumption);
const GRState *AssumeAux(const GRState *state, NonLoc Cond, bool Assumption);
};
} // end clang namespace

View File

@ -90,7 +90,8 @@ StoreManager::CastRegion(const GRState* state, const MemRegion* R,
// FIXME: Is this the right thing to do in all cases?
const TypedRegion *Base = isa<ElementRegion>(TR) ?
cast<TypedRegion>(TR->getSuperRegion()) : TR;
ElementRegion* ER = MRMgr.getElementRegion(Pointee, Idx, Base);
ElementRegion* ER = MRMgr.getElementRegion(Pointee, Idx, Base,
StateMgr.getContext());
return CastResult(state, ER);
}
}

View File

@ -92,14 +92,14 @@ std::ostream& std::operator<<(std::ostream& os, const SymExpr *SE) {
}
const SymbolRegionValue*
SymbolManager::getRegionValueSymbol(const MemRegion* R) {
SymbolManager::getRegionValueSymbol(const MemRegion* R, QualType T) {
llvm::FoldingSetNodeID profile;
SymbolRegionValue::Profile(profile, R);
SymbolRegionValue::Profile(profile, R, T);
void* InsertPos;
SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
if (!SD) {
SD = (SymExpr*) BPAlloc.Allocate<SymbolRegionValue>();
new (SD) SymbolRegionValue(SymbolCounter, R);
new (SD) SymbolRegionValue(SymbolCounter, R, T);
DataSet.InsertNode(SD, InsertPos);
++SymbolCounter;
}
@ -166,6 +166,9 @@ QualType SymbolConjured::getType(ASTContext&) const {
}
QualType SymbolRegionValue::getType(ASTContext& C) const {
if (!T.isNull())
return T;
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R))
return TR->getValueType(C);

View File

@ -30,11 +30,17 @@ const Builtin::Info &Builtin::Context::GetRecord(unsigned ID) const {
return TSRecords[ID - Builtin::FirstTSBuiltin];
}
Builtin::Context::Context(const TargetInfo &Target) {
// Get the target specific builtins from the target.
TSRecords = 0;
NumTSRecords = 0;
Target.getTargetBuiltins(TSRecords, NumTSRecords);
}
/// InitializeBuiltins - Mark the identifiers for all the builtins with their
/// appropriate builtin ID # and mark any non-portable builtin identifiers as
/// such.
void Builtin::Context::InitializeBuiltins(IdentifierTable &Table,
const TargetInfo &Target,
bool NoBuiltins) {
// Step #1: mark all target-independent builtins with their ID's.
for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i)
@ -42,9 +48,6 @@ void Builtin::Context::InitializeBuiltins(IdentifierTable &Table,
(!NoBuiltins || !strchr(BuiltinInfo[i].Attributes, 'f')))
Table.get(BuiltinInfo[i].Name).setBuiltinID(i);
// Get the target specific builtins from the target.
Target.getTargetBuiltins(TSRecords, NumTSRecords);
// Step #2: Register target-specific builtins.
for (unsigned i = 0, e = NumTSRecords; i != e; ++i)
if (!TSRecords[i].Suppressed &&

View File

@ -118,7 +118,7 @@ const char *Diagnostic::getWarningOptionForDiag(unsigned DiagID) {
bool Diagnostic::isBuiltinSFINAEDiag(unsigned DiagID) {
if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
return Info->SFINAE && Info->Class != CLASS_NOTE;
return Info->SFINAE && Info->Class == CLASS_ERROR;
return false;
}

View File

@ -358,7 +358,10 @@ FileID SourceManager::createFileID(const ContentCache *File,
SLocEntryTable[PreallocatedID]
= SLocEntry::get(Offset, FileInfo::get(IncludePos, File, FileCharacter));
SLocEntryLoaded[PreallocatedID] = true;
return LastFileIDLookup = FileID::get(PreallocatedID);
FileID FID = FileID::get(PreallocatedID);
if (File->FirstFID.isInvalid())
File->FirstFID = FID;
return LastFileIDLookup = FID;
}
SLocEntryTable.push_back(SLocEntry::get(NextOffset,
@ -914,6 +917,43 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc) const {
// Other miscellaneous methods.
//===----------------------------------------------------------------------===//
/// \brief Get the source location for the given file:line:col triplet.
///
/// If the source file is included multiple times, the source location will
/// be based upon the first inclusion.
SourceLocation SourceManager::getLocation(const FileEntry *SourceFile,
unsigned Line, unsigned Col) const {
assert(SourceFile && "Null source file!");
assert(Line && Col && "Line and column should start from 1!");
fileinfo_iterator FI = FileInfos.find(SourceFile);
if (FI == FileInfos.end())
return SourceLocation();
ContentCache *Content = FI->second;
// If this is the first use of line information for this buffer, compute the
/// SourceLineCache for it on demand.
if (Content->SourceLineCache == 0)
ComputeLineNumbers(Content, ContentCacheAlloc);
if (Line > Content->NumLines)
return SourceLocation();
unsigned FilePos = Content->SourceLineCache[Line - 1];
const char *Buf = Content->getBuffer()->getBufferStart();
unsigned BufLength = Content->getBuffer()->getBufferEnd() - Buf;
unsigned i = 0;
// Check that the given column is valid.
while (i < BufLength-1 && i < Col-1 && Buf[i] != '\n' && Buf[i] != '\r')
++i;
if (i < Col-1)
return SourceLocation();
return getLocForStartOfFile(Content->FirstFID).
getFileLocWithOffset(FilePos + Col - 1);
}
/// PrintStats - Print statistics to stderr.
///

View File

@ -522,7 +522,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BIsqrtf:
case Builtin::BIsqrtl: {
// Rewrite sqrt to intrinsic if allowed.
if (!FD->hasAttr<ConstAttr>())
if (!FD->hasAttr<ConstAttr>(getContext()))
break;
Value *Arg0 = EmitScalarExpr(E->getArg(0));
const llvm::Type *ArgType = Arg0->getType();
@ -534,7 +534,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BIpowf:
case Builtin::BIpowl: {
// Rewrite sqrt to intrinsic if allowed.
if (!FD->hasAttr<ConstAttr>())
if (!FD->hasAttr<ConstAttr>(getContext()))
break;
Value *Base = EmitScalarExpr(E->getArg(0));
Value *Exponent = EmitScalarExpr(E->getArg(1));

View File

@ -85,6 +85,11 @@ RValue
CodeGenFunction::EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E,
llvm::Value *AggLoc,
bool isAggLocVolatile) {
// If we shouldn't destroy the temporaries, just emit the
// child expression.
if (!E->shouldDestroyTemporaries())
return EmitAnyExpr(E->getSubExpr(), AggLoc, isAggLocVolatile);
// Keep track of the current cleanup stack depth.
size_t CleanupStackDepth = CleanupEntries.size();
(void) CleanupStackDepth;

View File

@ -377,13 +377,13 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
// FIXME: handle sseregparm someday...
if (TargetDecl) {
if (TargetDecl->hasAttr<NoThrowAttr>())
if (TargetDecl->hasAttr<NoThrowAttr>(getContext()))
FuncAttrs |= llvm::Attribute::NoUnwind;
if (TargetDecl->hasAttr<NoReturnAttr>())
if (TargetDecl->hasAttr<NoReturnAttr>(getContext()))
FuncAttrs |= llvm::Attribute::NoReturn;
if (TargetDecl->hasAttr<ConstAttr>())
if (TargetDecl->hasAttr<ConstAttr>(getContext()))
FuncAttrs |= llvm::Attribute::ReadNone;
else if (TargetDecl->hasAttr<PureAttr>())
else if (TargetDecl->hasAttr<PureAttr>(getContext()))
FuncAttrs |= llvm::Attribute::ReadOnly;
}
@ -432,7 +432,8 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
// register variable.
signed RegParm = 0;
if (TargetDecl)
if (const RegparmAttr *RegParmAttr = TargetDecl->getAttr<RegparmAttr>())
if (const RegparmAttr *RegParmAttr
= TargetDecl->getAttr<RegparmAttr>(getContext()))
RegParm = RegParmAttr->getNumParams();
unsigned PointerWidth = getContext().Target.getPointerWidth(0);

View File

@ -50,6 +50,24 @@ void CGDebugInfo::setLocation(SourceLocation Loc) {
/// getOrCreateCompileUnit - Get the compile unit from the cache or create a new
/// one if necessary. This returns null for invalid source locations.
llvm::DICompileUnit CGDebugInfo::getOrCreateCompileUnit(SourceLocation Loc) {
// Each input file is encoded as a separate compile unit in LLVM
// debugging information output. However, many target specific tool chains
// prefer to encode only one compile unit in an object file. In this
// situation, the LLVM code generator will include debugging information
// entities in the compile unit that is marked as main compile unit. The
// code generator accepts maximum one main compile unit per module. If a
// module does not contain any main compile unit then the code generator
// will emit multiple compile units in the output object file. Create main
// compile unit if there is not one available.
const LangOptions &LO = M->getLangOptions();
if (isMainCompileUnitCreated == false) {
if (LO.getMainFileName()) {
createCompileUnit(LO.getMainFileName(), true /* isMain */);
isMainCompileUnitCreated = true;
}
}
// Get source file information.
const char *FileName = "<unknown>";
SourceManager &SM = M->getContext().getSourceManager();
@ -72,25 +90,26 @@ llvm::DICompileUnit CGDebugInfo::getOrCreateCompileUnit(SourceLocation Loc) {
AbsFileName = tmp;
}
// See if thie compile unit is representing main source file. Each source
// file has corresponding compile unit. There is only one main source
// file at a time.
bool isMain = false;
const LangOptions &LO = M->getLangOptions();
const char *MainFileName = LO.getMainFileName();
if (isMainCompileUnitCreated == false) {
if (MainFileName) {
if (!strcmp(AbsFileName.getLast().c_str(), MainFileName))
isMain = true;
} else {
if (Loc.isValid() && SM.isFromMainFile(Loc))
isMain = true;
}
if (isMain)
isMainCompileUnitCreated = true;
// There is only one main source file at a time whose compile unit
// is already created.
Unit = createCompileUnit(FileName, false /* isMain */);
return Unit;
}
/// createCompileUnit - Create a new unit for the given file.
llvm::DICompileUnit CGDebugInfo::createCompileUnit(const char *FileName,
bool isMain) {
// Get absolute path name.
llvm::sys::Path AbsFileName(FileName);
if (!AbsFileName.isAbsolute()) {
llvm::sys::Path tmp = llvm::sys::Path::GetCurrentDirectory();
tmp.appendComponent(FileName);
AbsFileName = tmp;
}
unsigned LangTag;
const LangOptions &LO = M->getLangOptions();
if (LO.CPlusPlus) {
if (LO.ObjC1)
LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus;
@ -114,12 +133,13 @@ llvm::DICompileUnit CGDebugInfo::getOrCreateCompileUnit(SourceLocation Loc) {
RuntimeVers = LO.ObjCNonFragileABI ? 2 : 1;
// Create new compile unit.
return Unit = DebugFactory.CreateCompileUnit(LangTag, AbsFileName.getLast(),
AbsFileName.getDirname(),
Producer, isMain, isOptimized,
Flags, RuntimeVers);
return DebugFactory.CreateCompileUnit(LangTag, AbsFileName.getLast(),
AbsFileName.getDirname(),
Producer, isMain, isOptimized,
Flags, RuntimeVers);
}
/// CreateType - Get the Basic type from the cache or create a new
/// one if necessary.
llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT,
@ -761,7 +781,7 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty,
case Type::QualifiedName:
// Unsupported types
return llvm::DIType();
case Type::ObjCQualifiedId: // Encode id<p> in debug info just like id.
case Type::ObjCObjectPointer: // Encode id<p> in debug info just like id.
return Slot = getOrCreateType(M->getContext().getObjCIdType(), Unit);
case Type::ObjCQualifiedInterface: // Drop protocols from interface.

View File

@ -111,7 +111,9 @@ class CGDebugInfo {
void EmitDeclare(const VarDecl *decl, unsigned Tag, llvm::Value *AI,
CGBuilderTy &Builder);
/// createCompileUnit - Create a new unit for the given file.
llvm::DICompileUnit createCompileUnit(const char *FileName, bool isMain);
/// getOrCreateCompileUnit - Get the compile unit from the cache or create a
/// new one if necessary.
llvm::DICompileUnit getOrCreateCompileUnit(SourceLocation Loc);

View File

@ -60,7 +60,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
/// EmitBlockVarDecl - This method handles emission of any variable declaration
/// inside a function, including static vars etc.
void CodeGenFunction::EmitBlockVarDecl(const VarDecl &D) {
if (D.hasAttr<AsmLabelAttr>())
if (D.hasAttr<AsmLabelAttr>(getContext()))
CGM.ErrorUnsupported(&D, "__asm__");
switch (D.getStorageClass()) {
@ -171,7 +171,7 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) {
}
// FIXME: Merge attribute handling.
if (const AnnotateAttr *AA = D.getAttr<AnnotateAttr>()) {
if (const AnnotateAttr *AA = D.getAttr<AnnotateAttr>(getContext())) {
SourceManager &SM = CGM.getContext().getSourceManager();
llvm::Constant *Ann =
CGM.EmitAnnotateAttr(GV, AA,
@ -179,10 +179,10 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) {
CGM.AddAnnotation(Ann);
}
if (const SectionAttr *SA = D.getAttr<SectionAttr>())
if (const SectionAttr *SA = D.getAttr<SectionAttr>(getContext()))
GV->setSection(SA->getName());
if (D.hasAttr<UsedAttr>())
if (D.hasAttr<UsedAttr>(getContext()))
CGM.AddUsedGlobal(GV);
// We may have to cast the constant because of the initializer
@ -244,7 +244,7 @@ const llvm::Type *CodeGenFunction::BuildByRefType(QualType Ty,
/// These turn into simple stack objects, or GlobalValues depending on target.
void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
QualType Ty = D.getType();
bool isByRef = D.hasAttr<BlocksAttr>();
bool isByRef = D.hasAttr<BlocksAttr>(getContext());
bool needsDispose = false;
unsigned Align = 0;
@ -414,7 +414,7 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
}
// Handle the cleanup attribute
if (const CleanupAttr *CA = D.getAttr<CleanupAttr>()) {
if (const CleanupAttr *CA = D.getAttr<CleanupAttr>(getContext())) {
const FunctionDecl *FD = CA->getFunctionDecl();
llvm::Constant* F = CGM.GetAddrOfFunction(GlobalDecl(FD));

View File

@ -668,7 +668,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
if (VD && (VD->isBlockVarDecl() || isa<ParmVarDecl>(VD) ||
isa<ImplicitParamDecl>(VD))) {
LValue LV;
bool NonGCable = VD->hasLocalStorage() && !VD->hasAttr<BlocksAttr>();
bool NonGCable = VD->hasLocalStorage() &&
!VD->hasAttr<BlocksAttr>(getContext());
if (VD->hasExternalStorage()) {
llvm::Value *V = CGM.GetAddrOfGlobalVar(VD);
if (VD->getType()->isReferenceType())
@ -684,7 +685,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
// local static?
if (!NonGCable)
attr = getContext().getObjCGCAttrKind(E->getType());
if (VD->hasAttr<BlocksAttr>()) {
if (VD->hasAttr<BlocksAttr>(getContext())) {
bool needsCopyDispose = BlockRequiresCopying(VD->getType());
const llvm::Type *PtrStructTy = V->getType();
const llvm::Type *Ty = PtrStructTy;

View File

@ -365,23 +365,28 @@ ComplexPairTy ComplexExprEmitter::EmitCast(Expr *Op, QualType DestTy) {
ComplexPairTy ComplexExprEmitter::VisitPrePostIncDec(const UnaryOperator *E,
bool isInc, bool isPre) {
LValue LV = CGF.EmitLValue(E->getSubExpr());
ComplexPairTy InVal = EmitLoadOfComplex(LV.getAddress(), LV.isVolatileQualified());
ComplexPairTy InVal = EmitLoadOfComplex(LV.getAddress(),
LV.isVolatileQualified());
llvm::Value *NextVal;
if (isa<llvm::IntegerType>(InVal.first->getType())) {
uint64_t AmountVal = isInc ? 1 : -1;
NextVal = llvm::ConstantInt::get(InVal.first->getType(), AmountVal, true);
// Add the inc/dec to the real part.
NextVal = Builder.CreateAdd(InVal.first, NextVal, isInc ? "inc" : "dec");
} else {
QualType ElemTy = E->getType()->getAsComplexType()->getElementType();
llvm::APFloat FVal(CGF.getContext().getFloatTypeSemantics(ElemTy), 1);
if (!isInc)
FVal.changeSign();
NextVal = llvm::ConstantFP::get(FVal);
// Add the inc/dec to the real part.
NextVal = Builder.CreateFAdd(InVal.first, NextVal, isInc ? "inc" : "dec");
}
// Add the inc/dec to the real part.
NextVal = Builder.CreateAdd(InVal.first, NextVal, isInc ? "inc" : "dec");
ComplexPairTy IncVal(NextVal, InVal.second);
// Store the updated result through the lvalue.
@ -398,8 +403,15 @@ ComplexPairTy ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *E) {
TestAndClearIgnoreRealAssign();
TestAndClearIgnoreImagAssign();
ComplexPairTy Op = Visit(E->getSubExpr());
llvm::Value *ResR = Builder.CreateNeg(Op.first, "neg.r");
llvm::Value *ResI = Builder.CreateNeg(Op.second, "neg.i");
llvm::Value *ResR, *ResI;
if (Op.first->getType()->isFloatingPoint()) {
ResR = Builder.CreateFNeg(Op.first, "neg.r");
ResI = Builder.CreateFNeg(Op.second, "neg.i");
} else {
ResR = Builder.CreateNeg(Op.first, "neg.r");
ResI = Builder.CreateNeg(Op.second, "neg.i");
}
return ComplexPairTy(ResR, ResI);
}
@ -410,31 +422,62 @@ ComplexPairTy ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *E) {
TestAndClearIgnoreImagAssign();
// ~(a+ib) = a + i*-b
ComplexPairTy Op = Visit(E->getSubExpr());
llvm::Value *ResI = Builder.CreateNeg(Op.second, "conj.i");
llvm::Value *ResI;
if (Op.second->getType()->isFloatingPoint())
ResI = Builder.CreateFNeg(Op.second, "conj.i");
else
ResI = Builder.CreateNeg(Op.second, "conj.i");
return ComplexPairTy(Op.first, ResI);
}
ComplexPairTy ComplexExprEmitter::EmitBinAdd(const BinOpInfo &Op) {
llvm::Value *ResR = Builder.CreateAdd(Op.LHS.first, Op.RHS.first, "add.r");
llvm::Value *ResI = Builder.CreateAdd(Op.LHS.second, Op.RHS.second, "add.i");
llvm::Value *ResR, *ResI;
if (Op.LHS.first->getType()->isFloatingPoint()) {
ResR = Builder.CreateFAdd(Op.LHS.first, Op.RHS.first, "add.r");
ResI = Builder.CreateFAdd(Op.LHS.second, Op.RHS.second, "add.i");
} else {
ResR = Builder.CreateAdd(Op.LHS.first, Op.RHS.first, "add.r");
ResI = Builder.CreateAdd(Op.LHS.second, Op.RHS.second, "add.i");
}
return ComplexPairTy(ResR, ResI);
}
ComplexPairTy ComplexExprEmitter::EmitBinSub(const BinOpInfo &Op) {
llvm::Value *ResR = Builder.CreateSub(Op.LHS.first, Op.RHS.first, "sub.r");
llvm::Value *ResI = Builder.CreateSub(Op.LHS.second, Op.RHS.second, "sub.i");
llvm::Value *ResR, *ResI;
if (Op.LHS.first->getType()->isFloatingPoint()) {
ResR = Builder.CreateFSub(Op.LHS.first, Op.RHS.first, "sub.r");
ResI = Builder.CreateFSub(Op.LHS.second, Op.RHS.second, "sub.i");
} else {
ResR = Builder.CreateSub(Op.LHS.first, Op.RHS.first, "sub.r");
ResI = Builder.CreateSub(Op.LHS.second, Op.RHS.second, "sub.i");
}
return ComplexPairTy(ResR, ResI);
}
ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) {
llvm::Value *ResRl = Builder.CreateMul(Op.LHS.first, Op.RHS.first, "mul.rl");
llvm::Value *ResRr = Builder.CreateMul(Op.LHS.second, Op.RHS.second,"mul.rr");
llvm::Value *ResR = Builder.CreateSub(ResRl, ResRr, "mul.r");
using llvm::Value;
Value *ResR, *ResI;
llvm::Value *ResIl = Builder.CreateMul(Op.LHS.second, Op.RHS.first, "mul.il");
llvm::Value *ResIr = Builder.CreateMul(Op.LHS.first, Op.RHS.second, "mul.ir");
llvm::Value *ResI = Builder.CreateAdd(ResIl, ResIr, "mul.i");
if (Op.LHS.first->getType()->isFloatingPoint()) {
Value *ResRl = Builder.CreateFMul(Op.LHS.first, Op.RHS.first, "mul.rl");
Value *ResRr = Builder.CreateFMul(Op.LHS.second, Op.RHS.second,"mul.rr");
ResR = Builder.CreateFSub(ResRl, ResRr, "mul.r");
Value *ResIl = Builder.CreateFMul(Op.LHS.second, Op.RHS.first, "mul.il");
Value *ResIr = Builder.CreateFMul(Op.LHS.first, Op.RHS.second, "mul.ir");
ResI = Builder.CreateFAdd(ResIl, ResIr, "mul.i");
} else {
Value *ResRl = Builder.CreateMul(Op.LHS.first, Op.RHS.first, "mul.rl");
Value *ResRr = Builder.CreateMul(Op.LHS.second, Op.RHS.second,"mul.rr");
ResR = Builder.CreateSub(ResRl, ResRr, "mul.r");
Value *ResIl = Builder.CreateMul(Op.LHS.second, Op.RHS.first, "mul.il");
Value *ResIr = Builder.CreateMul(Op.LHS.first, Op.RHS.second, "mul.ir");
ResI = Builder.CreateAdd(ResIl, ResIr, "mul.i");
}
return ComplexPairTy(ResR, ResI);
}
@ -442,24 +485,38 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) {
llvm::Value *LHSr = Op.LHS.first, *LHSi = Op.LHS.second;
llvm::Value *RHSr = Op.RHS.first, *RHSi = Op.RHS.second;
// (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd))
llvm::Value *Tmp1 = Builder.CreateMul(LHSr, RHSr, "tmp"); // a*c
llvm::Value *Tmp2 = Builder.CreateMul(LHSi, RHSi, "tmp"); // b*d
llvm::Value *Tmp3 = Builder.CreateAdd(Tmp1, Tmp2, "tmp"); // ac+bd
llvm::Value *Tmp4 = Builder.CreateMul(RHSr, RHSr, "tmp"); // c*c
llvm::Value *Tmp5 = Builder.CreateMul(RHSi, RHSi, "tmp"); // d*d
llvm::Value *Tmp6 = Builder.CreateAdd(Tmp4, Tmp5, "tmp"); // cc+dd
llvm::Value *Tmp7 = Builder.CreateMul(LHSi, RHSr, "tmp"); // b*c
llvm::Value *Tmp8 = Builder.CreateMul(LHSr, RHSi, "tmp"); // a*d
llvm::Value *Tmp9 = Builder.CreateSub(Tmp7, Tmp8, "tmp"); // bc-ad
llvm::Value *DSTr, *DSTi;
if (Tmp3->getType()->isFloatingPoint()) {
if (Op.LHS.first->getType()->isFloatingPoint()) {
// (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd))
llvm::Value *Tmp1 = Builder.CreateFMul(LHSr, RHSr, "tmp"); // a*c
llvm::Value *Tmp2 = Builder.CreateFMul(LHSi, RHSi, "tmp"); // b*d
llvm::Value *Tmp3 = Builder.CreateFAdd(Tmp1, Tmp2, "tmp"); // ac+bd
llvm::Value *Tmp4 = Builder.CreateFMul(RHSr, RHSr, "tmp"); // c*c
llvm::Value *Tmp5 = Builder.CreateFMul(RHSi, RHSi, "tmp"); // d*d
llvm::Value *Tmp6 = Builder.CreateFAdd(Tmp4, Tmp5, "tmp"); // cc+dd
llvm::Value *Tmp7 = Builder.CreateFMul(LHSi, RHSr, "tmp"); // b*c
llvm::Value *Tmp8 = Builder.CreateFMul(LHSr, RHSi, "tmp"); // a*d
llvm::Value *Tmp9 = Builder.CreateFSub(Tmp7, Tmp8, "tmp"); // bc-ad
DSTr = Builder.CreateFDiv(Tmp3, Tmp6, "tmp");
DSTi = Builder.CreateFDiv(Tmp9, Tmp6, "tmp");
} else {
// (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd))
llvm::Value *Tmp1 = Builder.CreateMul(LHSr, RHSr, "tmp"); // a*c
llvm::Value *Tmp2 = Builder.CreateMul(LHSi, RHSi, "tmp"); // b*d
llvm::Value *Tmp3 = Builder.CreateAdd(Tmp1, Tmp2, "tmp"); // ac+bd
llvm::Value *Tmp4 = Builder.CreateMul(RHSr, RHSr, "tmp"); // c*c
llvm::Value *Tmp5 = Builder.CreateMul(RHSi, RHSi, "tmp"); // d*d
llvm::Value *Tmp6 = Builder.CreateAdd(Tmp4, Tmp5, "tmp"); // cc+dd
llvm::Value *Tmp7 = Builder.CreateMul(LHSi, RHSr, "tmp"); // b*c
llvm::Value *Tmp8 = Builder.CreateMul(LHSr, RHSi, "tmp"); // a*d
llvm::Value *Tmp9 = Builder.CreateSub(Tmp7, Tmp8, "tmp"); // bc-ad
if (Op.Ty->getAsComplexType()->getElementType()->isUnsignedIntegerType()) {
DSTr = Builder.CreateUDiv(Tmp3, Tmp6, "tmp");
DSTi = Builder.CreateUDiv(Tmp9, Tmp6, "tmp");

View File

@ -198,16 +198,13 @@ class VISIBILITY_HIDDEN ConstExprEmitter :
// Copy initializer elements. Skip padding fields.
unsigned EltNo = 0; // Element no in ILE
int FieldNo = 0; // Field no in RecordDecl
bool RewriteType = false;
for (RecordDecl::field_iterator Field = RD->field_begin(CGM.getContext()),
FieldEnd = RD->field_end(CGM.getContext());
EltNo < ILE->getNumInits() && Field != FieldEnd; ++Field) {
FieldNo++;
if (!Field->getIdentifier())
continue;
if (Field->isBitField()) {
if (!Field->getIdentifier())
continue;
InsertBitfieldIntoStruct(Elts, *Field, ILE->getInit(EltNo));
} else {
unsigned FieldNo = CGM.getTypes().getLLVMFieldNo(*Field);

View File

@ -294,6 +294,8 @@ class VISIBILITY_HIDDEN ScalarExprEmitter
if (CGF.getContext().getLangOptions().OverflowChecking
&& Ops.Ty->isSignedIntegerType())
return EmitOverflowCheckedBinOp(Ops);
if (Ops.LHS->getType()->isFPOrFPVector())
return Builder.CreateFMul(Ops.LHS, Ops.RHS, "mul");
return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
}
/// Create a binary op that checks for overflow.
@ -699,11 +701,12 @@ Value *ScalarExprEmitter::VisitPrePostIncDec(const UnaryOperator *E,
// An interesting aspect of this is that increment is always true.
// Decrement does not have this property.
NextVal = llvm::ConstantInt::getTrue();
} else if (isa<llvm::IntegerType>(InVal->getType())) {
NextVal = llvm::ConstantInt::get(InVal->getType(), AmountVal);
NextVal = Builder.CreateAdd(InVal, NextVal, isInc ? "inc" : "dec");
} else {
// Add the inc/dec to the real part.
if (isa<llvm::IntegerType>(InVal->getType()))
NextVal = llvm::ConstantInt::get(InVal->getType(), AmountVal);
else if (InVal->getType() == llvm::Type::FloatTy)
if (InVal->getType() == llvm::Type::FloatTy)
NextVal =
llvm::ConstantFP::get(llvm::APFloat(static_cast<float>(AmountVal)));
else if (InVal->getType() == llvm::Type::DoubleTy)
@ -716,7 +719,7 @@ Value *ScalarExprEmitter::VisitPrePostIncDec(const UnaryOperator *E,
&ignored);
NextVal = llvm::ConstantFP::get(F);
}
NextVal = Builder.CreateAdd(InVal, NextVal, isInc ? "inc" : "dec");
NextVal = Builder.CreateFAdd(InVal, NextVal, isInc ? "inc" : "dec");
}
// Store the updated result through the lvalue.
@ -735,6 +738,8 @@ Value *ScalarExprEmitter::VisitPrePostIncDec(const UnaryOperator *E,
Value *ScalarExprEmitter::VisitUnaryMinus(const UnaryOperator *E) {
TestAndClearIgnoreResultAssign();
Value *Op = Visit(E->getSubExpr());
if (Op->getType()->isFPOrFPVector())
return Builder.CreateFNeg(Op, "neg");
return Builder.CreateNeg(Op, "neg");
}
@ -982,9 +987,13 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) {
Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) {
if (!Ops.Ty->isPointerType()) {
if (CGF.getContext().getLangOptions().OverflowChecking
&& Ops.Ty->isSignedIntegerType())
if (CGF.getContext().getLangOptions().OverflowChecking &&
Ops.Ty->isSignedIntegerType())
return EmitOverflowCheckedBinOp(Ops);
if (Ops.LHS->getType()->isFPOrFPVector())
return Builder.CreateFAdd(Ops.LHS, Ops.RHS, "add");
return Builder.CreateAdd(Ops.LHS, Ops.RHS, "add");
}
@ -1050,6 +1059,9 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &Ops) {
if (CGF.getContext().getLangOptions().OverflowChecking
&& Ops.Ty->isSignedIntegerType())
return EmitOverflowCheckedBinOp(Ops);
if (Ops.LHS->getType()->isFPOrFPVector())
return Builder.CreateFSub(Ops.LHS, Ops.RHS, "sub");
return Builder.CreateSub(Ops.LHS, Ops.RHS, "sub");
}

View File

@ -126,7 +126,7 @@ void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD,
/// its pointer, name, and types registered in the class struture.
void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) {
// Check if we should generate debug info for this method.
if (CGM.getDebugInfo() && !OMD->hasAttr<NodebugAttr>())
if (CGM.getDebugInfo() && !OMD->hasAttr<NodebugAttr>(getContext()))
DebugInfo = CGM.getDebugInfo();
StartObjCMethod(OMD, OMD->getClassInterface());
EmitStmt(OMD->getBody(getContext()));

View File

@ -104,6 +104,7 @@ class CGObjCGNU : public CodeGen::CGObjCRuntime {
std::vector<llvm::Constant*> &V, const std::string &Name="");
llvm::GlobalVariable *ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
const ObjCIvarDecl *Ivar);
void EmitClassRef(const std::string &className);
public:
CGObjCGNU(CodeGen::CodeGenModule &cgm);
virtual llvm::Constant *GenerateConstantString(const ObjCStringLiteral *);
@ -168,15 +169,31 @@ class CGObjCGNU : public CodeGen::CGObjCRuntime {
} // end anonymous namespace
/// Emits a reference to a dummy variable which is emitted with each class.
/// This ensures that a linker error will be generated when trying to link
/// together modules where a referenced class is not defined.
void CGObjCGNU::EmitClassRef(const std::string &className){
std::string symbolRef = "__objc_class_ref_" + className;
// Don't emit two copies of the same symbol
if (TheModule.getGlobalVariable(symbolRef)) return;
std::string symbolName = "__objc_class_name_" + className;
llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(symbolName);
if (!ClassSymbol) {
ClassSymbol = new llvm::GlobalVariable(LongTy, false,
llvm::GlobalValue::ExternalLinkage, 0, symbolName, &TheModule);
}
new llvm::GlobalVariable(ClassSymbol->getType(), true,
llvm::GlobalValue::CommonLinkage, ClassSymbol, symbolRef, &TheModule);
}
static std::string SymbolNameForClass(const std::string &ClassName) {
return "___objc_class_name_" + ClassName;
return "_OBJC_CLASS_" + ClassName;
}
static std::string SymbolNameForMethod(const std::string &ClassName, const
std::string &CategoryName, const std::string &MethodName, bool isClassMethod)
{
return "._objc_method_" + ClassName +"("+CategoryName+")"+
return "_OBJC_METHOD_" + ClassName + "("+CategoryName+")"+
(isClassMethod ? "+" : "-") + MethodName;
}
@ -217,6 +234,7 @@ CGObjCGNU::CGObjCGNU(CodeGen::CodeGenModule &cgm)
llvm::Value *CGObjCGNU::GetClass(CGBuilderTy &Builder,
const ObjCInterfaceDecl *OID) {
llvm::Value *ClassName = CGM.GetAddrOfConstantCString(OID->getNameAsString());
EmitClassRef(OID->getNameAsString());
ClassName = Builder.CreateStructGEP(ClassName, 0);
std::vector<const llvm::Type*> Params(1, PtrToInt8Ty);
@ -831,14 +849,21 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
const ObjCInterfaceDecl * SuperClassDecl =
OID->getClassInterface()->getSuperClass();
std::string SuperClassName;
if (SuperClassDecl)
if (SuperClassDecl) {
SuperClassName = SuperClassDecl->getNameAsString();
EmitClassRef(SuperClassName);
}
// Get the class name
ObjCInterfaceDecl *ClassDecl =
const_cast<ObjCInterfaceDecl *>(OID->getClassInterface());
std::string ClassName = ClassDecl->getNameAsString();
// Emit the symbol that is used to generate linker errors if this class is
// referenced in other modules but not declared.
new llvm::GlobalVariable(LongTy, false, llvm::GlobalValue::ExternalLinkage,
llvm::ConstantInt::get(LongTy, 0), "__objc_class_name_" + ClassName,
&TheModule);
// Get the size of instances.
int instanceSize = Context.getASTObjCImplementationLayout(OID).getSize() / 8;

View File

@ -1356,11 +1356,12 @@ static llvm::Constant *getConstantGEP(llvm::Constant *C,
/// hasObjCExceptionAttribute - Return true if this class or any super
/// class has the __objc_exception__ attribute.
static bool hasObjCExceptionAttribute(const ObjCInterfaceDecl *OID) {
if (OID->hasAttr<ObjCExceptionAttr>())
static bool hasObjCExceptionAttribute(ASTContext &Context,
const ObjCInterfaceDecl *OID) {
if (OID->hasAttr<ObjCExceptionAttr>(Context))
return true;
if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
return hasObjCExceptionAttribute(Super);
return hasObjCExceptionAttribute(Context, Super);
return false;
}
@ -4402,7 +4403,7 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
if (classIsHidden)
flags |= OBJC2_CLS_HIDDEN;
if (hasObjCExceptionAttribute(ID->getClassInterface()))
if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
flags |= CLS_EXCEPTION;
if (!ID->getClassInterface()->getSuperClass()) {
@ -5686,7 +5687,7 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
// If this type (or a super class) has the __objc_exception__
// attribute, emit an external reference.
if (hasObjCExceptionAttribute(ID))
if (hasObjCExceptionAttribute(CGM.getContext(), ID))
return Entry =
new llvm::GlobalVariable(ObjCTypes.EHTypeTy, false,
llvm::GlobalValue::ExternalLinkage,

View File

@ -199,7 +199,7 @@ void CodeGenFunction::StartFunction(const Decl *D, QualType RetTy,
void CodeGenFunction::GenerateCode(const FunctionDecl *FD,
llvm::Function *Fn) {
// Check if we should generate debug info for this function.
if (CGM.getDebugInfo() && !FD->hasAttr<NodebugAttr>())
if (CGM.getDebugInfo() && !FD->hasAttr<NodebugAttr>(getContext()))
DebugInfo = CGM.getDebugInfo();
FunctionArgList Args;

View File

@ -102,7 +102,7 @@ CodeGenModule::getDeclVisibilityMode(const Decl *D) const {
if (VD->getStorageClass() == VarDecl::PrivateExtern)
return LangOptions::Hidden;
if (const VisibilityAttr *attr = D->getAttr<VisibilityAttr>()) {
if (const VisibilityAttr *attr = D->getAttr<VisibilityAttr>(getContext())) {
switch (attr->getVisibility()) {
default: assert(0 && "Unknown visibility!");
case VisibilityAttr::DefaultVisibility:
@ -241,10 +241,11 @@ void CodeGenModule::EmitAnnotations() {
}
static CodeGenModule::GVALinkage
GetLinkageForFunction(const FunctionDecl *FD, const LangOptions &Features) {
GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD,
const LangOptions &Features) {
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
// C++ member functions defined inside the class are always inline.
if (MD->isInline() || !MD->isOutOfLineDefinition())
if (MD->isInline() || !MD->isOutOfLine())
return CodeGenModule::GVA_CXXInline;
return CodeGenModule::GVA_StrongExternal;
@ -265,11 +266,11 @@ GetLinkageForFunction(const FunctionDecl *FD, const LangOptions &Features) {
return CodeGenModule::GVA_C99Inline;
// Normal inline is a strong symbol.
return CodeGenModule::GVA_StrongExternal;
} else if (FD->hasActiveGNUInlineAttribute()) {
} else if (FD->hasActiveGNUInlineAttribute(Context)) {
// GCC in C99 mode seems to use a different decision-making
// process for extern inline, which factors in previous
// declarations.
if (FD->isExternGNUInline())
if (FD->isExternGNUInline(Context))
return CodeGenModule::GVA_C99Inline;
// Normal inline is a strong symbol.
return CodeGenModule::GVA_StrongExternal;
@ -293,13 +294,13 @@ GetLinkageForFunction(const FunctionDecl *FD, const LangOptions &Features) {
/// variables (these details are set in EmitGlobalVarDefinition for variables).
void CodeGenModule::SetFunctionDefinitionAttributes(const FunctionDecl *D,
llvm::GlobalValue *GV) {
GVALinkage Linkage = GetLinkageForFunction(D, Features);
GVALinkage Linkage = GetLinkageForFunction(getContext(), D, Features);
if (Linkage == GVA_Internal) {
GV->setLinkage(llvm::Function::InternalLinkage);
} else if (D->hasAttr<DLLExportAttr>()) {
} else if (D->hasAttr<DLLExportAttr>(getContext())) {
GV->setLinkage(llvm::Function::DLLExportLinkage);
} else if (D->hasAttr<WeakAttr>()) {
} else if (D->hasAttr<WeakAttr>(getContext())) {
GV->setLinkage(llvm::Function::WeakAnyLinkage);
} else if (Linkage == GVA_C99Inline) {
// In C99 mode, 'inline' functions are guaranteed to have a strong
@ -332,10 +333,10 @@ void CodeGenModule::SetLLVMFunctionAttributes(const Decl *D,
AttributeList.size()));
// Set the appropriate calling convention for the Function.
if (D->hasAttr<FastCallAttr>())
if (D->hasAttr<FastCallAttr>(getContext()))
F->setCallingConv(llvm::CallingConv::X86_FastCall);
if (D->hasAttr<StdCallAttr>())
if (D->hasAttr<StdCallAttr>(getContext()))
F->setCallingConv(llvm::CallingConv::X86_StdCall);
}
@ -344,10 +345,10 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
if (!Features.Exceptions && !Features.ObjCNonFragileABI)
F->addFnAttr(llvm::Attribute::NoUnwind);
if (D->hasAttr<AlwaysInlineAttr>())
if (D->hasAttr<AlwaysInlineAttr>(getContext()))
F->addFnAttr(llvm::Attribute::AlwaysInline);
if (D->hasAttr<NoinlineAttr>())
if (D->hasAttr<NoinlineAttr>(getContext()))
F->addFnAttr(llvm::Attribute::NoInline);
}
@ -355,10 +356,10 @@ void CodeGenModule::SetCommonAttributes(const Decl *D,
llvm::GlobalValue *GV) {
setGlobalVisibility(GV, D);
if (D->hasAttr<UsedAttr>())
if (D->hasAttr<UsedAttr>(getContext()))
AddUsedGlobal(GV);
if (const SectionAttr *SA = D->getAttr<SectionAttr>())
if (const SectionAttr *SA = D->getAttr<SectionAttr>(getContext()))
GV->setSection(SA->getName());
}
@ -382,9 +383,10 @@ void CodeGenModule::SetFunctionAttributes(const FunctionDecl *FD,
// Only a few attributes are set on declarations; these may later be
// overridden by a definition.
if (FD->hasAttr<DLLImportAttr>()) {
if (FD->hasAttr<DLLImportAttr>(getContext())) {
F->setLinkage(llvm::Function::DLLImportLinkage);
} else if (FD->hasAttr<WeakAttr>() || FD->hasAttr<WeakImportAttr>()) {
} else if (FD->hasAttr<WeakAttr>(getContext()) ||
FD->hasAttr<WeakImportAttr>(getContext())) {
// "extern_weak" is overloaded in LLVM; we probably should have
// separate linkage types for this.
F->setLinkage(llvm::Function::ExternalWeakLinkage);
@ -392,7 +394,7 @@ void CodeGenModule::SetFunctionAttributes(const FunctionDecl *FD,
F->setLinkage(llvm::Function::ExternalLinkage);
}
if (const SectionAttr *SA = FD->getAttr<SectionAttr>())
if (const SectionAttr *SA = FD->getAttr<SectionAttr>(getContext()))
F->setSection(SA->getName());
}
@ -499,15 +501,16 @@ llvm::Constant *CodeGenModule::EmitAnnotateAttr(llvm::GlobalValue *GV,
bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) {
// Never defer when EmitAllDecls is specified or the decl has
// attribute used.
if (Features.EmitAllDecls || Global->hasAttr<UsedAttr>())
if (Features.EmitAllDecls || Global->hasAttr<UsedAttr>(getContext()))
return false;
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Global)) {
// Constructors and destructors should never be deferred.
if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>())
if (FD->hasAttr<ConstructorAttr>(getContext()) ||
FD->hasAttr<DestructorAttr>(getContext()))
return false;
GVALinkage Linkage = GetLinkageForFunction(FD, Features);
GVALinkage Linkage = GetLinkageForFunction(getContext(), FD, Features);
// static, static inline, always_inline, and extern inline functions can
// always be deferred. Normal inline functions can be deferred in C99/C++.
@ -528,7 +531,7 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
// If this is an alias definition (which otherwise looks like a declaration)
// emit it now.
if (Global->hasAttr<AliasAttr>())
if (Global->hasAttr<AliasAttr>(getContext()))
return EmitAliasDefinition(Global);
// Ignore declarations, they will be emitted on their first use.
@ -717,7 +720,8 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMGlobal(const char *MangledName,
if (D->getStorageClass() == VarDecl::PrivateExtern)
GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakImportAttr>())
if (D->hasAttr<WeakAttr>(getContext()) ||
D->hasAttr<WeakImportAttr>(getContext()))
GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
GV->setThreadLocal(D->isThreadSpecified());
@ -837,7 +841,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
cast<llvm::GlobalValue>(Entry)->eraseFromParent();
}
if (const AnnotateAttr *AA = D->getAttr<AnnotateAttr>()) {
if (const AnnotateAttr *AA = D->getAttr<AnnotateAttr>(getContext())) {
SourceManager &SM = Context.getSourceManager();
AddAnnotation(EmitAnnotateAttr(GV, AA,
SM.getInstantiationLineNumber(D->getLocation())));
@ -850,11 +854,11 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
// Set the llvm linkage type as appropriate.
if (D->getStorageClass() == VarDecl::Static)
GV->setLinkage(llvm::Function::InternalLinkage);
else if (D->hasAttr<DLLImportAttr>())
else if (D->hasAttr<DLLImportAttr>(getContext()))
GV->setLinkage(llvm::Function::DLLImportLinkage);
else if (D->hasAttr<DLLExportAttr>())
else if (D->hasAttr<DLLExportAttr>(getContext()))
GV->setLinkage(llvm::Function::DLLExportLinkage);
else if (D->hasAttr<WeakAttr>())
else if (D->hasAttr<WeakAttr>(getContext()))
GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage);
else if (!CompileOpts.NoCommon &&
(!D->hasExternalStorage() && !D->getInit()))
@ -1017,14 +1021,14 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) {
SetFunctionDefinitionAttributes(D, Fn);
SetLLVMFunctionAttributesForDefinition(D, Fn);
if (const ConstructorAttr *CA = D->getAttr<ConstructorAttr>())
if (const ConstructorAttr *CA = D->getAttr<ConstructorAttr>(getContext()))
AddGlobalCtor(Fn, CA->getPriority());
if (const DestructorAttr *DA = D->getAttr<DestructorAttr>())
if (const DestructorAttr *DA = D->getAttr<DestructorAttr>(getContext()))
AddGlobalDtor(Fn, DA->getPriority());
}
void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) {
const AliasAttr *AA = D->getAttr<AliasAttr>();
const AliasAttr *AA = D->getAttr<AliasAttr>(getContext());
assert(AA && "Not an alias?");
const llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType());
@ -1080,7 +1084,7 @@ void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) {
// Set attributes which are particular to an alias; this is a
// specialization of the attributes which may be set on a global
// variable/function.
if (D->hasAttr<DLLExportAttr>()) {
if (D->hasAttr<DLLExportAttr>(getContext())) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
// The dllexport attribute is ignored for undefined symbols.
if (FD->getBody(getContext()))
@ -1088,7 +1092,8 @@ void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) {
} else {
GA->setLinkage(llvm::Function::DLLExportLinkage);
}
} else if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakImportAttr>()) {
} else if (D->hasAttr<WeakAttr>(getContext()) ||
D->hasAttr<WeakImportAttr>(getContext())) {
GA->setLinkage(llvm::Function::WeakAnyLinkage);
}
@ -1476,6 +1481,9 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
case Decl::Namespace:
EmitNamespace(cast<NamespaceDecl>(D));
break;
// No code generation needed.
case Decl::Using:
break;
case Decl::CXXConstructor:
EmitCXXConstructors(cast<CXXConstructorDecl>(D));
break;

View File

@ -353,7 +353,7 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
return T;
}
case Type::ObjCQualifiedId:
case Type::ObjCObjectPointer:
// Protocols don't influence the LLVM type.
return ConvertTypeRecursive(Context.getObjCIdType());

View File

@ -87,7 +87,7 @@ static bool isInCLinkageSpecification(const Decl *D) {
bool CXXNameMangler::mangleFunctionDecl(const FunctionDecl *FD) {
// Clang's "overloadable" attribute extension to C/C++ implies
// name mangling (always).
if (!FD->hasAttr<OverloadableAttr>()) {
if (!FD->hasAttr<OverloadableAttr>(Context)) {
// C functions are not mangled, and "main" is never mangled.
if (!Context.getLangOptions().CPlusPlus || FD->isMain())
return false;
@ -111,7 +111,7 @@ bool CXXNameMangler::mangleFunctionDecl(const FunctionDecl *FD) {
bool CXXNameMangler::mangle(const NamedDecl *D) {
// Any decl can be declared with __asm("foo") on it, and this takes
// precedence over all other naming in the .o file.
if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>(Context)) {
// If we have an asm name, then we use it as the mangling.
Out << '\01'; // LLVM IR Marker for __asm("foo")
Out << ALA->getLabel();

View File

@ -17,3 +17,5 @@ add_clang_library(clangDriver
Tools.cpp
Types.cpp
)
add_dependencies(clangSema ClangDiagnosticDriver)

View File

@ -356,10 +356,15 @@ void Driver::PrintVersion(const Compilation &C) const {
// don't know what the client would like to do.
llvm::errs() << "clang version " CLANG_VERSION_STRING " ("
<< vers << " " << revision << ")" << "\n";
<< vers << " " << revision << ")" << '\n';
const ToolChain &TC = C.getDefaultToolChain();
llvm::errs() << "Target: " << TC.getTripleString() << '\n';
// Print the threading model.
//
// FIXME: Implement correctly.
llvm::errs() << "Thread model: " << "posix" << '\n';
}
bool Driver::HandleImmediateArgs(const Compilation &C) {
@ -429,6 +434,47 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
return false;
}
if (C.getArgs().hasArg(options::OPT_print_multi_lib)) {
// FIXME: We need tool chain support for this.
llvm::outs() << ".;\n";
switch (C.getDefaultToolChain().getTriple().getArch()) {
default:
break;
case llvm::Triple::x86_64:
llvm::outs() << "x86_64;@m64" << "\n";
break;
case llvm::Triple::ppc64:
llvm::outs() << "ppc64;@m64" << "\n";
break;
}
return false;
}
// FIXME: What is the difference between print-multi-directory and
// print-multi-os-directory?
if (C.getArgs().hasArg(options::OPT_print_multi_directory) ||
C.getArgs().hasArg(options::OPT_print_multi_os_directory)) {
switch (C.getDefaultToolChain().getTriple().getArch()) {
default:
case llvm::Triple::x86:
case llvm::Triple::ppc:
llvm::outs() << "." << "\n";
break;
case llvm::Triple::x86_64:
llvm::outs() << "x86_64" << "\n";
break;
case llvm::Triple::ppc64:
llvm::outs() << "ppc64" << "\n";
break;
}
return false;
}
return true;
}

View File

@ -108,16 +108,34 @@ ToolChain *DarwinHostInfo::getToolChain(const ArgList &Args,
const char *ArchName) const {
std::string Arch;
if (!ArchName) {
Arch = getArchName();
// If we aren't looking for a specific arch, infer the default architecture
// based on -arch and -m32/-m64 command line options.
if (Arg *A = Args.getLastArg(options::OPT_arch)) {
// The gcc driver behavior with multiple -arch flags wasn't consistent for
// things which rely on a default architecture. We just use the last -arch
// to find the default tool chain.
Arch = A->getValue(Args);
// Normalize arch name; we shouldn't be doing this here.
//
// FIXME: This should be unnecessary once everything moves over to using
// the ID based Triple interface.
if (Arch == "ppc")
Arch = "powerpc";
else if (Arch == "ppc64")
Arch = "powerpc64";
} else {
// Otherwise default to the arch of the host.
Arch = getArchName();
}
ArchName = Arch.c_str();
// If no arch name is specified, infer it from the host and
// -m32/-m64.
// Honor -m32 and -m64 when finding the default tool chain.
if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
if (getArchName() == "i386" || getArchName() == "x86_64") {
ArchName =
(A->getOption().getId() == options::OPT_m32) ? "i386" : "x86_64";
} else if (getArchName() == "powerpc" || getArchName() == "powerpc64") {
if (Arch == "i386" || Arch == "x86_64") {
ArchName = (A->getOption().getId() == options::OPT_m32) ? "i386" :
"x86_64";
} else if (Arch == "powerpc" || Arch == "powerpc64") {
ArchName = (A->getOption().getId() == options::OPT_m32) ? "powerpc" :
"powerpc64";
}

View File

@ -243,7 +243,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
}
case Decl::CXXMethod: {
const CXXMethodDecl* D = cast<CXXMethodDecl>(DC);
if (D->isOutOfLineDefinition())
if (D->isOutOfLine())
Out << "[c++ method] ";
else if (D->isImplicit())
Out << "(c++ method) ";
@ -273,7 +273,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
}
case Decl::CXXConstructor: {
const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC);
if (D->isOutOfLineDefinition())
if (D->isOutOfLine())
Out << "[c++ ctor] ";
else if (D->isImplicit())
Out << "(c++ ctor) ";
@ -302,7 +302,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
}
case Decl::CXXDestructor: {
const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC);
if (D->isOutOfLineDefinition())
if (D->isOutOfLine())
Out << "[c++ dtor] ";
else if (D->isImplicit())
Out << "(c++ dtor) ";
@ -318,7 +318,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
}
case Decl::CXXConversion: {
const CXXConversionDecl* D = cast<CXXConversionDecl>(DC);
if (D->isOutOfLineDefinition())
if (D->isOutOfLine())
Out << "[c++ conversion] ";
else if (D->isImplicit())
Out << "(c++ conversion) ";

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