Update Clang sources to r73879.
This commit is contained in:
parent
7ef7bab7e3
commit
b897c8660c
@ -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} )
|
||||
|
@ -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; }
|
||||
|
@ -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+".
|
||||
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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); }
|
||||
|
@ -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; }
|
||||
|
@ -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());
|
||||
|
@ -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
|
||||
|
50
include/clang/AST/TypeVisitor.h
Normal file
50
include/clang/AST/TypeVisitor.h
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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">;
|
||||
|
@ -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;
|
||||
|
@ -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*>
|
||||
|
@ -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,
|
||||
|
@ -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(); }
|
||||
|
75
include/clang/Frontend/ASTUnit.h
Normal file
75
include/clang/Frontend/ASTUnit.h
Normal 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
|
113
include/clang/Frontend/DeclContextXML.def
Normal file
113
include/clang/Frontend/DeclContextXML.def
Normal 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
|
250
include/clang/Frontend/DeclXML.def
Normal file
250
include/clang/Frontend/DeclXML.def
Normal 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
|
75
include/clang/Frontend/DocumentXML.def
Normal file
75
include/clang/Frontend/DocumentXML.def
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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; }
|
||||
|
517
include/clang/Frontend/StmtXML.def
Normal file
517
include/clang/Frontend/StmtXML.def
Normal 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
|
277
include/clang/Frontend/TypeXML.def
Normal file
277
include/clang/Frontend/TypeXML.def
Normal 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
|
@ -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,
|
||||
|
@ -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();
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -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.
|
||||
|
@ -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) {
|
||||
|
@ -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());
|
||||
|
109
lib/AST/Type.cpp
109
lib/AST/Type.cpp
@ -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;
|
||||
|
@ -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:";
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)));
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
@ -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());
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 &&
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
///
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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()));
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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();
|
||||
|
@ -17,3 +17,5 @@ add_clang_library(clangDriver
|
||||
Tools.cpp
|
||||
Types.cpp
|
||||
)
|
||||
|
||||
add_dependencies(clangSema ClangDiagnosticDriver)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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";
|
||||
}
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user