Import Clang r73954.

This commit is contained in:
ed 2009-06-23 14:50:21 +00:00
parent 8927c19a5e
commit da468bf93e
55 changed files with 1266 additions and 836 deletions

View File

@ -647,6 +647,13 @@ class FunctionDecl : public ValueDecl, public DeclContext {
// Move to DeclGroup when it is implemented.
SourceLocation TypeSpecStartLoc;
/// \brief End part of this FunctionDecl's source range.
///
/// We could compute the full range in getSourceRange(). However, when we're
/// dealing with a function definition deserialized from a PCH/AST file,
/// we can only compute the full range once the function body has been
/// de-serialized, so it's far better to have the (sometimes-redundant)
/// EndRangeLoc.
SourceLocation EndRangeLoc;
/// \brief The template or declaration that this declaration
@ -687,7 +694,6 @@ class FunctionDecl : public ValueDecl, public DeclContext {
return SourceRange(getLocation(), EndRangeLoc);
}
void setLocEnd(SourceLocation E) {
assert(getLocation() <= E && "Invalid end location");
EndRangeLoc = E;
}

View File

@ -283,6 +283,10 @@ class CXXRecordDecl : public RecordDecl {
/// copy constructor that accepts a const-qualified argument.
bool hasConstCopyConstructor(ASTContext &Context) const;
/// getCopyConstructor - Returns the copy constructor for this class
CXXConstructorDecl *getCopyConstructor(ASTContext &Context,
unsigned TypeQuals) const;
/// hasConstCopyAssignment - Determines whether this class has a
/// copy assignment operator that accepts a const-qualified argument.
bool hasConstCopyAssignment(ASTContext &Context) const;
@ -642,18 +646,13 @@ class CXXConstructorDecl : public CXXMethodDecl {
/// @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.
CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation L,
DeclarationName N, QualType T,
bool isExplicit, bool isInline, bool isImplicitlyDeclared)
: CXXMethodDecl(CXXConstructor, RD, L, N, T, false, isInline),
Explicit(isExplicit), ImplicitlyDefined(false),
ImplicitMustBeDefined(false) {
Explicit(isExplicit), ImplicitlyDefined(false) {
setImplicit(isImplicitlyDeclared);
}
@ -683,17 +682,6 @@ class CXXConstructorDecl : public CXXMethodDecl {
"Can only set the implicit-definition flag once the constructor has been defined");
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

View File

@ -469,10 +469,6 @@ 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) {
@ -587,6 +583,9 @@ class TemplateArgument {
/// \brief Retrieve the location where the template argument starts.
SourceLocation getLocation() const { return StartLoc; }
/// \brief Construct a template argument pack.
void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
/// \brief Used to insert TemplateArguments into FoldingSets.
void Profile(llvm::FoldingSetNodeID &ID) const {
ID.AddInteger(Kind);
@ -622,47 +621,51 @@ class TemplateArgument {
/// \brief A helper class for making template argument lists.
class TemplateArgumentListBuilder {
/// FlatArgs - contains the template arguments in flat form.
llvm::SmallVector<TemplateArgument, 16> FlatArgs;
llvm::SmallVector<TemplateArgument, 16> StructuredArgs;
ASTContext &Context;
TemplateArgument *StructuredArgs;
unsigned MaxStructuredArgs;
unsigned NumStructuredArgs;
TemplateArgument *FlatArgs;
unsigned MaxFlatArgs;
unsigned NumFlatArgs;
bool AddingToPack;
unsigned PackBeginIndex;
/// isAddingFromParameterPack - Returns whether we're adding arguments from
/// a parameter pack.
bool isAddingFromParameterPack() const {
return PackBeginIndex != std::numeric_limits<unsigned>::max();
}
public:
TemplateArgumentListBuilder(ASTContext &Context) : Context(Context),
PackBeginIndex(std::numeric_limits<unsigned>::max()) { }
TemplateArgumentListBuilder(const TemplateParameterList *Parameters,
unsigned NumTemplateArgs)
: StructuredArgs(0), MaxStructuredArgs(Parameters->size()),
NumStructuredArgs(0), FlatArgs(0),
MaxFlatArgs(std::max(MaxStructuredArgs, NumTemplateArgs)), NumFlatArgs(0),
AddingToPack(false), PackBeginIndex(0) { }
size_t structuredSize() const {
assert(!isAddingFromParameterPack() &&
"Size is not valid when adding from a parameter pack");
return StructuredArgs.size();
}
size_t flatSize() const { return FlatArgs.size(); }
void Append(const TemplateArgument& Arg);
void BeginPack();
void EndPack();
void push_back(const TemplateArgument& Arg);
void ReleaseArgs();
/// BeginParameterPack - Start adding arguments from a parameter pack.
void BeginParameterPack();
/// EndParameterPack - Finish adding arguments from a parameter pack.
void EndParameterPack();
const TemplateArgument *getFlatArgumentList() const {
return FlatArgs.data();
unsigned flatSize() const {
return NumFlatArgs;
}
TemplateArgument *getFlatArgumentList() {
return FlatArgs.data();
const TemplateArgument *getFlatArguments() const {
return FlatArgs;
}
unsigned structuredSize() const {
// If we don't have any structured args, just reuse the flat size.
if (!StructuredArgs)
return flatSize();
return NumStructuredArgs;
}
const TemplateArgument *getStructuredArguments() const {
// If we don't have any structured args, just reuse the flat args.
if (!StructuredArgs)
return getFlatArguments();
return StructuredArgs;
}
};
@ -676,22 +679,25 @@ class TemplateArgumentList {
///
/// The integer value will be non-zero to indicate that this
/// template argument list does not own the pointer.
llvm::PointerIntPair<TemplateArgument *, 1> Arguments;
llvm::PointerIntPair<const TemplateArgument *, 1> FlatArguments;
/// \brief The number of template arguments in this template
/// argument list.
unsigned NumArguments;
unsigned NumFlatArguments;
llvm::PointerIntPair<const TemplateArgument *, 1> StructuredArguments;
unsigned NumStructuredArguments;
public:
TemplateArgumentList(ASTContext &Context,
TemplateArgumentListBuilder &Builder,
bool CopyArgs, bool FlattenArgs);
bool TakeArgs);
~TemplateArgumentList();
/// \brief Retrieve the template argument at a given index.
const TemplateArgument &get(unsigned Idx) const {
assert(Idx < NumArguments && "Invalid template argument index");
assert(Idx < NumFlatArguments && "Invalid template argument index");
return getFlatArgumentList()[Idx];
}
@ -700,15 +706,15 @@ class TemplateArgumentList {
/// \brief Retrieve the number of template arguments in this
/// template argument list.
unsigned size() const { return NumArguments; }
unsigned size() const { return NumFlatArguments; }
/// \brief Retrieve the number of template arguments in the
/// flattened template argument list.
unsigned flat_size() const { return NumArguments; }
unsigned flat_size() const { return NumFlatArguments; }
/// \brief Retrieve the flattened template argument list.
const TemplateArgument *getFlatArgumentList() const {
return Arguments.getPointer();
return FlatArguments.getPointer();
}
};

View File

@ -27,7 +27,7 @@
namespace clang {
class EnvironmentManager;
class BasicValueFactory;
class ValueManager;
class LiveVariables;
class Environment {
@ -71,8 +71,8 @@ class Environment {
return X ? *X : UnknownVal();
}
SVal GetSVal(const Stmt* Ex, BasicValueFactory& BasicVals) const;
SVal GetBlkExprSVal(const Stmt* Ex, BasicValueFactory& BasicVals) const;
SVal GetSVal(const Stmt* Ex, ValueManager& ValMgr) const;
SVal GetBlkExprSVal(const Stmt* Ex, ValueManager& ValMgr) const;
/// Profile - Profile the contents of an Environment object for use
/// in a FoldingSet.

View File

@ -481,11 +481,6 @@ class GRExprEngine {
return N == EntryNode ? CleanedState : N->getState();
}
public:
inline NonLoc MakeConstantVal(uint64_t X, Expr* Ex) {
return NonLoc::MakeVal(getBasicVals(), X, Ex->getType());
}
public:
NodeTy* MakeNode(NodeSet& Dst, Stmt* S, NodeTy* Pred, const GRState* St,
ProgramPoint::Kind K = ProgramPoint::PostStmtKind,

View File

@ -532,7 +532,7 @@ class GRStateManager {
// Methods that query & manipulate the Environment.
SVal GetSVal(const GRState* St, const Stmt* Ex) {
return St->getEnvironment().GetSVal(Ex, getBasicVals());
return St->getEnvironment().GetSVal(Ex, ValueMgr);
}
SVal GetSValAsScalarOrLoc(const GRState* state, const Stmt *S) {
@ -546,7 +546,7 @@ class GRStateManager {
}
SVal GetBlkExprSVal(const GRState* St, const Stmt* Ex) {
return St->getEnvironment().GetBlkExprSVal(Ex, getBasicVals());
return St->getEnvironment().GetBlkExprSVal(Ex, ValueMgr);
}
const GRState* BindExpr(const GRState* St, const Stmt* Ex, SVal V,
@ -613,7 +613,7 @@ class GRStateManager {
// We only want to do fetches from regions that we can actually bind
// values. For example, SymbolicRegions of type 'id<...>' cannot
// have direct bindings (but their can be bindings on their subregions).
if (!R->isBoundable(getContext()))
if (!R->isBoundable())
return UnknownVal();
if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) {

View File

@ -59,11 +59,14 @@ class MemRegion : public llvm::FoldingSetNode {
protected:
MemRegion(Kind k) : kind(k) {}
virtual ~MemRegion();
ASTContext &getContext() const;
public:
// virtual MemExtent getExtent(MemRegionManager& mrm) const = 0;
virtual void Profile(llvm::FoldingSetNodeID& ID) const = 0;
virtual MemRegionManager* getMemRegionManager() const = 0;
std::string getString() const;
virtual void print(llvm::raw_ostream& os) const;
@ -72,7 +75,7 @@ class MemRegion : public llvm::FoldingSetNode {
template<typename RegionTy> const RegionTy* getAs() const;
virtual bool isBoundable(ASTContext&) const { return true; }
virtual bool isBoundable() const { return true; }
static bool classof(const MemRegion*) { return true; }
};
@ -81,14 +84,23 @@ class MemRegion : public llvm::FoldingSetNode {
/// for example, the set of global variables, the stack frame, etc.
class MemSpaceRegion : public MemRegion {
friend class MemRegionManager;
MemSpaceRegion() : MemRegion(MemSpaceRegionKind) {}
protected:
MemRegionManager *Mgr;
MemSpaceRegion(MemRegionManager *mgr) : MemRegion(MemSpaceRegionKind),
Mgr(mgr) {}
MemRegionManager* getMemRegionManager() const {
return Mgr;
}
public:
//RegionExtent getExtent() const { return UndefinedExtent(); }
void Profile(llvm::FoldingSetNodeID& ID) const;
bool isBoundable(ASTContext &) const { return false; }
bool isBoundable() const { return false; }
static bool classof(const MemRegion* R) {
return R->getKind() == MemSpaceRegionKind;
@ -101,11 +113,12 @@ class SubRegion : public MemRegion {
protected:
const MemRegion* superRegion;
SubRegion(const MemRegion* sReg, Kind k) : MemRegion(k), superRegion(sReg) {}
public:
const MemRegion* getSuperRegion() const {
return superRegion;
}
MemRegionManager* getMemRegionManager() const;
bool isSubRegionOf(const MemRegion* R) const;
@ -123,7 +136,7 @@ class AllocaRegion : public SubRegion {
// memory allocated by alloca at the same call site.
const Expr* Ex;
AllocaRegion(const Expr* ex, unsigned cnt, const MemRegion* superRegion)
AllocaRegion(const Expr* ex, unsigned cnt, const MemRegion *superRegion)
: SubRegion(superRegion, AllocaRegionKind), Cnt(cnt), Ex(ex) {}
public:
@ -133,7 +146,7 @@ class AllocaRegion : public SubRegion {
void Profile(llvm::FoldingSetNodeID& ID) const;
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Expr* Ex,
unsigned Cnt);
unsigned Cnt, const MemRegion *superRegion);
void print(llvm::raw_ostream& os) const;
@ -164,8 +177,8 @@ class TypedRegion : public SubRegion {
return getLocationType(C)->getDesugaredType();
}
bool isBoundable(ASTContext &C) const {
return !getValueType(C).isNull();
bool isBoundable() const {
return !getValueType(getContext()).isNull();
}
static bool classof(const MemRegion* R) {
@ -229,14 +242,14 @@ class CodeTextRegion : public TypedRegion {
return const_cast<SymbolRef>(static_cast<const SymbolRef>(Data));
}
bool isBoundable(ASTContext&) const { return false; }
bool isBoundable() const { return false; }
virtual void print(llvm::raw_ostream& os) const;
void Profile(llvm::FoldingSetNodeID& ID) const;
static void ProfileRegion(llvm::FoldingSetNodeID& ID,
const void* data, QualType t);
const void* data, QualType t, const MemRegion*);
static bool classof(const MemRegion* R) {
return R->getKind() == CodeTextRegionKind;
@ -262,7 +275,9 @@ class SymbolicRegion : public SubRegion {
void Profile(llvm::FoldingSetNodeID& ID) const;
static void ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym);
static void ProfileRegion(llvm::FoldingSetNodeID& ID,
SymbolRef sym,
const MemRegion* superRegion);
void print(llvm::raw_ostream& os) const;
@ -277,7 +292,7 @@ class StringRegion : public TypedRegion {
const StringLiteral* Str;
protected:
StringRegion(const StringLiteral* str, MemRegion* sreg)
StringRegion(const StringLiteral* str, const MemRegion* sreg)
: TypedRegion(sreg, StringRegionKind), Str(str) {}
static void ProfileRegion(llvm::FoldingSetNodeID& ID,
@ -327,7 +342,7 @@ class TypedViewRegion : public TypedRegion {
return PTy->getPointeeType();
}
bool isBoundable(ASTContext &C) const {
bool isBoundable() const {
return isa<PointerType>(LValueType);
}
@ -399,8 +414,8 @@ class VarRegion : public DeclRegion {
VarRegion(const VarDecl* vd, const MemRegion* sReg)
: DeclRegion(vd, sReg, VarRegionKind) {}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, VarDecl* VD,
const MemRegion* superRegion) {
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const VarDecl* VD,
const MemRegion* superRegion) {
DeclRegion::ProfileRegion(ID, VD, superRegion, VarRegionKind);
}
@ -436,8 +451,8 @@ class FieldRegion : public DeclRegion {
return C.getCanonicalType(getDecl()->getType());
}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, FieldDecl* FD,
const MemRegion* superRegion) {
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FieldDecl* FD,
const MemRegion* superRegion) {
DeclRegion::ProfileRegion(ID, FD, superRegion, FieldRegionKind);
}
@ -453,7 +468,8 @@ class ObjCObjectRegion : public DeclRegion {
ObjCObjectRegion(const ObjCInterfaceDecl* ivd, const MemRegion* sReg)
: DeclRegion(ivd, sReg, ObjCObjectRegionKind) {}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, ObjCInterfaceDecl* ivd,
static void ProfileRegion(llvm::FoldingSetNodeID& ID,
const ObjCInterfaceDecl* ivd,
const MemRegion* superRegion) {
DeclRegion::ProfileRegion(ID, ivd, superRegion, ObjCObjectRegionKind);
}
@ -479,8 +495,8 @@ class ObjCIvarRegion : public DeclRegion {
ObjCIvarRegion(const ObjCIvarDecl* ivd, const MemRegion* sReg)
: DeclRegion(ivd, sReg, ObjCIvarRegionKind) {}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, ObjCIvarDecl* ivd,
const MemRegion* superRegion) {
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const ObjCIvarDecl* ivd,
const MemRegion* superRegion) {
DeclRegion::ProfileRegion(ID, ivd, superRegion, ObjCIvarRegionKind);
}
@ -556,6 +572,7 @@ const RegionTy* MemRegion::getAs() const {
//===----------------------------------------------------------------------===//
class MemRegionManager {
ASTContext &C;
llvm::BumpPtrAllocator& A;
llvm::FoldingSet<MemRegion> Regions;
@ -566,11 +583,13 @@ class MemRegionManager {
MemSpaceRegion* code;
public:
MemRegionManager(llvm::BumpPtrAllocator& a)
: A(a), globals(0), stack(0), heap(0), unknown(0), code(0) {}
MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator& a)
: C(c), A(a), globals(0), stack(0), heap(0), unknown(0), code(0) {}
~MemRegionManager() {}
ASTContext &getContext() { return C; }
/// getStackRegion - Retrieve the memory region associated with the
/// current stack frame.
MemSpaceRegion* getStackRegion();
@ -589,17 +608,6 @@ class MemRegionManager {
MemSpaceRegion* getCodeRegion();
bool isGlobalsRegion(const MemRegion* R) {
assert(R);
return R == globals;
}
/// onStack - check if the region is allocated on the stack.
bool onStack(const MemRegion* R);
/// onHeap - check if the region is allocated on the heap, usually by malloc.
bool onHeap(const MemRegion* R);
/// getAllocaRegion - Retrieve a region associated with a call to alloca().
AllocaRegion* getAllocaRegion(const Expr* Ex, unsigned Cnt);
@ -646,14 +654,164 @@ class MemRegionManager {
CodeTextRegion* getCodeTextRegion(SymbolRef sym, QualType t);
CodeTextRegion* getCodeTextRegion(const FunctionDecl* fd, QualType t);
template <typename RegionTy, typename A1>
RegionTy* getRegion(const A1 a1);
template <typename RegionTy, typename A1>
RegionTy* getRegion(const A1 a1, const MemRegion* superRegion);
template <typename RegionTy, typename A1, typename A2>
RegionTy* getRegion(const A1 a1, const A2 a2);
bool isGlobalsRegion(const MemRegion* R) {
assert(R);
return R == globals;
}
bool hasStackStorage(const MemRegion* R);
bool hasHeapStorage(const MemRegion* R);
private:
MemSpaceRegion* LazyAllocate(MemSpaceRegion*& region);
};
//===----------------------------------------------------------------------===//
// Out-of-line member definitions.
//===----------------------------------------------------------------------===//
inline ASTContext& MemRegion::getContext() const {
return getMemRegionManager()->getContext();
}
template<typename RegionTy> struct MemRegionManagerTrait;
template <typename RegionTy, typename A1>
RegionTy* MemRegionManager::getRegion(const A1 a1) {
const typename MemRegionManagerTrait<RegionTy>::SuperRegionTy *superRegion =
MemRegionManagerTrait<RegionTy>::getSuperRegion(*this, a1);
llvm::FoldingSetNodeID ID;
RegionTy::ProfileRegion(ID, a1, superRegion);
void* InsertPos;
RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
InsertPos));
if (!R) {
R = (RegionTy*) A.Allocate<RegionTy>();
new (R) RegionTy(a1, superRegion);
Regions.InsertNode(R, InsertPos);
}
return R;
}
template <typename RegionTy, typename A1>
RegionTy* MemRegionManager::getRegion(const A1 a1, const MemRegion *superRegion)
{
llvm::FoldingSetNodeID ID;
RegionTy::ProfileRegion(ID, a1, superRegion);
void* InsertPos;
RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
InsertPos));
if (!R) {
R = (RegionTy*) A.Allocate<RegionTy>();
new (R) RegionTy(a1, superRegion);
Regions.InsertNode(R, InsertPos);
}
return R;
}
template <typename RegionTy, typename A1, typename A2>
RegionTy* MemRegionManager::getRegion(const A1 a1, const A2 a2) {
const typename MemRegionManagerTrait<RegionTy>::SuperRegionTy *superRegion =
MemRegionManagerTrait<RegionTy>::getSuperRegion(*this, a1, a2);
llvm::FoldingSetNodeID ID;
RegionTy::ProfileRegion(ID, a1, a2, superRegion);
void* InsertPos;
RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
InsertPos));
if (!R) {
R = (RegionTy*) A.Allocate<RegionTy>();
new (R) RegionTy(a1, a2, superRegion);
Regions.InsertNode(R, InsertPos);
}
return R;
}
//===----------------------------------------------------------------------===//
// Traits for constructing regions.
//===----------------------------------------------------------------------===//
template <> struct MemRegionManagerTrait<AllocaRegion> {
typedef MemRegion SuperRegionTy;
static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
const Expr *, unsigned) {
return MRMgr.getStackRegion();
}
};
template <> struct MemRegionManagerTrait<CompoundLiteralRegion> {
typedef MemRegion SuperRegionTy;
static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
const CompoundLiteralExpr *CL) {
return CL->isFileScope() ? MRMgr.getGlobalsRegion()
: MRMgr.getStackRegion();
}
};
template <> struct MemRegionManagerTrait<StringRegion> {
typedef MemSpaceRegion SuperRegionTy;
static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
const StringLiteral*) {
return MRMgr.getGlobalsRegion();
}
};
template <> struct MemRegionManagerTrait<VarRegion> {
typedef MemRegion SuperRegionTy;
static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
const VarDecl *d) {
return d->hasLocalStorage() ? MRMgr.getStackRegion()
: MRMgr.getGlobalsRegion();
}
};
template <> struct MemRegionManagerTrait<SymbolicRegion> {
typedef MemRegion SuperRegionTy;
static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
SymbolRef) {
return MRMgr.getUnknownRegion();
}
};
template<> struct MemRegionManagerTrait<CodeTextRegion> {
typedef MemSpaceRegion SuperRegionTy;
static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
const FunctionDecl*, QualType) {
return MRMgr.getCodeRegion();
}
static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
SymbolRef, QualType) {
return MRMgr.getCodeRegion();
}
};
} // end clang namespace
//===----------------------------------------------------------------------===//
// Pretty-printing regions.
//===----------------------------------------------------------------------===//
namespace llvm {
static inline raw_ostream& operator<<(raw_ostream& O,
const clang::MemRegion* R) {

View File

@ -30,6 +30,7 @@ class BasicValueFactory;
class MemRegion;
class MemRegionManager;
class GRStateManager;
class ValueManager;
class SVal {
public:
@ -171,28 +172,6 @@ class NonLoc : public SVal {
public:
void print(llvm::raw_ostream& Out) const;
// Utility methods to create NonLocs.
static NonLoc MakeIntVal(BasicValueFactory& BasicVals, uint64_t X,
bool isUnsigned);
static NonLoc MakeVal(BasicValueFactory& BasicVals, uint64_t X,
unsigned BitWidth, bool isUnsigned);
static NonLoc MakeVal(BasicValueFactory& BasicVals, uint64_t X, QualType T);
static NonLoc MakeVal(BasicValueFactory& BasicVals, const IntegerLiteral *I);
static NonLoc MakeVal(BasicValueFactory& BasicVals, const llvm::APInt& I,
bool isUnsigned);
static NonLoc MakeVal(BasicValueFactory& BasicVals, const llvm::APSInt& I);
static NonLoc MakeIntTruthVal(BasicValueFactory& BasicVals, bool b);
static NonLoc MakeCompoundVal(QualType T, llvm::ImmutableList<SVal> Vals,
BasicValueFactory& BasicVals);
// Implement isa<T> support.
static inline bool classof(const SVal* V) {
return V->getBaseKind() == NonLocKind;
@ -210,12 +189,6 @@ class Loc : public SVal {
Loc(const Loc& X) : SVal(X.Data, true, X.getSubKind()) {}
Loc& operator=(const Loc& X) { memcpy(this, &X, sizeof(Loc)); return *this; }
static Loc MakeVal(const MemRegion* R);
static Loc MakeVal(const AddrLabelExpr* E);
static Loc MakeNull(BasicValueFactory &BasicVals);
// Implement isa<T> support.
static inline bool classof(const SVal* V) {
return V->getBaseKind() == LocKind;
@ -301,6 +274,8 @@ class ConcreteInt : public NonLoc {
};
class LocAsInteger : public NonLoc {
friend class clang::ValueManager;
LocAsInteger(const std::pair<SVal, uintptr_t>& data) :
NonLoc(LocAsIntegerKind, &data) {
assert (isa<Loc>(data.first));
@ -330,12 +305,10 @@ class LocAsInteger : public NonLoc {
static inline bool classof(const NonLoc* V) {
return V->getSubKind() == LocAsIntegerKind;
}
static LocAsInteger Make(BasicValueFactory& Vals, Loc V, unsigned Bits);
};
class CompoundVal : public NonLoc {
friend class NonLoc;
friend class clang::ValueManager;
CompoundVal(const CompoundValData* D) : NonLoc(CompoundValKind, D) {}

View File

@ -9,7 +9,7 @@
//
// This file defines ValueManager, a class that manages symbolic values
// and SVals created for use by GRExprEngine and related classes. It
// wraps SymbolManager, MemRegionManager, and BasicValueFactory.
// wraps and owns SymbolManager, MemRegionManager, and BasicValueFactory.
//
//===----------------------------------------------------------------------===//
@ -39,7 +39,7 @@ class ValueManager {
ValueManager(llvm::BumpPtrAllocator &alloc, ASTContext &context)
: Context(context), BasicVals(Context, alloc),
SymMgr(Context, BasicVals, alloc),
MemMgr(alloc) {}
MemMgr(Context, alloc) {}
// Accessors to submanagers.
@ -68,17 +68,8 @@ class ValueManager {
return SymMgr.getConjuredSymbol(E, VisitCount, SymbolTag);
}
// Aggregation methods that use multiple submanagers.
Loc makeRegionVal(SymbolRef Sym) {
return Loc::MakeVal(MemMgr.getSymbolicRegion(Sym));
}
/// makeZeroVal - Construct an SVal representing '0' for the specified type.
SVal makeZeroVal(QualType T);
/// makeZeroArrayIndex - Construct an SVal representing '0' index for array
/// elements.
SVal makeZeroArrayIndex();
/// GetRegionValueSymbolVal - make a unique symbol for value of R.
SVal getRegionValueSymbolVal(const MemRegion* R, QualType T = QualType());
@ -87,16 +78,77 @@ class ValueManager {
SVal getConjuredSymbolVal(const Expr* E, QualType T, unsigned Count);
SVal getFunctionPointer(const FunctionDecl* FD);
NonLoc makeNonLoc(SymbolRef sym);
NonLoc makeCompoundVal(QualType T, llvm::ImmutableList<SVal> Vals) {
return nonloc::CompoundVal(BasicVals.getCompoundValData(T, Vals));
}
NonLoc makeZeroArrayIndex() {
return nonloc::ConcreteInt(BasicVals.getZeroWithPtrWidth(false));
}
NonLoc makeIntVal(const IntegerLiteral* I) {
return nonloc::ConcreteInt(BasicVals.getValue(I->getValue(),
I->getType()->isUnsignedIntegerType()));
}
NonLoc makeIntVal(const llvm::APSInt& V) {
return nonloc::ConcreteInt(BasicVals.getValue(V));
}
NonLoc makeIntVal(const llvm::APInt& V, bool isUnsigned) {
return nonloc::ConcreteInt(BasicVals.getValue(V, isUnsigned));
}
NonLoc makeIntVal(uint64_t X, QualType T) {
return nonloc::ConcreteInt(BasicVals.getValue(X, T));
}
NonLoc makeIntVal(uint64_t X, bool isUnsigned) {
return nonloc::ConcreteInt(BasicVals.getIntValue(X, isUnsigned));
}
NonLoc makeIntVal(uint64_t X, unsigned BitWidth, bool isUnsigned) {
return nonloc::ConcreteInt(BasicVals.getValue(X, BitWidth, isUnsigned));
}
NonLoc makeLocAsInteger(Loc V, unsigned Bits) {
return nonloc::LocAsInteger(BasicVals.getPersistentSValWithData(V, Bits));
}
NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
const llvm::APSInt& rhs, QualType T);
NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
const SymExpr *rhs, QualType T);
NonLoc makeTruthVal(bool b, QualType T);
NonLoc makeTruthVal(bool b, QualType T) {
return nonloc::ConcreteInt(BasicVals.getTruthValue(b, T));
}
NonLoc makeTruthVal(bool b) {
return nonloc::ConcreteInt(BasicVals.getTruthValue(b));
}
Loc makeNull() {
return loc::ConcreteInt(BasicVals.getZeroWithPtrWidth());
}
Loc makeLoc(SymbolRef Sym) {
return loc::MemRegionVal(MemMgr.getSymbolicRegion(Sym));
}
Loc makeLoc(const MemRegion* R) {
return loc::MemRegionVal(R);
}
Loc makeLoc(const AddrLabelExpr* E) {
return loc::GotoLabel(E->getLabel());
}
Loc makeLoc(const llvm::APSInt& V) {
return loc::ConcreteInt(BasicVals.getValue(V));
}
};
} // end clang namespace
#endif

View File

@ -136,4 +136,7 @@ def warn_pch_char_signed : Error<
def err_not_a_pch_file : Error<
"'%0' does not appear to be a precompiled header file">, DefaultFatal;
def warn_unknown_warning_option : Warning<
"unknown warning option '%0'">,
InGroup<DiagGroup<"unknown-warning-option"> >;
}

View File

@ -580,8 +580,8 @@ 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">;
"cannot define the implicit default constructor for %0, because %select{base class|member}1 "
"%2 does not have any default constructor">;
def note_previous_class_decl : Note<
"%0 declared here">;
def err_unintialized_member : Error<
@ -870,7 +870,8 @@ def err_undeclared_var_use : Error<"use of undeclared identifier %0">;
def err_undeclared_use : Error<"use of undeclared '%0'">;
def warn_deprecated : Warning<"%0 is deprecated">,
InGroup<DiagGroup<"deprecated-declarations">>;
def warn_unavailable : Warning<"%0 is unavailable">;
def warn_unavailable : Warning<"%0 is unavailable">,
InGroup<DiagGroup<"unavailable-declarations">>;
def note_unavailable_here : Note<
"function has been explicitly marked %select{unavailable|deleted}0 here">;
def warn_not_enough_argument : Warning<

View File

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

View File

@ -637,18 +637,50 @@ class Action : public ActionBase {
// Expression Parsing Callbacks.
//===--------------------------------------------------------------------===//
/// \brief Notifies the action when the parser is processing an unevaluated
/// operand.
/// \brief Describes how the expressions currently being parsed are
/// evaluated at run-time, if at all.
enum ExpressionEvaluationContext {
/// \brief The current expression and its subexpressions occur within an
/// unevaluated operand (C++0x [expr]p8), such as a constant expression
/// or the subexpression of \c sizeof, where the type or the value of the
/// expression may be significant but no code will be generated to evaluate
/// the value of the expression at run time.
Unevaluated,
/// \brief The current expression is potentially evaluated at run time,
/// which means that code may be generated to evaluate the value of the
/// expression at run time.
PotentiallyEvaluated,
/// \brief The current expression may be potentially evaluated or it may
/// be unevaluated, but it is impossible to tell from the lexical context.
/// This evaluation context is used primary for the operand of the C++
/// \c typeid expression, whose argument is potentially evaluated only when
/// it is an lvalue of polymorphic class type (C++ [basic.def.odr]p2).
PotentiallyPotentiallyEvaluated
};
/// \brief The parser is entering a new expression evaluation context.
///
/// \param UnevaluatedOperand true to indicate that the parser is processing
/// an unevaluated operand, or false otherwise.
/// \param NewContext is the new expression evaluation context.
///
/// \returns whether the the action module was previously in an unevaluated
/// operand.
virtual bool setUnevaluatedOperand(bool UnevaluatedOperand) {
return false;
/// \returns the previous expression evaluation context.
virtual ExpressionEvaluationContext
PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) {
return PotentiallyEvaluated;
}
/// \brief The parser is existing an expression evaluation context.
///
/// \param OldContext the expression evaluation context that the parser is
/// leaving.
///
/// \param NewContext the expression evaluation context that the parser is
/// returning to.
virtual void
PopExpressionEvaluationContext(ExpressionEvaluationContext OldContext,
ExpressionEvaluationContext NewContext) { }
// Primary Expressions.
/// \brief Retrieve the source range that corresponds to the given
@ -1891,6 +1923,29 @@ class PrettyStackTraceActionsDecl : public llvm::PrettyStackTraceEntry {
virtual void print(llvm::raw_ostream &OS) const;
};
/// \brief RAII object that enters a new expression evaluation context.
class EnterExpressionEvaluationContext {
/// \brief The action object.
Action &Actions;
/// \brief The previous expression evaluation context.
Action::ExpressionEvaluationContext PrevContext;
/// \brief The current expression evaluation context.
Action::ExpressionEvaluationContext CurContext;
public:
EnterExpressionEvaluationContext(Action &Actions,
Action::ExpressionEvaluationContext NewContext)
: Actions(Actions), CurContext(NewContext) {
PrevContext = Actions.PushExpressionEvaluationContext(NewContext);
}
~EnterExpressionEvaluationContext() {
Actions.PopExpressionEvaluationContext(CurContext, PrevContext);
}
};
} // end namespace clang
#endif

View File

@ -104,24 +104,6 @@ class Parser {
GreaterThanIsOperator = OldGreaterThanIsOperator;
}
};
/// \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);

View File

@ -379,7 +379,7 @@ Stmt *FunctionDecl::getBodyIfAvailable() const {
void FunctionDecl::setBody(Stmt *B) {
Body = B;
if (B && EndRangeLoc < B->getLocEnd())
if (B)
EndRangeLoc = B->getLocEnd();
}
@ -494,8 +494,9 @@ void FunctionDecl::setParams(ASTContext& C, ParmVarDecl **NewParamInfo,
ParamInfo = new (Mem) ParmVarDecl*[NumParams];
memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams);
// Update source range.
if (EndRangeLoc < NewParamInfo[NumParams-1]->getLocEnd())
// Update source range. The check below allows us to set EndRangeLoc before
// setting the parameters.
if (EndRangeLoc.isInvalid() || EndRangeLoc == getLocation())
EndRangeLoc = NewParamInfo[NumParams-1]->getLocEnd();
}
}

View File

@ -66,21 +66,29 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
}
bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const {
return getCopyConstructor(Context, QualType::Const) != 0;
}
CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(ASTContext &Context,
unsigned TypeQuals) const{
QualType ClassType
= Context.getTypeDeclType(const_cast<CXXRecordDecl*>(this));
DeclarationName ConstructorName
= Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(ClassType));
unsigned TypeQuals;
Context.getCanonicalType(ClassType));
unsigned FoundTQs;
DeclContext::lookup_const_iterator Con, ConEnd;
for (llvm::tie(Con, ConEnd) = this->lookup(Context, ConstructorName);
Con != ConEnd; ++Con) {
if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context, TypeQuals) &&
(TypeQuals & QualType::Const) != 0)
return true;
if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context,
FoundTQs)) {
if (((TypeQuals & QualType::Const) == (FoundTQs & QualType::Const)) ||
(!(TypeQuals & QualType::Const) && (FoundTQs & QualType::Const)))
return cast<CXXConstructorDecl>(*Con);
}
}
return false;
return 0;
}
bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context) const {

View File

@ -239,79 +239,103 @@ TemplateArgument::TemplateArgument(Expr *E) : Kind(Expression) {
}
/// \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];
void TemplateArgument::setArgumentPack(TemplateArgument *args, unsigned NumArgs,
bool CopyArgs) {
assert(isNull() && "Must call setArgumentPack on a null argument");
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 != Args.NumArgs; ++I)
Args.Args[I] = args[I];
}
//===----------------------------------------------------------------------===//
// TemplateArgumentListBuilder Implementation
//===----------------------------------------------------------------------===//
void TemplateArgumentListBuilder::push_back(const TemplateArgument& Arg) {
void TemplateArgumentListBuilder::Append(const TemplateArgument& Arg) {
switch (Arg.getKind()) {
default: break;
case TemplateArgument::Type:
assert(Arg.getAsType()->isCanonical() && "Type must be canonical!");
break;
default: break;
case TemplateArgument::Type:
assert(Arg.getAsType()->isCanonical() && "Type must be canonical!");
break;
}
FlatArgs.push_back(Arg);
assert(NumFlatArgs < MaxFlatArgs && "Argument list builder is full!");
assert(!StructuredArgs &&
"Can't append arguments when an argument pack has been added!");
if (!isAddingFromParameterPack())
StructuredArgs.push_back(Arg);
if (!FlatArgs)
FlatArgs = new TemplateArgument[MaxFlatArgs];
FlatArgs[NumFlatArgs++] = Arg;
}
void TemplateArgumentListBuilder::BeginParameterPack() {
assert(!isAddingFromParameterPack() && "Already adding to parameter pack!");
PackBeginIndex = FlatArgs.size();
void TemplateArgumentListBuilder::BeginPack() {
assert(!AddingToPack && "Already adding to pack!");
assert(!StructuredArgs && "Argument list already contains a pack!");
AddingToPack = true;
PackBeginIndex = NumFlatArgs;
}
void TemplateArgumentListBuilder::EndParameterPack() {
assert(isAddingFromParameterPack() && "Not adding to parameter pack!");
void TemplateArgumentListBuilder::EndPack() {
assert(AddingToPack && "Not adding to pack!");
assert(!StructuredArgs && "Argument list already contains a pack!");
AddingToPack = false;
unsigned NumArgs = FlatArgs.size() - PackBeginIndex;
TemplateArgument *Args = NumArgs ? &FlatArgs[PackBeginIndex] : 0;
StructuredArgs = new TemplateArgument[MaxStructuredArgs];
StructuredArgs.push_back(TemplateArgument(SourceLocation(), Args, NumArgs,
/*CopyArgs=*/false));
// First copy the flat entries over to the list (if any)
for (unsigned I = 0; I != PackBeginIndex; ++I) {
NumStructuredArgs++;
StructuredArgs[I] = FlatArgs[I];
}
PackBeginIndex = std::numeric_limits<unsigned>::max();
}
// Next, set the pack.
TemplateArgument *PackArgs = 0;
unsigned NumPackArgs = NumFlatArgs - PackBeginIndex;
if (NumPackArgs)
PackArgs = &FlatArgs[PackBeginIndex];
StructuredArgs[NumStructuredArgs++].setArgumentPack(PackArgs, NumPackArgs,
/*CopyArgs=*/false);
}
void TemplateArgumentListBuilder::ReleaseArgs() {
FlatArgs = 0;
NumFlatArgs = 0;
MaxFlatArgs = 0;
StructuredArgs = 0;
NumStructuredArgs = 0;
MaxStructuredArgs = 0;
}
//===----------------------------------------------------------------------===//
// TemplateArgumentList Implementation
//===----------------------------------------------------------------------===//
TemplateArgumentList::TemplateArgumentList(ASTContext &Context,
TemplateArgumentListBuilder &Builder,
bool CopyArgs, bool FlattenArgs)
: NumArguments(Builder.flatSize()) {
if (!CopyArgs) {
Arguments.setPointer(Builder.getFlatArgumentList());
Arguments.setInt(1);
return;
}
bool TakeArgs)
: FlatArguments(Builder.getFlatArguments(), TakeArgs),
NumFlatArguments(Builder.flatSize()),
StructuredArguments(Builder.getStructuredArguments(), TakeArgs),
NumStructuredArguments(Builder.structuredSize()) {
unsigned Size = sizeof(TemplateArgument) * Builder.flatSize();
unsigned Align = llvm::AlignOf<TemplateArgument>::Alignment;
void *Mem = Context.Allocate(Size, Align);
Arguments.setPointer((TemplateArgument *)Mem);
Arguments.setInt(0);
TemplateArgument *Args = (TemplateArgument *)Mem;
for (unsigned I = 0; I != NumArguments; ++I)
new (Args + I) TemplateArgument(Builder.getFlatArgumentList()[I]);
if (!TakeArgs)
return;
if (Builder.getStructuredArguments() == Builder.getFlatArguments())
StructuredArguments.setInt(0);
Builder.ReleaseArgs();
}
TemplateArgumentList::~TemplateArgumentList() {
@ -333,7 +357,7 @@ ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK,
// class template specializations?
SpecializedTemplate->getIdentifier()),
SpecializedTemplate(SpecializedTemplate),
TemplateArgs(Context, Builder, /*CopyArgs=*/true, /*FlattenArgs=*/true),
TemplateArgs(Context, Builder, /*TakeArgs=*/true),
SpecializationKind(TSK_Undeclared) {
}

View File

@ -63,7 +63,7 @@ class VISIBILITY_HIDDEN BasicStoreManager : public StoreManager {
// FIXME: Investigate what is using this. This method should be removed.
virtual Loc getLoc(const VarDecl* VD) {
return Loc::MakeVal(MRMgr.getVarRegion(VD));
return ValMgr.makeLoc(MRMgr.getVarRegion(VD));
}
const GRState *BindCompoundLiteral(const GRState *state,
@ -126,17 +126,17 @@ StoreManager* clang::CreateBasicStoreManager(GRStateManager& StMgr) {
}
SVal BasicStoreManager::getLValueVar(const GRState *state, const VarDecl* VD) {
return Loc::MakeVal(MRMgr.getVarRegion(VD));
return ValMgr.makeLoc(MRMgr.getVarRegion(VD));
}
SVal BasicStoreManager::getLValueString(const GRState *state,
const StringLiteral* S) {
return Loc::MakeVal(MRMgr.getStringRegion(S));
return ValMgr.makeLoc(MRMgr.getStringRegion(S));
}
SVal BasicStoreManager::getLValueCompoundLiteral(const GRState *state,
const CompoundLiteralExpr* CL){
return Loc::MakeVal(MRMgr.getCompoundLiteralRegion(CL));
return ValMgr.makeLoc(MRMgr.getCompoundLiteralRegion(CL));
}
SVal BasicStoreManager::getLValueIvar(const GRState *state, const ObjCIvarDecl* D,
@ -151,7 +151,7 @@ SVal BasicStoreManager::getLValueIvar(const GRState *state, const ObjCIvarDecl*
const MemRegion *BaseR = cast<loc::MemRegionVal>(BaseL).getRegion();
if (BaseR == SelfRegion)
return loc::MemRegionVal(MRMgr.getObjCIvarRegion(D, BaseR));
return ValMgr.makeLoc(MRMgr.getObjCIvarRegion(D, BaseR));
}
return UnknownVal();
@ -186,7 +186,7 @@ SVal BasicStoreManager::getLValueField(const GRState *state, SVal Base,
return Base;
}
return Loc::MakeVal(MRMgr.getFieldRegion(D, BaseR));
return ValMgr.makeLoc(MRMgr.getFieldRegion(D, BaseR));
}
SVal BasicStoreManager::getLValueElement(const GRState *state,
@ -242,8 +242,8 @@ SVal BasicStoreManager::getLValueElement(const GRState *state,
}
if (BaseR)
return Loc::MakeVal(MRMgr.getElementRegion(elementType, UnknownVal(),
BaseR, getContext()));
return ValMgr.makeLoc(MRMgr.getElementRegion(elementType, UnknownVal(),
BaseR, getContext()));
else
return UnknownVal();
}
@ -351,7 +351,7 @@ Store BasicStoreManager::BindInternal(Store store, Loc loc, SVal V) {
// are incompatible. This may also cause lots of breakage
// elsewhere. Food for thought.
if (const TypedRegion *TyR = dyn_cast<TypedRegion>(R)) {
if (TyR->isBoundable(C) &&
if (TyR->isBoundable() &&
Loc::IsLocType(TyR->getValueType(C)))
V = X->getLoc();
}
@ -456,7 +456,7 @@ BasicStoreManager::RemoveDeadBindings(const GRState *state, Stmt* Loc,
const MemRegion* R = I.getKey();
if (!Marked.count(R)) {
store = Remove(store, Loc::MakeVal(R));
store = Remove(store, ValMgr.makeLoc(R));
SVal X = I.getData();
for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
@ -483,7 +483,7 @@ Store BasicStoreManager::scanForIvars(Stmt *B, const Decl* SelfDecl, Store St) {
const MemRegion *IVR = MRMgr.getObjCIvarRegion(IV->getDecl(),
SelfRegion);
SVal X = ValMgr.getRegionValueSymbolVal(IVR);
St = BindInternal(St, Loc::MakeVal(IVR), X);
St = BindInternal(St, ValMgr.makeLoc(IVR), X);
}
}
}
@ -515,8 +515,8 @@ Store BasicStoreManager::getInitialStore() {
SelfRegion = MRMgr.getObjCObjectRegion(MD->getClassInterface(),
MRMgr.getHeapRegion());
St = BindInternal(St, Loc::MakeVal(MRMgr.getVarRegion(PD)),
Loc::MakeVal(SelfRegion));
St = BindInternal(St, ValMgr.makeLoc(MRMgr.getVarRegion(PD)),
ValMgr.makeLoc(SelfRegion));
// Scan the method for ivar references. While this requires an
// entire AST scan, the cost should not be high in practice.
@ -541,7 +541,7 @@ Store BasicStoreManager::getInitialStore() {
? ValMgr.getRegionValueSymbolVal(R)
: UndefinedVal();
St = BindInternal(St, Loc::MakeVal(R), X);
St = BindInternal(St, ValMgr.makeLoc(R), X);
}
}
return St;

View File

@ -2835,7 +2835,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
// Remove any existing reference-count binding.
if (Sym) state = state->remove<RefBindings>(Sym);
if (R->isBoundable(Ctx)) {
if (R->isBoundable()) {
// Set the value of the variable to be a conjured symbol.
unsigned Count = Builder.getCurrentBlockCount();
QualType T = R->getValueType(Ctx);
@ -2843,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(ValMgr.makeLoc(R), V);
}
else if (const RecordType *RT = T->getAsStructureType()) {
// Handle structs in a not so awesome way. Here we just
@ -2873,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(ValMgr.makeLoc(FR), V);
}
}
} else if (const ArrayType *AT = Ctx.getAsArrayType(T)) {
@ -2987,7 +2987,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
QualType RetT = GetReturnType(Ex, ValMgr.getContext());
state = state->set<RefBindings>(Sym, RefVal::makeOwned(RE.getObjKind(),
RetT));
state = state->bindExpr(Ex, ValMgr.makeRegionVal(Sym), false);
state = state->bindExpr(Ex, ValMgr.makeLoc(Sym), false);
// FIXME: Add a flag to the checker where allocations are assumed to
// *not fail.
@ -3010,7 +3010,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
QualType RetT = GetReturnType(Ex, ValMgr.getContext());
state = state->set<RefBindings>(Sym, RefVal::makeNotOwned(RE.getObjKind(),
RetT));
state = state->bindExpr(Ex, ValMgr.makeRegionVal(Sym), false);
state = state->bindExpr(Ex, ValMgr.makeLoc(Sym), false);
break;
}
}

View File

@ -18,14 +18,14 @@
using namespace clang;
SVal Environment::GetSVal(const Stmt *E, BasicValueFactory& BasicVals) const {
SVal Environment::GetSVal(const Stmt *E, ValueManager& ValMgr) const {
for (;;) {
switch (E->getStmtClass()) {
case Stmt::AddrLabelExprClass:
return Loc::MakeVal(cast<AddrLabelExpr>(E));
return ValMgr.makeLoc(cast<AddrLabelExpr>(E));
// ParenExprs are no-ops.
@ -35,11 +35,11 @@ SVal Environment::GetSVal(const Stmt *E, BasicValueFactory& BasicVals) const {
case Stmt::CharacterLiteralClass: {
const CharacterLiteral* C = cast<CharacterLiteral>(E);
return NonLoc::MakeVal(BasicVals, C->getValue(), C->getType());
return ValMgr.makeIntVal(C->getValue(), C->getType());
}
case Stmt::IntegerLiteralClass: {
return NonLoc::MakeVal(BasicVals, cast<IntegerLiteral>(E));
return ValMgr.makeIntVal(cast<IntegerLiteral>(E));
}
// Casts where the source and target type are the same
@ -69,8 +69,7 @@ SVal Environment::GetSVal(const Stmt *E, BasicValueFactory& BasicVals) const {
return LookupExpr(E);
}
SVal Environment::GetBlkExprSVal(const Stmt *E,
BasicValueFactory& BasicVals) const {
SVal Environment::GetBlkExprSVal(const Stmt *E, ValueManager& ValMgr) const {
while (1) {
switch (E->getStmtClass()) {
@ -80,11 +79,11 @@ SVal Environment::GetBlkExprSVal(const Stmt *E,
case Stmt::CharacterLiteralClass: {
const CharacterLiteral* C = cast<CharacterLiteral>(E);
return NonLoc::MakeVal(BasicVals, C->getValue(), C->getType());
return ValMgr.makeIntVal(C->getValue(), C->getType());
}
case Stmt::IntegerLiteralClass: {
return NonLoc::MakeVal(BasicVals, cast<IntegerLiteral>(E));
return ValMgr.makeIntVal(cast<IntegerLiteral>(E));
}
default:

View File

@ -905,16 +905,19 @@ void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, NodeTy* Pred,
// this right now, and since most logical expressions are used for branches,
// the payoff is not likely to be large. Instead, we do eager evaluation.
if (const GRState *newState = state->assume(X, true))
MakeNode(Dst, B, Pred, newState->bindBlkExpr(B, MakeConstantVal(1U, B)));
MakeNode(Dst, B, Pred,
newState->bindBlkExpr(B, ValMgr.makeIntVal(1U, B->getType())));
if (const GRState *newState = state->assume(X, false))
MakeNode(Dst, B, Pred, newState->bindBlkExpr(B, MakeConstantVal(0U, B)));
MakeNode(Dst, B, Pred,
newState->bindBlkExpr(B, ValMgr.makeIntVal(0U, B->getType())));
}
else {
// We took the LHS expression. Depending on whether we are '&&' or
// '||' we know what the value of the expression is via properties of
// the short-circuiting.
X = MakeConstantVal( B->getOpcode() == BinaryOperator::LAnd ? 0U : 1U, B);
X = ValMgr.makeIntVal(B->getOpcode() == BinaryOperator::LAnd ? 0U : 1U,
B->getType());
MakeNode(Dst, B, Pred, state->bindBlkExpr(B, X));
}
}
@ -944,8 +947,7 @@ void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* Ex, NodeTy* Pred, NodeSet& Dst,
} else if (const EnumConstantDecl* ED = dyn_cast<EnumConstantDecl>(D)) {
assert(!asLValue && "EnumConstantDecl does not have lvalue.");
BasicValueFactory& BasicVals = StateMgr.getBasicVals();
SVal V = nonloc::ConcreteInt(BasicVals.getValue(ED->getInitVal()));
SVal V = ValMgr.makeIntVal(ED->getInitVal());
MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V));
return;
@ -1615,14 +1617,16 @@ void GRExprEngine::EvalEagerlyAssume(NodeSet &Dst, NodeSet &Src, Expr *Ex) {
if (isa<nonloc::SymExprVal>(V)) {
// First assume that the condition is true.
if (const GRState *stateTrue = state->assume(V, true)) {
stateTrue = stateTrue->bindExpr(Ex, MakeConstantVal(1U, Ex));
stateTrue = stateTrue->bindExpr(Ex,
ValMgr.makeIntVal(1U, Ex->getType()));
Dst.Add(Builder->generateNode(PostStmtCustom(Ex, &EagerlyAssumeTag),
stateTrue, Pred));
}
// Next, assume that the condition is false.
if (const GRState *stateFalse = state->assume(V, false)) {
stateFalse = stateFalse->bindExpr(Ex, MakeConstantVal(0U, Ex));
stateFalse = stateFalse->bindExpr(Ex,
ValMgr.makeIntVal(0U, Ex->getType()));
Dst.Add(Builder->generateNode(PostStmtCustom(Ex, &EagerlyAssumeTag),
stateFalse, Pred));
}
@ -1725,12 +1729,11 @@ void GRExprEngine::VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S,
const GRState *state = GetState(Pred);
// Handle the case where the container still has elements.
QualType IntTy = getContext().IntTy;
SVal TrueV = NonLoc::MakeVal(getBasicVals(), 1, IntTy);
SVal TrueV = ValMgr.makeTruthVal(1);
const GRState *hasElems = state->bindExpr(S, TrueV);
// Handle the case where the container has no elements.
SVal FalseV = NonLoc::MakeVal(getBasicVals(), 0, IntTy);
SVal FalseV = ValMgr.makeTruthVal(0);
const GRState *noElems = state->bindExpr(S, FalseV);
if (loc::MemRegionVal* MV = dyn_cast<loc::MemRegionVal>(&ElementV))
@ -1742,11 +1745,11 @@ void GRExprEngine::VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S,
assert (Loc::IsLocType(T));
unsigned Count = Builder->getCurrentBlockCount();
SymbolRef Sym = SymMgr.getConjuredSymbol(elem, T, Count);
SVal V = Loc::MakeVal(getStoreManager().getRegionManager().getSymbolicRegion(Sym));
SVal V = ValMgr.makeLoc(Sym);
hasElems = hasElems->bindLoc(ElementV, V);
// Bind the location to 'nil' on the false branch.
SVal nilV = loc::ConcreteInt(getBasicVals().getValue(0, T));
SVal nilV = ValMgr.makeIntVal(0, T);
noElems = noElems->bindLoc(ElementV, nilV);
}
@ -2290,7 +2293,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, NodeTy* Pred,
// Handle base case where the initializer has no elements.
// e.g: static int* myArray[] = {};
if (NumInitElements == 0) {
SVal V = NonLoc::MakeCompoundVal(T, StartVals, getBasicVals());
SVal V = ValMgr.makeCompoundVal(T, StartVals);
MakeNode(Dst, E, Pred, state->bindExpr(E, V));
return;
}
@ -2323,7 +2326,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, NodeTy* Pred,
if (NewItr == ItrEnd) {
// Now we have a list holding all init values. Make CompoundValData.
SVal V = NonLoc::MakeCompoundVal(T, NewVals, getBasicVals());
SVal V = ValMgr.makeCompoundVal(T, NewVals);
// Make final state and node.
MakeNode(Dst, E, *NI, state->bindExpr(E, V));
@ -2393,8 +2396,7 @@ void GRExprEngine::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex,
amt = getContext().getTypeAlign(T) / 8;
MakeNode(Dst, Ex, Pred,
GetState(Pred)->bindExpr(Ex, NonLoc::MakeVal(getBasicVals(), amt,
Ex->getType())));
GetState(Pred)->bindExpr(Ex, ValMgr.makeIntVal(amt, Ex->getType())));
}
@ -2468,7 +2470,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
// For all other types, UnaryOperator::Float returns 0.
assert (Ex->getType()->isIntegerType());
const GRState* state = GetState(*I);
SVal X = NonLoc::MakeVal(getBasicVals(), 0, Ex->getType());
SVal X = ValMgr.makeZeroVal(Ex->getType());
MakeNode(Dst, U, *I, state->bindExpr(U, X));
}
@ -2571,7 +2573,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
// transfer functions as "0 == E".
if (isa<Loc>(V)) {
Loc X = Loc::MakeNull(getBasicVals());
Loc X = ValMgr.makeNull();
SVal Result = EvalBinOp(state,BinaryOperator::EQ, cast<Loc>(V), X,
U->getType());
state = state->bindExpr(U, Result);
@ -2629,7 +2631,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
BinaryOperator::Opcode Op = U->isIncrementOp() ? BinaryOperator::Add
: BinaryOperator::Sub;
SVal Result = EvalBinOp(state, Op, V2, MakeConstantVal(1U, U),
SVal Result = EvalBinOp(state, Op, V2, ValMgr.makeIntVal(1U,U->getType()),
U->getType());
// Conjure a new symbol if necessary to recover precision.

View File

@ -717,7 +717,7 @@ class VISIBILITY_HIDDEN FindLastStoreBRVisitor : public BugReporterVisitor {
if (isa<loc::ConcreteInt>(V)) {
bool b = false;
ASTContext &C = BRC.getASTContext();
if (R->isBoundable(C)) {
if (R->isBoundable()) {
if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) {
if (C.isObjCObjectPointerType(TR->getValueType(C))) {
os << "initialized to nil";
@ -748,7 +748,7 @@ class VISIBILITY_HIDDEN FindLastStoreBRVisitor : public BugReporterVisitor {
if (isa<loc::ConcreteInt>(V)) {
bool b = false;
ASTContext &C = BRC.getASTContext();
if (R->isBoundable(C)) {
if (R->isBoundable()) {
if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) {
if (C.isObjCObjectPointerType(TR->getValueType(C))) {
os << "nil object reference stored to ";

View File

@ -84,7 +84,7 @@ SVal GRSimpleVals::EvalCast(GRExprEngine& Eng, Loc X, QualType T) {
unsigned BitWidth = Eng.getContext().getTypeSize(T);
if (!isa<loc::ConcreteInt>(X))
return nonloc::LocAsInteger::Make(BasicVals, X, BitWidth);
return Eng.getValueManager().makeLocAsInteger(X, BitWidth);
llvm::APSInt V = cast<loc::ConcreteInt>(X).getValue();
V.setIsUnsigned(T->isUnsignedIntegerType() || Loc::IsLocType(T));
@ -133,8 +133,8 @@ SVal GRSimpleVals::DetermEvalBinOpNN(GRExprEngine& Eng,
BinaryOperator::Opcode Op,
NonLoc L, NonLoc R,
QualType T) {
BasicValueFactory& BasicVals = Eng.getBasicVals();
ValueManager& ValMgr = Eng.getValueManager();
unsigned subkind = L.getSubKind();
while (1) {
@ -157,16 +157,15 @@ SVal GRSimpleVals::DetermEvalBinOpNN(GRExprEngine& Eng,
llvm::APSInt V = cast<nonloc::ConcreteInt>(R).getValue();
V.setIsUnsigned(true);
V.extOrTrunc(Ctx.getTypeSize(Ctx.VoidPtrTy));
return EvalBinOp(Eng, Op, LL,
loc::ConcreteInt(BasicVals.getValue(V)));
return EvalBinOp(Eng, Op, LL, ValMgr.makeLoc(V));
}
default:
switch (Op) {
case BinaryOperator::EQ:
return NonLoc::MakeIntTruthVal(BasicVals, false);
return ValMgr.makeTruthVal(false);
case BinaryOperator::NE:
return NonLoc::MakeIntTruthVal(BasicVals, true);
return ValMgr.makeTruthVal(true);
default:
// This case also handles pointer arithmetic.
return UnknownVal();
@ -289,7 +288,7 @@ SVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, const GRState *state,
SVal GRSimpleVals::EvalEquality(GRExprEngine& Eng, Loc L, Loc R, bool isEqual) {
BasicValueFactory& BasicVals = Eng.getBasicVals();
ValueManager& ValMgr = Eng.getValueManager();
switch (L.getSubKind()) {
@ -307,7 +306,7 @@ SVal GRSimpleVals::EvalEquality(GRExprEngine& Eng, Loc L, Loc R, bool isEqual) {
if (!isEqual)
b = !b;
return NonLoc::MakeIntTruthVal(BasicVals, b);
return ValMgr.makeTruthVal(b);
}
else if (SymbolRef Sym = R.getAsSymbol()) {
const SymIntExpr * SE =
@ -339,10 +338,10 @@ SVal GRSimpleVals::EvalEquality(GRExprEngine& Eng, Loc L, Loc R, bool isEqual) {
// Fall-through.
case loc::GotoLabelKind:
return NonLoc::MakeIntTruthVal(BasicVals, isEqual ? L == R : L != R);
return ValMgr.makeTruthVal(isEqual ? L == R : L != R);
}
return NonLoc::MakeIntTruthVal(BasicVals, isEqual ? false : true);
return ValMgr.makeTruthVal(isEqual ? false : true);
}
//===----------------------------------------------------------------------===//
@ -367,8 +366,8 @@ void GRSimpleVals::EvalCall(ExplodedNodeSet<GRState>& Dst,
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());
if (R->isBoundable())
St = StateMgr.BindLoc(St, cast<Loc>(V), UnknownVal());
} else if (isa<nonloc::LocAsInteger>(V))
St = StateMgr.BindLoc(St, cast<nonloc::LocAsInteger>(V).getLoc(),
UnknownVal());

View File

@ -18,6 +18,9 @@
using namespace clang;
//===----------------------------------------------------------------------===//
// Basic methods.
//===----------------------------------------------------------------------===//
MemRegion::~MemRegion() {}
@ -34,6 +37,19 @@ bool SubRegion::isSubRegionOf(const MemRegion* R) const {
return false;
}
MemRegionManager* SubRegion::getMemRegionManager() const {
const SubRegion* r = this;
do {
const MemRegion *superRegion = r->getSuperRegion();
if (const SubRegion *sr = dyn_cast<SubRegion>(superRegion)) {
r = sr;
continue;
}
return superRegion->getMemRegionManager();
} while (1);
}
void MemSpaceRegion::Profile(llvm::FoldingSetNodeID& ID) const {
ID.AddInteger((unsigned)getKind());
}
@ -47,14 +63,15 @@ void StringRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
}
void AllocaRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
const Expr* Ex, unsigned cnt) {
const Expr* Ex, unsigned cnt,
const MemRegion *) {
ID.AddInteger((unsigned) AllocaRegionKind);
ID.AddPointer(Ex);
ID.AddInteger(cnt);
}
void AllocaRegion::Profile(llvm::FoldingSetNodeID& ID) const {
ProfileRegion(ID, Ex, Cnt);
ProfileRegion(ID, Ex, Cnt, superRegion);
}
void TypedViewRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, QualType T,
@ -87,13 +104,15 @@ void DeclRegion::Profile(llvm::FoldingSetNodeID& ID) const {
DeclRegion::ProfileRegion(ID, D, superRegion, getKind());
}
void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym) {
void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym,
const MemRegion *sreg) {
ID.AddInteger((unsigned) MemRegion::SymbolicRegionKind);
ID.Add(sym);
ID.AddPointer(sreg);
}
void SymbolicRegion::Profile(llvm::FoldingSetNodeID& ID) const {
SymbolicRegion::ProfileRegion(ID, sym);
SymbolicRegion::ProfileRegion(ID, sym, getSuperRegion());
}
void ElementRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
@ -110,14 +129,14 @@ void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const {
}
void CodeTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const void* data,
QualType t) {
QualType t, const MemRegion*) {
ID.AddInteger(MemRegion::CodeTextRegionKind);
ID.AddPointer(data);
ID.Add(t);
}
void CodeTextRegion::Profile(llvm::FoldingSetNodeID& ID) const {
CodeTextRegion::ProfileRegion(ID, Data, LocationType);
CodeTextRegion::ProfileRegion(ID, Data, LocationType, superRegion);
}
//===----------------------------------------------------------------------===//
@ -186,13 +205,12 @@ void VarRegion::print(llvm::raw_ostream& os) const {
// MemRegionManager methods.
//===----------------------------------------------------------------------===//
MemSpaceRegion* MemRegionManager::LazyAllocate(MemSpaceRegion*& region) {
MemSpaceRegion* MemRegionManager::LazyAllocate(MemSpaceRegion*& region) {
if (!region) {
region = (MemSpaceRegion*) A.Allocate<MemSpaceRegion>();
new (region) MemSpaceRegion();
new (region) MemSpaceRegion(this);
}
return region;
}
@ -216,82 +234,21 @@ MemSpaceRegion* MemRegionManager::getCodeRegion() {
return LazyAllocate(code);
}
bool MemRegionManager::onStack(const MemRegion* R) {
while (const SubRegion* SR = dyn_cast<SubRegion>(R))
R = SR->getSuperRegion();
return (R != 0) && (R == stack);
}
bool MemRegionManager::onHeap(const MemRegion* R) {
while (const SubRegion* SR = dyn_cast<SubRegion>(R))
R = SR->getSuperRegion();
return (R != 0) && (R == heap);
}
//===----------------------------------------------------------------------===//
// Constructing regions.
//===----------------------------------------------------------------------===//
StringRegion* MemRegionManager::getStringRegion(const StringLiteral* Str) {
llvm::FoldingSetNodeID ID;
MemSpaceRegion* GlobalsR = getGlobalsRegion();
StringRegion::ProfileRegion(ID, Str, GlobalsR);
void* InsertPos;
MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
StringRegion* R = cast_or_null<StringRegion>(data);
if (!R) {
R = (StringRegion*) A.Allocate<StringRegion>();
new (R) StringRegion(Str, GlobalsR);
Regions.InsertNode(R, InsertPos);
}
return R;
return getRegion<StringRegion>(Str);
}
VarRegion* MemRegionManager::getVarRegion(const VarDecl* d) {
const MemRegion* superRegion = d->hasLocalStorage() ? getStackRegion()
: getGlobalsRegion();
llvm::FoldingSetNodeID ID;
DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::VarRegionKind);
void* InsertPos;
MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
VarRegion* R = cast_or_null<VarRegion>(data);
if (!R) {
R = (VarRegion*) A.Allocate<VarRegion>();
new (R) VarRegion(d, superRegion);
Regions.InsertNode(R, InsertPos);
}
return R;
return getRegion<VarRegion>(d);
}
CompoundLiteralRegion*
MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr* CL) {
// Is this compound literal allocated on the stack or is part of the
// global constant pool?
const MemRegion* superRegion = CL->isFileScope() ?
getGlobalsRegion() : getStackRegion();
// Profile the compound literal.
llvm::FoldingSetNodeID ID;
CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion);
void* InsertPos;
MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
CompoundLiteralRegion* R = cast_or_null<CompoundLiteralRegion>(data);
if (!R) {
R = (CompoundLiteralRegion*) A.Allocate<CompoundLiteralRegion>();
new (R) CompoundLiteralRegion(CL, superRegion);
Regions.InsertNode(R, InsertPos);
}
return R;
return getRegion<CompoundLiteralRegion>(CL);
}
ElementRegion*
@ -318,149 +275,45 @@ MemRegionManager::getElementRegion(QualType elementType, SVal Idx,
CodeTextRegion* MemRegionManager::getCodeTextRegion(const FunctionDecl* fd,
QualType t) {
llvm::FoldingSetNodeID ID;
CodeTextRegion::ProfileRegion(ID, fd, t);
void* InsertPos;
MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
CodeTextRegion* R = cast_or_null<CodeTextRegion>(data);
if (!R) {
R = (CodeTextRegion*) A.Allocate<CodeTextRegion>();
new (R) CodeTextRegion(fd, t, getCodeRegion());
Regions.InsertNode(R, InsertPos);
}
return R;
return getRegion<CodeTextRegion>(fd, t);
}
CodeTextRegion* MemRegionManager::getCodeTextRegion(SymbolRef sym, QualType t) {
llvm::FoldingSetNodeID ID;
CodeTextRegion::ProfileRegion(ID, sym, t);
void* InsertPos;
MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
CodeTextRegion* R = cast_or_null<CodeTextRegion>(data);
if (!R) {
R = (CodeTextRegion*) A.Allocate<CodeTextRegion>();
new (R) CodeTextRegion(sym, t, getCodeRegion());
Regions.InsertNode(R, InsertPos);
}
return R;
return getRegion<CodeTextRegion>(sym, t);
}
/// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
SymbolicRegion* MemRegionManager::getSymbolicRegion(SymbolRef sym) {
llvm::FoldingSetNodeID ID;
SymbolicRegion::ProfileRegion(ID, sym);
void* InsertPos;
MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
SymbolicRegion* R = cast_or_null<SymbolicRegion>(data);
if (!R) {
R = (SymbolicRegion*) A.Allocate<SymbolicRegion>();
// SymbolicRegion's storage class is usually unknown.
new (R) SymbolicRegion(sym, getUnknownRegion());
Regions.InsertNode(R, InsertPos);
}
return R;
return getRegion<SymbolicRegion>(sym);
}
FieldRegion* MemRegionManager::getFieldRegion(const FieldDecl* d,
const MemRegion* superRegion) {
llvm::FoldingSetNodeID ID;
DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::FieldRegionKind);
void* InsertPos;
MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
FieldRegion* R = cast_or_null<FieldRegion>(data);
if (!R) {
R = (FieldRegion*) A.Allocate<FieldRegion>();
new (R) FieldRegion(d, superRegion);
Regions.InsertNode(R, InsertPos);
}
return R;
return getRegion<FieldRegion>(d, superRegion);
}
ObjCIvarRegion*
MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl* d,
const MemRegion* superRegion) {
llvm::FoldingSetNodeID ID;
DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::ObjCIvarRegionKind);
void* InsertPos;
MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
ObjCIvarRegion* R = cast_or_null<ObjCIvarRegion>(data);
if (!R) {
R = (ObjCIvarRegion*) A.Allocate<ObjCIvarRegion>();
new (R) ObjCIvarRegion(d, superRegion);
Regions.InsertNode(R, InsertPos);
}
return R;
return getRegion<ObjCIvarRegion>(d, superRegion);
}
ObjCObjectRegion*
MemRegionManager::getObjCObjectRegion(const ObjCInterfaceDecl* d,
const MemRegion* superRegion) {
llvm::FoldingSetNodeID ID;
DeclRegion::ProfileRegion(ID, d, superRegion,
MemRegion::ObjCObjectRegionKind);
void* InsertPos;
MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
ObjCObjectRegion* R = cast_or_null<ObjCObjectRegion>(data);
if (!R) {
R = (ObjCObjectRegion*) A.Allocate<ObjCObjectRegion>();
new (R) ObjCObjectRegion(d, superRegion);
Regions.InsertNode(R, InsertPos);
}
return R;
const MemRegion* superRegion) {
return getRegion<ObjCObjectRegion>(d, superRegion);
}
TypedViewRegion*
MemRegionManager::getTypedViewRegion(QualType t, const MemRegion* superRegion) {
llvm::FoldingSetNodeID ID;
TypedViewRegion::ProfileRegion(ID, t, superRegion);
void* InsertPos;
MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
TypedViewRegion* R = cast_or_null<TypedViewRegion>(data);
if (!R) {
R = (TypedViewRegion*) A.Allocate<TypedViewRegion>();
new (R) TypedViewRegion(t, superRegion);
Regions.InsertNode(R, InsertPos);
}
return R;
return getRegion<TypedViewRegion>(t, superRegion);
}
AllocaRegion* MemRegionManager::getAllocaRegion(const Expr* E, unsigned cnt) {
llvm::FoldingSetNodeID ID;
AllocaRegion::ProfileRegion(ID, E, cnt);
void* InsertPos;
MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
AllocaRegion* R = cast_or_null<AllocaRegion>(data);
if (!R) {
R = (AllocaRegion*) A.Allocate<AllocaRegion>();
new (R) AllocaRegion(E, cnt, getStackRegion());
Regions.InsertNode(R, InsertPos);
}
return R;
return getRegion<AllocaRegion>(E, cnt);
}
bool MemRegionManager::hasStackStorage(const MemRegion* R) {
// Only subregions can have stack storage.
const SubRegion* SR = dyn_cast<SubRegion>(R);
@ -476,10 +329,29 @@ bool MemRegionManager::hasStackStorage(const MemRegion* R) {
SR = dyn_cast<SubRegion>(R);
}
return false;
}
bool MemRegionManager::hasHeapStorage(const MemRegion* R) {
// Only subregions can have stack storage.
const SubRegion* SR = dyn_cast<SubRegion>(R);
if (!SR)
return false;
MemSpaceRegion* H = getHeapRegion();
while (SR) {
R = SR->getSuperRegion();
if (R == H)
return true;
SR = dyn_cast<SubRegion>(R);
}
return false;
}
//===----------------------------------------------------------------------===//
// View handling.

View File

@ -513,7 +513,7 @@ SVal RegionStoreManager::getLValueElement(const GRState *St,
if (OffI.isUnsigned()) {
llvm::APSInt Tmp = OffI;
Tmp.setIsSigned(true);
Offset = NonLoc::MakeVal(getBasicVals(), Tmp);
Offset = ValMgr.makeIntVal(Tmp);
}
}
return loc::MemRegionVal(MRMgr.getElementRegion(elementType, Offset,
@ -547,7 +547,7 @@ SVal RegionStoreManager::getLValueElement(const GRState *St,
Tmp.setIsSigned(true);
Tmp += BaseIdxI; // Compute the new offset.
NewIdx = NonLoc::MakeVal(getBasicVals(), Tmp);
NewIdx = ValMgr.makeIntVal(Tmp);
}
else
NewIdx = nonloc::ConcreteInt(getBasicVals().getValue(BaseIdxI + OffI));
@ -572,7 +572,7 @@ SVal RegionStoreManager::getSizeInElements(const GRState *state,
if (const ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(T)) {
// return the size as signed integer.
return NonLoc::MakeVal(getBasicVals(), CAT->getSize(), false);
return ValMgr.makeIntVal(CAT->getSize(), false);
}
const QualType* CastTy = state->get<RegionCasts>(VR);
@ -585,19 +585,19 @@ SVal RegionStoreManager::getSizeInElements(const GRState *state,
uint64_t EleSize = getContext().getTypeSize(EleTy);
uint64_t VarSize = getContext().getTypeSize(VarTy);
assert(VarSize != 0);
return NonLoc::MakeIntVal(getBasicVals(), VarSize / EleSize, false);
return ValMgr.makeIntVal(VarSize/EleSize, false);
}
// Clients can use ordinary variables as if they were arrays. These
// essentially are arrays of size 1.
return NonLoc::MakeIntVal(getBasicVals(), 1, false);
return ValMgr.makeIntVal(1, false);
}
if (const StringRegion* SR = dyn_cast<StringRegion>(R)) {
const StringLiteral* Str = SR->getStringLiteral();
// We intentionally made the size value signed because it participates in
// operations with signed indices.
return NonLoc::MakeIntVal(getBasicVals(), Str->getByteLength()+1, false);
return ValMgr.makeIntVal(Str->getByteLength()+1, false);
}
if (const FieldRegion* FR = dyn_cast<FieldRegion>(R)) {
@ -676,7 +676,9 @@ RegionStoreManager::CastRegion(const GRState *state, const MemRegion* R,
// CodeTextRegion should be cast to only function pointer type.
if (isa<CodeTextRegion>(R)) {
assert(CastToTy->isFunctionPointerType() || CastToTy->isBlockPointerType());
assert(CastToTy->isFunctionPointerType() || CastToTy->isBlockPointerType()
|| (CastToTy->isPointerType()
&& CastToTy->getAsPointerType()->getPointeeType()->isVoidType()));
return CastResult(state, R);
}
@ -800,7 +802,7 @@ SVal RegionStoreManager::EvalBinOp(const GRState *state,
const MemRegion* NewER =
MRMgr.getElementRegion(ER->getElementType(), NewIdx,ER->getSuperRegion(),
getContext());
return Loc::MakeVal(NewER);
return ValMgr.makeLoc(NewER);
}
@ -937,7 +939,7 @@ SVal RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) {
}
}
if (MRMgr.onStack(R) || MRMgr.onHeap(R)) {
if (MRMgr.hasStackStorage(R) || MRMgr.hasHeapStorage(R)) {
// All stack variables are considered to have undefined values
// upon creation. All heap allocated blocks are considered to
// have undefined values as well unless they are explicitly bound
@ -984,7 +986,7 @@ SVal RegionStoreManager::RetrieveStruct(const GRState *state,
StructVal = getBasicVals().consVals(FieldValue, StructVal);
}
return NonLoc::MakeCompoundVal(T, StructVal, getBasicVals());
return ValMgr.makeCompoundVal(T, StructVal);
}
SVal RegionStoreManager::RetrieveArray(const GRState *state,
@ -998,7 +1000,7 @@ SVal RegionStoreManager::RetrieveArray(const GRState *state,
llvm::APSInt i = getBasicVals().getZeroWithPtrWidth(false);
for (; i < Size; ++i) {
SVal Idx = NonLoc::MakeVal(getBasicVals(), i);
SVal Idx = ValMgr.makeIntVal(i);
ElementRegion* ER = MRMgr.getElementRegion(CAT->getElementType(), Idx, R,
getContext());
QualType ETy = ER->getElementType();
@ -1006,7 +1008,7 @@ SVal RegionStoreManager::RetrieveArray(const GRState *state,
ArrayVal = getBasicVals().consVals(ElementVal, ArrayVal);
}
return NonLoc::MakeCompoundVal(T, ArrayVal, getBasicVals());
return ValMgr.makeCompoundVal(T, ArrayVal);
}
//===----------------------------------------------------------------------===//
@ -1059,7 +1061,7 @@ const GRState *RegionStoreManager::BindDecl(const GRState *state,
if (T->isStructureType())
return BindStruct(state, VR, InitVal);
return Bind(state, Loc::MakeVal(VR), InitVal);
return Bind(state, ValMgr.makeLoc(VR), InitVal);
}
// FIXME: this method should be merged into Bind().
@ -1077,17 +1079,11 @@ const GRState *RegionStoreManager::BindArray(const GRState *state,
SVal Init) {
QualType T = R->getValueType(getContext());
assert(T->isArrayType());
// When we are binding the whole array, it always has default value 0.
state = state->set<RegionDefaultValue>(R, NonLoc::MakeIntVal(getBasicVals(),
0, false));
ConstantArrayType* CAT = cast<ConstantArrayType>(T.getTypePtr());
QualType ElementTy = CAT->getElementType();
llvm::APSInt Size(CAT->getSize(), false);
llvm::APSInt i = getBasicVals().getValue(0, Size.getBitWidth(),
Size.isUnsigned());
llvm::APSInt i(llvm::APInt::getNullValue(Size.getBitWidth()), false);
// Check if the init expr is a StringLiteral.
if (isa<loc::MemRegionVal>(Init)) {
@ -1104,12 +1100,10 @@ const GRState *RegionStoreManager::BindArray(const GRState *state,
if (j >= len)
break;
SVal Idx = NonLoc::MakeVal(getBasicVals(), i);
ElementRegion* ER =
MRMgr.getElementRegion(cast<ArrayType>(T)->getElementType(),
Idx, R, getContext());
SVal Idx = ValMgr.makeIntVal(i);
ElementRegion* ER = MRMgr.getElementRegion(ElementTy, Idx,R,getContext());
SVal V = NonLoc::MakeVal(getBasicVals(), str[j], sizeof(char)*8, true);
SVal V = ValMgr.makeIntVal(str[j], sizeof(char)*8, true);
state = Bind(state, loc::MemRegionVal(ER), V);
}
@ -1120,19 +1114,29 @@ const GRState *RegionStoreManager::BindArray(const GRState *state,
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
for (; i < Size; ++i, ++VI) {
// The init list might be shorter than the array decl.
// The init list might be shorter than the array length.
if (VI == VE)
break;
SVal Idx = NonLoc::MakeVal(getBasicVals(), i);
ElementRegion* ER =
MRMgr.getElementRegion(cast<ArrayType>(T)->getElementType(),
Idx, R, getContext());
SVal Idx = ValMgr.makeIntVal(i);
ElementRegion* ER = MRMgr.getElementRegion(ElementTy, Idx, R, getContext());
if (CAT->getElementType()->isStructureType())
state = BindStruct(state, ER, *VI);
else
state = Bind(state, Loc::MakeVal(ER), *VI);
state = Bind(state, ValMgr.makeLoc(ER), *VI);
}
// If the init list is shorter than the array length, bind the rest elements
// to 0.
if (ElementTy->isIntegerType()) {
while (i < Size) {
SVal Idx = ValMgr.makeIntVal(i);
ElementRegion* ER = MRMgr.getElementRegion(ElementTy, Idx,R,getContext());
SVal V = ValMgr.makeZeroVal(ElementTy);
state = Bind(state, ValMgr.makeLoc(ER), V);
++i;
}
}
return state;
@ -1161,30 +1165,37 @@ RegionStoreManager::BindStruct(const GRState *state, const TypedRegion* R,
nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(V);
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
for (RecordDecl::field_iterator FI = RD->field_begin(getContext()),
FE = RD->field_end(getContext());
RecordDecl::field_iterator FI, FE;
for (FI = RD->field_begin(getContext()), FE = RD->field_end(getContext());
FI != FE; ++FI, ++VI) {
// There may be fewer values than fields only when we are initializing a
// struct decl. In this case, mark the region as having default value.
if (VI == VE) {
const NonLoc& Idx = NonLoc::MakeIntVal(getBasicVals(), 0, false);
state = state->set<RegionDefaultValue>(R, Idx);
if (VI == VE)
break;
}
QualType FTy = (*FI)->getType();
FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);
if (Loc::IsLocType(FTy) || FTy->isIntegerType())
state = Bind(state, Loc::MakeVal(FR), *VI);
state = Bind(state, ValMgr.makeLoc(FR), *VI);
else if (FTy->isArrayType())
state = BindArray(state, FR, *VI);
else if (FTy->isStructureType())
state = BindStruct(state, FR, *VI);
}
// There may be fewer values in the initialize list than the fields of struct.
while (FI != FE) {
QualType FTy = (*FI)->getType();
if (FTy->isIntegerType()) {
FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);
state = Bind(state, ValMgr.makeLoc(FR), ValMgr.makeZeroVal(FTy));
}
++FI;
}
return state;
}
@ -1202,7 +1213,7 @@ const GRState *RegionStoreManager::KillStruct(const GRState *state,
const MemRegion* R = I.getKey();
if (const SubRegion* subRegion = dyn_cast<SubRegion>(R))
if (subRegion->isSubRegionOf(R))
store = Remove(store, Loc::MakeVal(subRegion));
store = Remove(store, ValMgr.makeLoc(subRegion));
// FIXME: Maybe we should also remove the bindings for the "views" of the
// subregions.
}
@ -1398,7 +1409,7 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState *state, Stmt* Loc,
continue;
// Remove this dead region from the store.
store = Remove(store, Loc::MakeVal(R));
store = Remove(store, ValMgr.makeLoc(R));
// Mark all non-live symbols that this region references as dead.
if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(R))

View File

@ -236,180 +236,6 @@ SVal loc::ConcreteInt::EvalBinOp(BasicValueFactory& BasicVals,
return UndefinedVal();
}
//===----------------------------------------------------------------------===//
// Utility methods for constructing SVals.
//===----------------------------------------------------------------------===//
SVal ValueManager::makeZeroVal(QualType T) {
if (Loc::IsLocType(T))
return Loc::MakeNull(BasicVals);
if (T->isIntegerType())
return NonLoc::MakeVal(BasicVals, 0, T);
// FIXME: Handle floats.
// FIXME: Handle structs.
return UnknownVal();
}
SVal ValueManager::makeZeroArrayIndex() {
return nonloc::ConcreteInt(BasicVals.getZeroWithPtrWidth(false));
}
//===----------------------------------------------------------------------===//
// Utility methods for constructing Non-Locs.
//===----------------------------------------------------------------------===//
NonLoc ValueManager::makeNonLoc(SymbolRef sym) {
return nonloc::SymbolVal(sym);
}
NonLoc ValueManager::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
const APSInt& v, QualType T) {
// The Environment ensures we always get a persistent APSInt in
// BasicValueFactory, so we don't need to get the APSInt from
// BasicValueFactory again.
assert(!Loc::IsLocType(T));
return nonloc::SymExprVal(SymMgr.getSymIntExpr(lhs, op, v, T));
}
NonLoc ValueManager::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
const SymExpr *rhs, QualType T) {
assert(SymMgr.getType(lhs) == SymMgr.getType(rhs));
assert(!Loc::IsLocType(T));
return nonloc::SymExprVal(SymMgr.getSymSymExpr(lhs, op, rhs, T));
}
NonLoc NonLoc::MakeIntVal(BasicValueFactory& BasicVals, uint64_t X,
bool isUnsigned) {
return nonloc::ConcreteInt(BasicVals.getIntValue(X, isUnsigned));
}
NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, uint64_t X,
unsigned BitWidth, bool isUnsigned) {
return nonloc::ConcreteInt(BasicVals.getValue(X, BitWidth, isUnsigned));
}
NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, uint64_t X, QualType T) {
return nonloc::ConcreteInt(BasicVals.getValue(X, T));
}
NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, const IntegerLiteral* I) {
return nonloc::ConcreteInt(BasicVals.getValue(APSInt(I->getValue(),
I->getType()->isUnsignedIntegerType())));
}
NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, const llvm::APInt& I,
bool isUnsigned) {
return nonloc::ConcreteInt(BasicVals.getValue(I, isUnsigned));
}
NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, const llvm::APSInt& I) {
return nonloc::ConcreteInt(BasicVals.getValue(I));
}
NonLoc NonLoc::MakeIntTruthVal(BasicValueFactory& BasicVals, bool b) {
return nonloc::ConcreteInt(BasicVals.getTruthValue(b));
}
NonLoc ValueManager::makeTruthVal(bool b, QualType T) {
return nonloc::ConcreteInt(BasicVals.getTruthValue(b, T));
}
NonLoc NonLoc::MakeCompoundVal(QualType T, llvm::ImmutableList<SVal> Vals,
BasicValueFactory& BasicVals) {
return nonloc::CompoundVal(BasicVals.getCompoundValData(T, Vals));
}
SVal ValueManager::getRegionValueSymbolVal(const MemRegion* R, QualType T) {
SymbolRef sym = SymMgr.getRegionValueSymbol(R, T);
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R)) {
if (T.isNull())
T = TR->getValueType(SymMgr.getContext());
// If T is of function pointer type, create a CodeTextRegion wrapping a
// symbol.
if (T->isFunctionPointerType()) {
return Loc::MakeVal(MemMgr.getCodeTextRegion(sym, T));
}
if (Loc::IsLocType(T))
return Loc::MakeVal(MemMgr.getSymbolicRegion(sym));
// Only handle integers for now.
if (T->isIntegerType() && T->isScalarType())
return makeNonLoc(sym);
}
return UnknownVal();
}
SVal ValueManager::getConjuredSymbolVal(const Expr* E, unsigned Count) {
QualType T = E->getType();
SymbolRef sym = SymMgr.getConjuredSymbol(E, Count);
// If T is of function pointer type, create a CodeTextRegion wrapping a
// symbol.
if (T->isFunctionPointerType()) {
return Loc::MakeVal(MemMgr.getCodeTextRegion(sym, T));
}
if (Loc::IsLocType(T))
return Loc::MakeVal(MemMgr.getSymbolicRegion(sym));
if (T->isIntegerType() && T->isScalarType())
return makeNonLoc(sym);
return UnknownVal();
}
SVal ValueManager::getConjuredSymbolVal(const Expr* E, QualType T,
unsigned Count) {
SymbolRef sym = SymMgr.getConjuredSymbol(E, T, Count);
// If T is of function pointer type, create a CodeTextRegion wrapping a
// symbol.
if (T->isFunctionPointerType()) {
return Loc::MakeVal(MemMgr.getCodeTextRegion(sym, T));
}
if (Loc::IsLocType(T))
return Loc::MakeVal(MemMgr.getSymbolicRegion(sym));
if (T->isIntegerType() && T->isScalarType())
return makeNonLoc(sym);
return UnknownVal();
}
SVal ValueManager::getFunctionPointer(const FunctionDecl* FD) {
CodeTextRegion* R
= MemMgr.getCodeTextRegion(FD, Context.getPointerType(FD->getType()));
return loc::MemRegionVal(R);
}
nonloc::LocAsInteger nonloc::LocAsInteger::Make(BasicValueFactory& Vals, Loc V,
unsigned Bits) {
return LocAsInteger(Vals.getPersistentSValWithData(V, Bits));
}
//===----------------------------------------------------------------------===//
// Utility methods for constructing Locs.
//===----------------------------------------------------------------------===//
Loc Loc::MakeVal(const MemRegion* R) { return loc::MemRegionVal(R); }
Loc Loc::MakeVal(const AddrLabelExpr *E) {
return loc::GotoLabel(E->getLabel());
}
Loc Loc::MakeNull(BasicValueFactory &BasicVals) {
return loc::ConcreteInt(BasicVals.getZeroWithPtrWidth());
}
//===----------------------------------------------------------------------===//
// Pretty-Printing.
//===----------------------------------------------------------------------===//

View File

@ -0,0 +1,125 @@
//== ValueManager.cpp - Aggregate manager of symbols and SVals --*- 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 ValueManager, a class that manages symbolic values
// and SVals created for use by GRExprEngine and related classes. It
// wraps and owns SymbolManager, MemRegionManager, and BasicValueFactory.
//
//===----------------------------------------------------------------------===//
#include "clang/Analysis/PathSensitive/ValueManager.h"
using namespace clang;
using namespace llvm;
//===----------------------------------------------------------------------===//
// Utility methods for constructing SVals.
//===----------------------------------------------------------------------===//
SVal ValueManager::makeZeroVal(QualType T) {
if (Loc::IsLocType(T))
return makeNull();
if (T->isIntegerType())
return makeIntVal(0, T);
// FIXME: Handle floats.
// FIXME: Handle structs.
return UnknownVal();
}
//===----------------------------------------------------------------------===//
// Utility methods for constructing Non-Locs.
//===----------------------------------------------------------------------===//
NonLoc ValueManager::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
const APSInt& v, QualType T) {
// The Environment ensures we always get a persistent APSInt in
// BasicValueFactory, so we don't need to get the APSInt from
// BasicValueFactory again.
assert(!Loc::IsLocType(T));
return nonloc::SymExprVal(SymMgr.getSymIntExpr(lhs, op, v, T));
}
NonLoc ValueManager::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
const SymExpr *rhs, QualType T) {
assert(SymMgr.getType(lhs) == SymMgr.getType(rhs));
assert(!Loc::IsLocType(T));
return nonloc::SymExprVal(SymMgr.getSymSymExpr(lhs, op, rhs, T));
}
SVal ValueManager::getRegionValueSymbolVal(const MemRegion* R, QualType T) {
SymbolRef sym = SymMgr.getRegionValueSymbol(R, T);
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R)) {
if (T.isNull())
T = TR->getValueType(SymMgr.getContext());
// If T is of function pointer type, create a CodeTextRegion wrapping a
// symbol.
if (T->isFunctionPointerType()) {
return loc::MemRegionVal(MemMgr.getCodeTextRegion(sym, T));
}
if (Loc::IsLocType(T))
return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
// Only handle integers for now.
if (T->isIntegerType() && T->isScalarType())
return nonloc::SymbolVal(sym);
}
return UnknownVal();
}
SVal ValueManager::getConjuredSymbolVal(const Expr* E, unsigned Count) {
QualType T = E->getType();
SymbolRef sym = SymMgr.getConjuredSymbol(E, Count);
// If T is of function pointer type, create a CodeTextRegion wrapping a
// symbol.
if (T->isFunctionPointerType()) {
return loc::MemRegionVal(MemMgr.getCodeTextRegion(sym, T));
}
if (Loc::IsLocType(T))
return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
if (T->isIntegerType() && T->isScalarType())
return nonloc::SymbolVal(sym);
return UnknownVal();
}
SVal ValueManager::getConjuredSymbolVal(const Expr* E, QualType T,
unsigned Count) {
SymbolRef sym = SymMgr.getConjuredSymbol(E, T, Count);
// If T is of function pointer type, create a CodeTextRegion wrapping a
// symbol.
if (T->isFunctionPointerType()) {
return loc::MemRegionVal(MemMgr.getCodeTextRegion(sym, T));
}
if (Loc::IsLocType(T))
return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
if (T->isIntegerType() && T->isScalarType())
return nonloc::SymbolVal(sym);
return UnknownVal();
}
SVal ValueManager::getFunctionPointer(const FunctionDecl* FD) {
CodeTextRegion* R
= MemMgr.getCodeTextRegion(FD, Context.getPointerType(FD->getType()));
return loc::MemRegionVal(R);
}

View File

@ -373,7 +373,10 @@ FileID SourceManager::createFileID(const ContentCache *File,
// Set LastFileIDLookup to the newly created file. The next getFileID call is
// almost guaranteed to be from that file.
return LastFileIDLookup = FileID::get(SLocEntryTable.size()-1);
FileID FID = FileID::get(SLocEntryTable.size()-1);
if (File->FirstFID.isInvalid())
File->FirstFID = FID;
return LastFileIDLookup = FID;
}
/// createInstantiationLoc - Return a new SourceLocation that encodes the fact

View File

@ -169,6 +169,7 @@ static bool getDarwinNumber(const char *Triple, unsigned &Maj, unsigned &Min, un
}
static void getDarwinDefines(std::vector<char> &Defs, const LangOptions &Opts) {
Define(Defs, "__APPLE_CC__", "5621");
Define(Defs, "__APPLE__");
Define(Defs, "__MACH__");
Define(Defs, "OBJC_NEW_PROPERTIES");

View File

@ -763,7 +763,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
if (CE->getOpcode() == llvm::Instruction::BitCast &&
ActualFT->getReturnType() == CurFT->getReturnType() &&
ActualFT->getNumParams() == CurFT->getNumParams()) {
ActualFT->getNumParams() == CurFT->getNumParams() &&
ActualFT->getNumParams() == Args.size()) {
bool ArgsMatch = true;
for (unsigned i = 0, e = ActualFT->getNumParams(); i != e; ++i)
if (ActualFT->getParamType(i) != CurFT->getParamType(i)) {

View File

@ -232,7 +232,6 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
DefineBuiltinMacro(Buf, "__clang__=1"); // Clang Frontend
// Currently claim to be compatible with GCC 4.2.1-5621.
DefineBuiltinMacro(Buf, "__APPLE_CC__=5621");
DefineBuiltinMacro(Buf, "__GNUC_MINOR__=2");
DefineBuiltinMacro(Buf, "__GNUC_PATCHLEVEL__=1");
DefineBuiltinMacro(Buf, "__GNUC__=4");

View File

@ -24,6 +24,7 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include <cstdio>
#include <cstring>
#include <utility>
@ -99,7 +100,8 @@ bool clang::ProcessWarningOptions(Diagnostic &Diags,
}
if (Diags.setDiagnosticGroupMapping(OptStart, Mapping))
fprintf(stderr, "warning: unknown warning option: -W%s\n", Opt.c_str());
Diags.Report(FullSourceLoc(), diag::warn_unknown_warning_option)
<< ("-W" + Opt);
}
return false;

View File

@ -473,13 +473,14 @@ char Lexer::getCharAndSizeSlow(const char *Ptr, unsigned &Size,
// Common case, backslash-char where the char is not whitespace.
if (!isWhitespace(Ptr[0])) return '\\';
// See if we have optional whitespace characters followed by a newline.
// See if we have optional whitespace characters between the slash and
// newline.
if (unsigned EscapedNewLineSize = getEscapedNewLineSize(Ptr)) {
// Remember that this token needs to be cleaned.
if (Tok) Tok->setFlag(Token::NeedsCleaning);
// Warn if there was whitespace between the backslash and newline.
if (EscapedNewLineSize != 1 && Tok && !isLexingRawMode())
if (Ptr[0] != '\n' && Ptr[0] != '\r' && Tok && !isLexingRawMode())
Diag(Ptr, diag::backslash_newline_space);
// Found backslash<whitespace><newline>. Parse the char after it.

View File

@ -273,7 +273,7 @@ AttributeList* Parser::ParseMicrosoftTypeAttributes(AttributeList *CurrAttr) {
/// [C++] template-declaration
/// [C++] namespace-definition
/// [C++] using-directive
/// [C++] using-declaration [TODO]
/// [C++] using-declaration
/// [C++0x] static_assert-declaration
/// others... [FIXME]
///

View File

@ -279,7 +279,8 @@ Parser::OwningExprResult Parser::ParseConstantExpression() {
// C++ [basic.def.odr]p2:
// An expression is potentially evaluated unless it appears where an
// integral constant expression is required (see 5.19) [...].
EnterUnevaluatedOperand Unevaluated(Actions);
EnterExpressionEvaluationContext Unevaluated(Actions,
Action::Unevaluated);
OwningExprResult LHS(ParseCastExpression(false));
if (LHS.isInvalid()) return move(LHS);
@ -983,7 +984,8 @@ Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
//
// The GNU typeof and alignof extensions also behave as unevaluated
// operands.
EnterUnevaluatedOperand Unevaluated(Actions);
EnterExpressionEvaluationContext Unevaluated(Actions,
Action::Unevaluated);
Operand = ParseCastExpression(true/*isUnaryExpression*/);
} else {
// If it starts with a '(', we know that it is either a parenthesized
@ -999,7 +1001,8 @@ Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
//
// The GNU typeof and alignof extensions also behave as unevaluated
// operands.
EnterUnevaluatedOperand Unevaluated(Actions);
EnterExpressionEvaluationContext Unevaluated(Actions,
Action::Unevaluated);
Operand = ParseParenExpression(ExprType, true/*stopIfCastExpr*/,
CastTy, RParenLoc);
CastRange = SourceRange(LParenLoc, RParenLoc);

View File

@ -384,10 +384,9 @@ Parser::OwningExprResult Parser::ParseCXXTypeid() {
//
// Note that we can't tell whether the expression is an lvalue of a
// polymorphic class type until after we've parsed the expression, so
// we treat the expression as an unevaluated operand and let semantic
// analysis cope with case where the expression is not an unevaluated
// operand.
EnterUnevaluatedOperand Unevaluated(Actions);
// we the expression is potentially potentially evaluated.
EnterExpressionEvaluationContext Unevaluated(Actions,
Action::PotentiallyPotentiallyEvaluated);
Result = ParseExpression();
// Match the ')'.

View File

@ -750,7 +750,7 @@ void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
/// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]).
///
/// template-argument: [C++ 14.2]
/// assignment-expression
/// constant-expression
/// type-id
/// id-expression
void *Parser::ParseTemplateArgument(bool &ArgIsType) {
@ -768,7 +768,7 @@ void *Parser::ParseTemplateArgument(bool &ArgIsType) {
return TypeArg.get();
}
OwningExprResult ExprArg = ParseAssignmentExpression();
OwningExprResult ExprArg = ParseConstantExpression();
if (ExprArg.isInvalid() || !ExprArg.get())
return 0;

View File

@ -182,7 +182,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
ExternalSource(0), CurContext(0), PreDeclaratorDC(0),
CurBlock(0), PackContext(0), IdResolver(pp.getLangOptions()),
GlobalNewDeleteDeclared(false), InUnevaluatedOperand(false),
GlobalNewDeleteDeclared(false), ExprEvalContext(PotentiallyEvaluated),
CompleteTranslationUnit(CompleteTranslationUnit),
NumSFINAEErrors(0), CurrentInstantiationScope(0) {
@ -235,6 +235,18 @@ void Sema::DeleteStmt(StmtTy *S) {
/// translation unit when EOF is reached and all but the top-level scope is
/// popped.
void Sema::ActOnEndOfTranslationUnit() {
// C++: Perform implicit template instantiations.
//
// FIXME: When we perform these implicit instantiations, we do not carefully
// keep track of the point of instantiation (C++ [temp.point]). This means
// that name lookup that occurs within the template instantiation will
// always happen at the end of the translation unit, so it will find
// some names that should not be found. Although this is common behavior
// for C++ compilers, it is technically wrong. In the future, we either need
// to be able to filter the results of name lookup or we need to perform
// template instantiations earlier.
PerformPendingImplicitInstantiations();
if (!CompleteTranslationUnit)
return;

View File

@ -29,7 +29,9 @@
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/OwningPtr.h"
#include <list>
#include <string>
#include <queue>
#include <vector>
namespace llvm {
@ -247,11 +249,18 @@ class Sema : public Action {
/// have been declared.
bool GlobalNewDeleteDeclared;
/// A flag that indicates when we are processing an unevaluated operand
/// (C++0x [expr]). C99 has the same notion of declarations being
/// "used" and C++03 has the notion of "potentially evaluated", but we
/// adopt the C++0x terminology since it is most precise.
bool InUnevaluatedOperand;
/// The current expression evaluation context.
ExpressionEvaluationContext ExprEvalContext;
typedef std::vector<std::pair<SourceLocation, Decl *> >
PotentiallyReferencedDecls;
/// A stack of declarations, each element of which is a set of declarations
/// that will be marked as referenced if the corresponding potentially
/// potentially evaluated expression is potentially evaluated. Each element
/// in the stack corresponds to a PotentiallyPotentiallyEvaluated expression
/// evaluation context.
std::list<PotentiallyReferencedDecls> PotentiallyReferencedDeclStack;
/// \brief Whether the code handled by Sema should be considered a
/// complete translation unit or not.
@ -1334,12 +1343,13 @@ class Sema : public Action {
void DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
Expr **Args, unsigned NumArgs);
virtual bool setUnevaluatedOperand(bool UnevaluatedOperand) {
bool Result = InUnevaluatedOperand;
InUnevaluatedOperand = UnevaluatedOperand;
return Result;
}
virtual ExpressionEvaluationContext
PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext);
virtual void
PopExpressionEvaluationContext(ExpressionEvaluationContext OldContext,
ExpressionEvaluationContext NewContext);
void MarkDeclarationReferenced(SourceLocation Loc, Decl *D);
// Primary Expressions.
@ -1572,10 +1582,16 @@ class Sema : public Action {
QualType DeclInitType,
Expr **Exprs, unsigned NumExprs);
/// DefineImplicitDefaultConstructor - Checks for feasibilityt of
/// DefineImplicitDefaultConstructor - Checks for feasibility of
/// defining this constructor as the default constructor.
void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
CXXConstructorDecl *Constructor);
/// DefineImplicitCopyConstructor - Checks for feasibility of
/// defining this constructor as the copy constructor.
void DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
CXXConstructorDecl *Constructor,
unsigned TypeQuals);
/// MaybeBindToTemporary - If the passed in expression has a record type with
/// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise
@ -2495,6 +2511,22 @@ class Sema : public Action {
/// variables.
LocalInstantiationScope *CurrentInstantiationScope;
/// \brief An entity for which implicit template instantiation is required.
///
/// The source location associated with the declaration is the first place in
/// the source code where the declaration was "used". It is not necessarily
/// the point of instantiation (which will be either before or after the
/// namespace-scope declaration that triggered this implicit instantiation),
/// However, it is the location that diagnostics should generally refer to,
/// because users will need to know what code triggered the instantiation.
typedef std::pair<ValueDecl *, SourceLocation> PendingImplicitInstantiation;
/// \brief The queue of implicit template instantiations that are required
/// but have not yet been performed.
std::queue<PendingImplicitInstantiation> PendingImplicitInstantiations;
void PerformPendingImplicitInstantiations();
QualType InstantiateType(QualType T, const TemplateArgumentList &TemplateArgs,
SourceLocation Loc, DeclarationName Entity);
@ -2550,7 +2582,7 @@ class Sema : public Action {
void InstantiateVariableDefinition(VarDecl *Var);
NamedDecl *InstantiateCurrentDeclRef(NamedDecl *D);
// Simple function for cloning expressions.
template<typename T>
OwningExprResult Clone(T *E) {

View File

@ -2733,12 +2733,9 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl) {
IK_Default);
if (!Constructor)
Var->setInvalidDecl();
else {
else
if (!RD->hasTrivialConstructor())
InitializeVarWithConstructor(Var, Constructor, InitType, 0, 0);
// Check for valid construction.
DefineImplicitDefaultConstructor(Var->getLocation(), Constructor);
}
}
}

View File

@ -107,6 +107,9 @@ namespace {
void
Sema::ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc,
ExprArg defarg) {
if (!param || !defarg.get())
return;
ParmVarDecl *Param = cast<ParmVarDecl>(param.getAs<Decl>());
UnparsedDefaultArgLocs.erase(Param);
@ -161,6 +164,9 @@ Sema::ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc,
void Sema::ActOnParamUnparsedDefaultArgument(DeclPtrTy param,
SourceLocation EqualLoc,
SourceLocation ArgLoc) {
if (!param)
return;
ParmVarDecl *Param = cast<ParmVarDecl>(param.getAs<Decl>());
if (Param)
Param->setUnparsedDefaultArg();
@ -171,6 +177,9 @@ void Sema::ActOnParamUnparsedDefaultArgument(DeclPtrTy param,
/// ActOnParamDefaultArgumentError - Parsing or semantic analysis of
/// the default argument for the parameter param failed.
void Sema::ActOnParamDefaultArgumentError(DeclPtrTy param) {
if (!param)
return;
ParmVarDecl *Param = cast<ParmVarDecl>(param.getAs<Decl>());
Param->setInvalidDecl();
@ -415,6 +424,9 @@ Sema::BaseResult
Sema::ActOnBaseSpecifier(DeclPtrTy classdecl, SourceRange SpecifierRange,
bool Virtual, AccessSpecifier Access,
TypeTy *basetype, SourceLocation BaseLoc) {
if (!classdecl)
return true;
AdjustDeclIfTemplate(classdecl);
CXXRecordDecl *Class = cast<CXXRecordDecl>(classdecl.getAs<Decl>());
QualType BaseType = QualType::getFromOpaquePtr(basetype);
@ -640,6 +652,9 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
ExprTy **Args, unsigned NumArgs,
SourceLocation *CommaLocs,
SourceLocation RParenLoc) {
if (!ConstructorD)
return true;
CXXConstructorDecl *Constructor
= dyn_cast<CXXConstructorDecl>(ConstructorD.getAs<Decl>());
if (!Constructor) {
@ -741,8 +756,11 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
SourceLocation ColonLoc,
MemInitTy **MemInits, unsigned NumMemInits) {
CXXConstructorDecl *Constructor =
dyn_cast<CXXConstructorDecl>(ConstructorDecl.getAs<Decl>());
if (!ConstructorDecl)
return;
CXXConstructorDecl *Constructor
= dyn_cast<CXXConstructorDecl>(ConstructorDecl.getAs<Decl>());
if (!Constructor) {
Diag(ColonLoc, diag::err_only_constructors_take_base_inits);
@ -957,6 +975,9 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
DeclPtrTy TagDecl,
SourceLocation LBrac,
SourceLocation RBrac) {
if (!TagDecl)
return;
AdjustDeclIfTemplate(TagDecl);
ActOnFields(S, RLoc, TagDecl,
(DeclPtrTy*)FieldCollector->getCurFields(),
@ -1238,6 +1259,9 @@ void Sema::ActOnReenterTemplateScope(Scope *S, DeclPtrTy TemplateD) {
/// name. However, it should not bring the parameters into scope;
/// that will be performed by ActOnDelayedCXXMethodParameter.
void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) {
if (!MethodD)
return;
CXXScopeSpec SS;
FunctionDecl *Method = cast<FunctionDecl>(MethodD.getAs<Decl>());
QualType ClassTy
@ -1253,6 +1277,9 @@ void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) {
/// the method declaration. For example, we could see an
/// ActOnParamDefaultArgument event for this parameter.
void Sema::ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy ParamD) {
if (!ParamD)
return;
ParmVarDecl *Param = cast<ParmVarDecl>(ParamD.getAs<Decl>());
// If this parameter has an unparsed default argument, clear it out
@ -1272,6 +1299,9 @@ void Sema::ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy ParamD) {
/// immediately!) for this method, if it was also defined inside the
/// class body.
void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) {
if (!MethodD)
return;
FunctionDecl *Method = cast<FunctionDecl>(MethodD.getAs<Decl>());
CXXScopeSpec SS;
QualType ClassTy
@ -1842,13 +1872,13 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S,
void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
CXXConstructorDecl *Constructor) {
if (!Constructor->isDefaultConstructor() ||
!Constructor->isImplicit() || Constructor->isImplicitMustBeDefined())
return;
assert((Constructor->isImplicit() && Constructor->isDefaultConstructor() &&
!Constructor->isUsed()) &&
"DefineImplicitDefaultConstructor - call it for implicit default ctor");
CXXRecordDecl *ClassDecl
= cast<CXXRecordDecl>(Constructor->getDeclContext());
assert(ClassDecl && "InitializeVarWithConstructor - invalid constructor");
assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor");
// Before the implicitly-declared default constructor for a class is
// implicitly defined, all the implicitly-declared default constructors
// for its base class and its non-static data members shall have been
@ -1861,8 +1891,8 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
if (!BaseClassDecl->hasTrivialConstructor()) {
if (CXXConstructorDecl *BaseCtor =
BaseClassDecl->getDefaultConstructor(Context)) {
if (BaseCtor->isImplicit())
BaseCtor->setImplicitMustBeDefined();
if (BaseCtor->isImplicit() && !BaseCtor->isUsed())
MarkDeclarationReferenced(CurrentLocation, BaseCtor);
}
else {
Diag(CurrentLocation, diag::err_defining_default_ctor)
@ -1886,8 +1916,8 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
if (!FieldClassDecl->hasTrivialConstructor())
if (CXXConstructorDecl *FieldCtor =
FieldClassDecl->getDefaultConstructor(Context)) {
if (FieldCtor->isImplicit())
FieldCtor->setImplicitMustBeDefined();
if (FieldCtor->isImplicit() && !FieldCtor->isUsed())
MarkDeclarationReferenced(CurrentLocation, FieldCtor);
}
else {
Diag(CurrentLocation, diag::err_defining_default_ctor)
@ -1912,7 +1942,49 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
}
}
if (!err)
Constructor->setImplicitMustBeDefined();
Constructor->setUsed();
}
void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
CXXConstructorDecl *CopyConstructor,
unsigned TypeQuals) {
assert((CopyConstructor->isImplicit() &&
CopyConstructor->isCopyConstructor(Context, TypeQuals) &&
!CopyConstructor->isUsed()) &&
"DefineImplicitCopyConstructor - call it for implicit copy ctor");
CXXRecordDecl *ClassDecl
= cast<CXXRecordDecl>(CopyConstructor->getDeclContext());
assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor");
// Before the implicitly-declared copy constructor for a class is
// implicitly defined, all the implicitly-declared copy constructors
// for its base class and its non-static data members shall have been
// implicitly defined.
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
Base != ClassDecl->bases_end(); ++Base) {
CXXRecordDecl *BaseClassDecl
= cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl());
if (CXXConstructorDecl *BaseCopyCtor =
BaseClassDecl->getCopyConstructor(Context, TypeQuals))
if (BaseCopyCtor->isImplicit() && !BaseCopyCtor->isUsed())
MarkDeclarationReferenced(CurrentLocation, BaseCopyCtor);
}
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(Context);
Field != ClassDecl->field_end(Context);
++Field) {
QualType FieldType = Context.getCanonicalType((*Field)->getType());
if (const ArrayType *Array = Context.getAsArrayType(FieldType))
FieldType = Array->getElementType();
if (const RecordType *FieldClassType = FieldType->getAsRecordType()) {
CXXRecordDecl *FieldClassDecl
= cast<CXXRecordDecl>(FieldClassType->getDecl());
if (CXXConstructorDecl *FieldCopyCtor =
FieldClassDecl->getCopyConstructor(Context, TypeQuals))
if (FieldCopyCtor->isImplicit() && !FieldCopyCtor->isUsed())
MarkDeclarationReferenced(CurrentLocation, FieldCopyCtor);
}
}
CopyConstructor->setUsed();
}
void Sema::InitializeVarWithConstructor(VarDecl *VD,
@ -1921,6 +1993,7 @@ void Sema::InitializeVarWithConstructor(VarDecl *VD,
Expr **Exprs, unsigned NumExprs) {
Expr *Temp = CXXConstructExpr::Create(Context, DeclInitType, Constructor,
false, Exprs, NumExprs);
MarkDeclarationReferenced(VD->getLocation(), Constructor);
VD->setInit(Context, Temp);
}
@ -1990,9 +2063,6 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
VDecl->setCXXDirectInitializer(true);
InitializeVarWithConstructor(VDecl, Constructor, DeclInitType,
(Expr**)Exprs.release(), NumExprs);
// An implicitly-declared default constructor for a class is implicitly
// defined when it is used to creat an object of its class type.
DefineImplicitDefaultConstructor(VDecl->getLocation(), Constructor);
}
return;
}

View File

@ -2134,25 +2134,32 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
MemberType = MemberType.getQualifiedType(combinedQualifiers);
}
MarkDeclarationReferenced(MemberLoc, FD);
return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow, FD,
MemberLoc, MemberType));
}
if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl))
if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
MarkDeclarationReferenced(MemberLoc, MemberDecl);
return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow,
Var, MemberLoc,
Var->getType().getNonReferenceType()));
if (FunctionDecl *MemberFn = dyn_cast<FunctionDecl>(MemberDecl))
}
if (FunctionDecl *MemberFn = dyn_cast<FunctionDecl>(MemberDecl)) {
MarkDeclarationReferenced(MemberLoc, MemberDecl);
return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow,
MemberFn, MemberLoc,
MemberFn->getType()));
}
if (OverloadedFunctionDecl *Ovl
= dyn_cast<OverloadedFunctionDecl>(MemberDecl))
return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow, Ovl,
MemberLoc, Context.OverloadTy));
if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl))
if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
MarkDeclarationReferenced(MemberLoc, MemberDecl);
return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow,
Enum, MemberLoc, Enum->getType()));
}
if (isa<TypeDecl>(MemberDecl))
return ExprError(Diag(MemberLoc,diag::err_typecheck_member_reference_type)
<< DeclarationName(&Member) << int(OpKind == tok::arrow));
@ -5432,6 +5439,35 @@ bool Sema::VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result){
return false;
}
Sema::ExpressionEvaluationContext
Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) {
// Introduce a new set of potentially referenced declarations to the stack.
if (NewContext == PotentiallyPotentiallyEvaluated)
PotentiallyReferencedDeclStack.push_back(PotentiallyReferencedDecls());
std::swap(ExprEvalContext, NewContext);
return NewContext;
}
void
Sema::PopExpressionEvaluationContext(ExpressionEvaluationContext OldContext,
ExpressionEvaluationContext NewContext) {
ExprEvalContext = NewContext;
if (OldContext == PotentiallyPotentiallyEvaluated) {
// Mark any remaining declarations in the current position of the stack
// as "referenced". If they were not meant to be referenced, semantic
// analysis would have eliminated them (e.g., in ActOnCXXTypeId).
PotentiallyReferencedDecls RemainingDecls;
RemainingDecls.swap(PotentiallyReferencedDeclStack.back());
PotentiallyReferencedDeclStack.pop_back();
for (PotentiallyReferencedDecls::iterator I = RemainingDecls.begin(),
IEnd = RemainingDecls.end();
I != IEnd; ++I)
MarkDeclarationReferenced(I->first, I->second);
}
}
/// \brief Note that the given declaration was referenced in the source code.
///
@ -5446,6 +5482,9 @@ bool Sema::VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result){
void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
assert(D && "No declaration?");
if (D->isUsed())
return;
// Mark a parameter declaration "used", regardless of whether we're in a
// template or not.
if (isa<ParmVarDecl>(D))
@ -5456,18 +5495,55 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
if (CurContext->isDependentContext())
return;
// If we are in an unevaluated operand, don't mark any definitions as used.
if (InUnevaluatedOperand)
return;
switch (ExprEvalContext) {
case Unevaluated:
// We are in an expression that is not potentially evaluated; do nothing.
return;
case PotentiallyEvaluated:
// We are in a potentially-evaluated expression, so this declaration is
// "used"; handle this below.
break;
case PotentiallyPotentiallyEvaluated:
// We are in an expression that may be potentially evaluated; queue this
// declaration reference until we know whether the expression is
// potentially evaluated.
PotentiallyReferencedDeclStack.back().push_back(std::make_pair(Loc, D));
return;
}
// Note that this declaration has been used.
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
unsigned TypeQuals;
if (Constructor->isImplicit() && Constructor->isDefaultConstructor()) {
if (!Constructor->isUsed())
DefineImplicitDefaultConstructor(Loc, Constructor);
}
else if (Constructor->isImplicit() &&
Constructor->isCopyConstructor(Context, TypeQuals)) {
if (!Constructor->isUsed())
DefineImplicitCopyConstructor(Loc, Constructor, TypeQuals);
}
// FIXME: more checking for other implicits go here.
else
Constructor->setUsed(true);
}
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
// FIXME: implicit template instantiation
// Implicit instantiation of function templates
if (!Function->getBody(Context)) {
if (Function->getInstantiatedFromMemberFunction())
PendingImplicitInstantiations.push(std::make_pair(Function, Loc));
// FIXME: check for function template specializations.
}
// FIXME: keep track of references to static functions
(void)Function;
Function->setUsed(true);
return;
}
}
if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
(void)Var;

View File

@ -71,6 +71,31 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
QualType TypeInfoType = Context.getTypeDeclType(TypeInfoRecordDecl);
if (!isType) {
// C++0x [expr.typeid]p3:
// When typeid is applied to an expression other than an lvalue of a
// polymorphic class type [...] [the] expression is an unevaluated
// operand.
// FIXME: if the type of the expression is a class type, the class
// shall be completely defined.
bool isUnevaluatedOperand = true;
Expr *E = static_cast<Expr *>(TyOrExpr);
if (E && !E->isTypeDependent() && E->isLvalue(Context) == Expr::LV_Valid) {
QualType T = E->getType();
if (const RecordType *RecordT = T->getAsRecordType()) {
CXXRecordDecl *RecordD = cast<CXXRecordDecl>(RecordT->getDecl());
if (RecordD->isPolymorphic())
isUnevaluatedOperand = false;
}
}
// If this is an unevaluated operand, clear out the set of declaration
// references we have been computing.
if (isUnevaluatedOperand)
PotentiallyReferencedDeclStack.back().clear();
}
return Owned(new (Context) CXXTypeidExpr(isType, TyOrExpr,
TypeInfoType.withConst(),
SourceRange(OpLoc, RParenLoc)));

View File

@ -847,13 +847,14 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
// Check that the template argument list is well-formed for this
// template.
TemplateArgumentListBuilder ConvertedTemplateArgs(Context);
TemplateArgumentListBuilder Converted(Template->getTemplateParameters(),
NumTemplateArgs);
if (CheckTemplateArgumentList(Template, TemplateLoc, LAngleLoc,
TemplateArgs, NumTemplateArgs, RAngleLoc,
ConvertedTemplateArgs))
Converted))
return QualType();
assert((ConvertedTemplateArgs.structuredSize() ==
assert((Converted.structuredSize() ==
Template->getTemplateParameters()->size()) &&
"Converted template argument list is too short!");
@ -871,16 +872,16 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
// template<typename T, typename U = T> struct A;
TemplateName CanonName = Context.getCanonicalTemplateName(Name);
CanonType = Context.getTemplateSpecializationType(CanonName,
ConvertedTemplateArgs.getFlatArgumentList(),
ConvertedTemplateArgs.flatSize());
Converted.getFlatArguments(),
Converted.flatSize());
} else if (ClassTemplateDecl *ClassTemplate
= dyn_cast<ClassTemplateDecl>(Template)) {
// Find the class template specialization declaration that
// corresponds to these arguments.
llvm::FoldingSetNodeID ID;
ClassTemplateSpecializationDecl::Profile(ID,
ConvertedTemplateArgs.getFlatArgumentList(),
ConvertedTemplateArgs.flatSize());
Converted.getFlatArguments(),
Converted.flatSize());
void *InsertPos = 0;
ClassTemplateSpecializationDecl *Decl
= ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
@ -892,7 +893,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
ClassTemplate->getDeclContext(),
TemplateLoc,
ClassTemplate,
ConvertedTemplateArgs, 0);
Converted, 0);
ClassTemplate->getSpecializations().InsertNode(Decl, InsertPos);
Decl->setLexicalDeclContext(CurContext);
}
@ -1003,7 +1004,7 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
return true;
// Add the converted template type argument.
Converted.push_back(
Converted.Append(
TemplateArgument(Arg.getLocation(),
Context.getCanonicalType(Arg.getAsType())));
return false;
@ -1061,9 +1062,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// parameter.
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
if (TTP->isParameterPack()) {
// We have an empty parameter pack.
Converted.BeginParameterPack();
Converted.EndParameterPack();
// We have an empty argument pack.
Converted.BeginPack();
Converted.EndPack();
break;
}
@ -1076,13 +1077,12 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// on the previously-computed template arguments.
if (ArgType->isDependentType()) {
InstantiatingTemplate Inst(*this, TemplateLoc,
Template, Converted.getFlatArgumentList(),
Template, Converted.getFlatArguments(),
Converted.flatSize(),
SourceRange(TemplateLoc, RAngleLoc));
TemplateArgumentList TemplateArgs(Context, Converted,
/*CopyArgs=*/false,
/*FlattenArgs=*/false);
/*TakeArgs=*/false);
ArgType = InstantiateType(ArgType, TemplateArgs,
TTP->getDefaultArgumentLoc(),
TTP->getDeclName());
@ -1098,13 +1098,12 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
break;
InstantiatingTemplate Inst(*this, TemplateLoc,
Template, Converted.getFlatArgumentList(),
Template, Converted.getFlatArguments(),
Converted.flatSize(),
SourceRange(TemplateLoc, RAngleLoc));
TemplateArgumentList TemplateArgs(Context, Converted,
/*CopyArgs=*/false,
/*FlattenArgs=*/false);
/*TakeArgs=*/false);
Sema::OwningExprResult E = InstantiateExpr(NTTP->getDefaultArgument(),
TemplateArgs);
@ -1130,14 +1129,14 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
if (TTP->isParameterPack()) {
Converted.BeginParameterPack();
Converted.BeginPack();
// Check all the remaining arguments (if any).
for (; ArgIdx < NumArgs; ++ArgIdx) {
if (CheckTemplateTypeArgument(TTP, TemplateArgs[ArgIdx], Converted))
Invalid = true;
}
Converted.EndParameterPack();
Converted.EndPack();
} else {
if (CheckTemplateTypeArgument(TTP, Arg, Converted))
Invalid = true;
@ -1152,13 +1151,12 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
if (NTTPType->isDependentType()) {
// Instantiate the type of the non-type template parameter.
InstantiatingTemplate Inst(*this, TemplateLoc,
Template, Converted.getFlatArgumentList(),
Template, Converted.getFlatArguments(),
Converted.flatSize(),
SourceRange(TemplateLoc, RAngleLoc));
TemplateArgumentList TemplateArgs(Context, Converted,
/*CopyArgs=*/false,
/*FlattenArgs=*/false);
/*TakeArgs=*/false);
NTTPType = InstantiateType(NTTPType, TemplateArgs,
NTTP->getLocation(),
NTTP->getDeclName());
@ -1167,7 +1165,6 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
if (!NTTPType.isNull())
NTTPType = CheckNonTypeTemplateParameterType(NTTPType,
NTTP->getLocation());
if (NTTPType.isNull()) {
Invalid = true;
break;
@ -1185,7 +1182,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
if (CheckTemplateArgument(NTTP, NTTPType, E, Result))
Invalid = true;
else
Converted.push_back(Result);
Converted.Append(Result);
break;
}
@ -1193,7 +1190,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
case TemplateArgument::Integral:
// We've already checked this template argument, so just copy
// it to the list of converted arguments.
Converted.push_back(Arg);
Converted.Append(Arg);
break;
case TemplateArgument::Type:
@ -1240,7 +1237,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// Add the converted template argument.
Decl *D
= Context.getCanonicalDecl(cast<DeclRefExpr>(ArgExpr)->getDecl());
Converted.push_back(TemplateArgument(Arg.getLocation(), D));
Converted.Append(TemplateArgument(Arg.getLocation(), D));
continue;
}
}
@ -1257,7 +1254,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
case TemplateArgument::Declaration:
// We've already checked this template argument, so just copy
// it to the list of converted arguments.
Converted.push_back(Arg);
Converted.Append(Arg);
break;
case TemplateArgument::Integral:
@ -2102,7 +2099,7 @@ bool Sema::CheckClassTemplatePartialSpecializationArgs(
// accommodate variadic templates.
MirrorsPrimaryTemplate = true;
const TemplateArgument *ArgList = TemplateArgs.getFlatArgumentList();
const TemplateArgument *ArgList = TemplateArgs.getFlatArguments();
for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
// Determine whether the template argument list of the partial
@ -2298,13 +2295,14 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
// Check that the template argument list is well-formed for this
// template.
TemplateArgumentListBuilder ConvertedTemplateArgs(Context);
TemplateArgumentListBuilder Converted(ClassTemplate->getTemplateParameters(),
TemplateArgs.size());
if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, LAngleLoc,
TemplateArgs.data(), TemplateArgs.size(),
RAngleLoc, ConvertedTemplateArgs))
RAngleLoc, Converted))
return true;
assert((ConvertedTemplateArgs.structuredSize() ==
assert((Converted.structuredSize() ==
ClassTemplate->getTemplateParameters()->size()) &&
"Converted template argument list is too short!");
@ -2315,8 +2313,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
bool MirrorsPrimaryTemplate;
if (CheckClassTemplatePartialSpecializationArgs(
ClassTemplate->getTemplateParameters(),
ConvertedTemplateArgs,
MirrorsPrimaryTemplate))
Converted, MirrorsPrimaryTemplate))
return true;
if (MirrorsPrimaryTemplate) {
@ -2338,13 +2335,13 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
// FIXME: Template parameter list matters, too
ClassTemplatePartialSpecializationDecl::Profile(ID,
ConvertedTemplateArgs.getFlatArgumentList(),
ConvertedTemplateArgs.flatSize());
Converted.getFlatArguments(),
Converted.flatSize());
}
else
ClassTemplateSpecializationDecl::Profile(ID,
ConvertedTemplateArgs.getFlatArgumentList(),
ConvertedTemplateArgs.flatSize());
Converted.getFlatArguments(),
Converted.flatSize());
void *InsertPos = 0;
ClassTemplateSpecializationDecl *PrevDecl = 0;
@ -2387,7 +2384,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
TemplateNameLoc,
TemplateParams,
ClassTemplate,
ConvertedTemplateArgs,
Converted,
PrevPartial);
if (PrevPartial) {
@ -2437,7 +2434,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
ClassTemplate->getDeclContext(),
TemplateNameLoc,
ClassTemplate,
ConvertedTemplateArgs,
Converted,
PrevDecl);
if (PrevDecl) {
@ -2559,13 +2556,14 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
// Check that the template argument list is well-formed for this
// template.
TemplateArgumentListBuilder ConvertedTemplateArgs(Context);
TemplateArgumentListBuilder Converted(ClassTemplate->getTemplateParameters(),
TemplateArgs.size());
if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, LAngleLoc,
TemplateArgs.data(), TemplateArgs.size(),
RAngleLoc, ConvertedTemplateArgs))
RAngleLoc, Converted))
return true;
assert((ConvertedTemplateArgs.structuredSize() ==
assert((Converted.structuredSize() ==
ClassTemplate->getTemplateParameters()->size()) &&
"Converted template argument list is too short!");
@ -2573,8 +2571,8 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
// corresponds to these arguments.
llvm::FoldingSetNodeID ID;
ClassTemplateSpecializationDecl::Profile(ID,
ConvertedTemplateArgs.getFlatArgumentList(),
ConvertedTemplateArgs.flatSize());
Converted.getFlatArguments(),
Converted.flatSize());
void *InsertPos = 0;
ClassTemplateSpecializationDecl *PrevDecl
= ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
@ -2617,7 +2615,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
ClassTemplate->getDeclContext(),
TemplateNameLoc,
ClassTemplate,
ConvertedTemplateArgs, 0);
Converted, 0);
Specialization->setLexicalDeclContext(CurContext);
CurContext->addDecl(Context, Specialization);
return DeclPtrTy::make(Specialization);
@ -2643,7 +2641,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
ClassTemplate->getDeclContext(),
TemplateNameLoc,
ClassTemplate,
ConvertedTemplateArgs, 0);
Converted, 0);
ClassTemplate->getSpecializations().InsertNode(Specialization,
InsertPos);

View File

@ -654,7 +654,8 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
// C++ [temp.deduct.type]p2:
// [...] or if any template argument remains neither deduced nor
// explicitly specified, template argument deduction fails.
TemplateArgumentListBuilder Builder(Context);
TemplateArgumentListBuilder Builder(Partial->getTemplateParameters(),
Deduced.size());
for (unsigned I = 0, N = Deduced.size(); I != N; ++I) {
if (Deduced[I].isNull()) {
Decl *Param
@ -669,13 +670,12 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
return TDK_Incomplete;
}
Builder.push_back(Deduced[I]);
Builder.Append(Deduced[I]);
}
// Form the template argument list from the deduced template arguments.
TemplateArgumentList *DeducedArgumentList
= new (Context) TemplateArgumentList(Context, Builder, /*CopyArgs=*/true,
/*FlattenArgs=*/true);
= new (Context) TemplateArgumentList(Context, Builder, /*TakeArgs=*/true);
Info.reset(DeducedArgumentList);
// Substitute the deduced template arguments into the template

View File

@ -420,6 +420,7 @@ InstantiateDependentSizedArrayType(const DependentSizedArrayType *T,
}
// Instantiate the size expression
EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
Sema::OwningExprResult InstantiatedArraySize =
SemaRef.InstantiateExpr(ArraySize, TemplateArgs);
if (InstantiatedArraySize.isInvalid())
@ -443,6 +444,10 @@ InstantiateDependentSizedExtVectorType(const DependentSizedExtVectorType *T,
return QualType();
}
// The expression in a dependent-sized extended vector type is not
// potentially evaluated.
EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
// Instantiate the size expression.
const Expr *SizeExpr = T->getSizeExpr();
Sema::OwningExprResult InstantiatedArraySize =
@ -520,6 +525,9 @@ TemplateTypeInstantiator::InstantiateTypedefType(const TypedefType *T,
QualType
TemplateTypeInstantiator::InstantiateTypeOfExprType(const TypeOfExprType *T,
unsigned Quals) const {
// The expression in a typeof is not potentially evaluated.
EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
Sema::OwningExprResult E
= SemaRef.InstantiateExpr(T->getUnderlyingExpr(), TemplateArgs);
if (E.isInvalid())
@ -1175,6 +1183,9 @@ TemplateArgument Sema::Instantiate(TemplateArgument Arg,
return Arg;
case TemplateArgument::Expression: {
// Template argument expressions are not potentially evaluated.
EnterExpressionEvaluationContext Unevaluated(*this, Action::Unevaluated);
Sema::OwningExprResult E = InstantiateExpr(Arg.getAsExpr(), TemplateArgs);
if (E.isInvalid())
return TemplateArgument();

View File

@ -163,6 +163,9 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
if (Invalid)
BitWidth = 0;
else if (BitWidth) {
// The bit-width expression is not potentially evaluated.
EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
OwningExprResult InstantiatedBitWidth
= SemaRef.InstantiateExpr(BitWidth, TemplateArgs);
if (InstantiatedBitWidth.isInvalid()) {
@ -192,6 +195,9 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) {
Expr *AssertExpr = D->getAssertExpr();
// The expression in a static assertion is not potentially evaluated.
EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
OwningExprResult InstantiatedAssertExpr
= SemaRef.InstantiateExpr(AssertExpr, TemplateArgs);
if (InstantiatedAssertExpr.isInvalid())
@ -222,8 +228,13 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
EC != ECEnd; ++EC) {
// The specified value for the enumerator.
OwningExprResult Value = SemaRef.Owned((Expr *)0);
if (Expr *UninstValue = EC->getInitExpr())
if (Expr *UninstValue = EC->getInitExpr()) {
// The enumerator's value expression is not potentially evaluated.
EnterExpressionEvaluationContext Unevaluated(SemaRef,
Action::Unevaluated);
Value = SemaRef.InstantiateExpr(UninstValue, TemplateArgs);
}
// Drop the initial value and continue.
bool isInvalid = false;
@ -586,6 +597,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
if (Function->isInvalidDecl())
return;
assert(!Function->getBody(Context) && "Already instantiated!");
// Find the function body that we'll be substituting.
const FunctionDecl *PatternDecl
= Function->getInstantiatedFromMemberFunction();
@ -765,3 +778,18 @@ NamedDecl * Sema::InstantiateCurrentDeclRef(NamedDecl *D) {
return D;
}
/// \brief Performs template instantiation for all implicit template
/// instantiations we have seen until this point.
void Sema::PerformPendingImplicitInstantiations() {
while (!PendingImplicitInstantiations.empty()) {
PendingImplicitInstantiation Inst = PendingImplicitInstantiations.front();
PendingImplicitInstantiations.pop();
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Inst.first))
if (!Function->getBody(Context))
InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function);
// FIXME: instantiation static member variables
}
}

View File

@ -714,9 +714,17 @@ TemplateExprInstantiator::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
E->getSourceRange());
}
Sema::OwningExprResult Arg = Visit(E->getArgumentExpr());
if (Arg.isInvalid())
return SemaRef.ExprError();
Sema::OwningExprResult Arg(SemaRef);
{
// C++0x [expr.sizeof]p1:
// The operand is either an expression, which is an unevaluated operand
// [...]
EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
Arg = Visit(E->getArgumentExpr());
if (Arg.isInvalid())
return SemaRef.ExprError();
}
Sema::OwningExprResult Result
= SemaRef.CreateSizeOfAlignOfExpr((Expr *)Arg.get(), E->getOperatorLoc(),
@ -949,6 +957,12 @@ TemplateExprInstantiator::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
E->getSourceRange().getEnd());
}
// We don't know whether the expression is potentially evaluated until
// after we perform semantic analysis, so the expression is potentially
// potentially evaluated.
EnterExpressionEvaluationContext Unevaluated(SemaRef,
Action::PotentiallyPotentiallyEvaluated);
OwningExprResult Operand = Visit(E->getExprOperand());
if (Operand.isInvalid())
return SemaRef.ExprError();

View File

@ -145,6 +145,9 @@ TemplateStmtInstantiator::VisitSwitchCase(SwitchCase *S) {
}
Sema::OwningStmtResult TemplateStmtInstantiator::VisitCaseStmt(CaseStmt *S) {
// The case value expressions are not potentially evaluated.
EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
// Instantiate left-hand case value.
OwningExprResult LHS = SemaRef.InstantiateExpr(S->getLHS(), TemplateArgs);
if (LHS.isInvalid())

View File

@ -33,3 +33,7 @@ void f1() {}
// RUN: grep 'define .* @f3' %t | not grep -F '...'
struct foo { int X, Y, Z; } f3() {
}
// PR4423 - This shouldn't crash in codegen
void f4() {}
void f5() { f4(42); }

View File

@ -0,0 +1,29 @@
// RUN: clang-cc -emit-llvm %s -o %t &&
template<typename T>
struct X {
void f(T) { }
void f(char) { }
void g(T) { }
void h(T) { }
};
void foo(X<int> &xi, X<float> *xfp, int i, float f) {
// RUN: grep "linkonce_odr.*_ZN1XIiE1fEi" %t | count 1 &&
xi.f(i);
// RUN: grep "linkonce_odr.*_ZN1XIiE1gEi" %t | count 1 &&
xi.g(f);
// RUN: grep "linkonce_odr.*_ZN1XIfE1fEf" %t | count 1 &&
xfp->f(f);
// RUN: grep "linkonce_odr.*_ZN1XIfE1hEf" %t | count 0 &&
// RUN: true
}

View File

@ -11,7 +11,7 @@ struct X2 : X1 { // expected-note {{'struct X2' declared here}} \
struct X3 : public X2 {
};
X3 x3; // expected-error {{cannot define the default constructor for 'struct X3', because member 'struct X2' does not have any implicit default constructor}}
X3 x3; // expected-error {{cannot define the implicit default constructor for 'struct X3', because member 'struct X2' does not have any default constructor}}
struct X4 {
@ -19,7 +19,7 @@ struct X4 {
X2 & rx2; // expected-note {{declared at}}
};
X4 x4; // expected-error {{cannot define the default constructor for 'struct X4', because base class 'struct X2' does not have any implicit default constructor}} \
X4 x4; // expected-error {{cannot define the implicit default constructor for 'struct X4', because base class 'struct X2' does not have any default constructor}} \
// expected-error {{cannot define the implicit default constructor for 'struct X4', because reference member rx2 cannot be default-initialized}}

View File

@ -35,6 +35,12 @@ template<typename> class TemplateTemplateParm; // expected-error{{template param
template<template<typename T, int> class X> class TemplateTemplateParm; // expected-error{{too many template parameters in template template parameter redeclaration}}
template<typename T>
struct test {}; // expected-note{{previous definition}}
template<typename T>
struct test : T {}; // expected-error{{redefinition}}
#if 0
// FIXME: parse template declarations in these scopes, so that we can
// complain about the one at function scope.

View File

@ -89,6 +89,21 @@ class dynarray {
iterator end() { return Last; }
const_iterator end() const { return Last; }
bool operator==(const dynarray &other) const {
if (size() != other.size())
return false;
for (unsigned I = 0, N = size(); I != N; ++I)
if ((*this)[I] != other[I])
return false;
return true;
}
bool operator!=(const dynarray &other) const {
return !(*this == other);
}
public:
T* Start, *Last, *End;
};
@ -100,11 +115,6 @@ struct Point {
float x, y, z;
};
// FIXME: remove these when we have implicit instantiation for member
// functions of class templates.
template class dynarray<int>;
template class dynarray<Point>;
int main() {
dynarray<int> di;
di.push_back(0);
@ -146,5 +156,13 @@ int main() {
I != IEnd; ++I)
assert(*I == I - di4.begin());
assert(di4 == di);
di4[3] = 17;
assert(di4 != di);
dynarray<Point> dp;
dp.push_back(Point());
assert(dp.size() == 1);
return 0;
}

View File

@ -0,0 +1,16 @@
// RUN: clang-cc -fsyntax-only -verify %s
template<typename T, typename U>
struct X {
T f(T x, U y) { return x + y; }
unsigned g(T x, U y) { return sizeof(f(x, y)); }
};
void test(X<int, int> *xii, X<int*, int> *xpi, X<int, int*> *xip) {
(void)xii->f(1, 2);
(void)xpi->f(0, 2);
(void)sizeof(xip->f(2, 0)); // okay: does not instantiate
(void)xip->g(2, 0); // okay: does not instantiate
}