forked from OSchip/llvm-project
In preparation for fixing PR 6884, rework CFGElement to have getAs<> return pointers instead of fresh CFGElements.
- Also, consoldiate getDtorKind() and getKind() into one "kind". - Add empty getDestructorDecl() method to CFGImplicitDtor. llvm-svn: 126738
This commit is contained in:
parent
9720642c68
commit
96a7a59119
|
@ -29,6 +29,7 @@ namespace llvm {
|
|||
}
|
||||
|
||||
namespace clang {
|
||||
class CXXDestructorDecl;
|
||||
class Decl;
|
||||
class Stmt;
|
||||
class Expr;
|
||||
|
@ -47,45 +48,45 @@ class CFGElement {
|
|||
public:
|
||||
enum Kind {
|
||||
// main kind
|
||||
Invalid,
|
||||
Statement,
|
||||
Initializer,
|
||||
ImplicitDtor,
|
||||
// dtor kind
|
||||
AutomaticObjectDtor,
|
||||
BaseDtor,
|
||||
MemberDtor,
|
||||
TemporaryDtor,
|
||||
DTOR_BEGIN = AutomaticObjectDtor
|
||||
DTOR_BEGIN = AutomaticObjectDtor,
|
||||
DTOR_END = TemporaryDtor
|
||||
};
|
||||
|
||||
protected:
|
||||
// The int bits are used to mark the main kind.
|
||||
// The int bits are used to mark the kind.
|
||||
llvm::PointerIntPair<void *, 2> Data1;
|
||||
// The int bits are used to mark the dtor kind.
|
||||
llvm::PointerIntPair<void *, 2> Data2;
|
||||
|
||||
CFGElement(void *Ptr, unsigned Int) : Data1(Ptr, Int) {}
|
||||
CFGElement(void *Ptr1, unsigned Int1, void *Ptr2, unsigned Int2)
|
||||
: Data1(Ptr1, Int1), Data2(Ptr2, Int2) {}
|
||||
CFGElement(Kind kind, const void *Ptr1, const void *Ptr2 = 0)
|
||||
: Data1(const_cast<void*>(Ptr1), ((unsigned) kind) & 0x3),
|
||||
Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) {}
|
||||
|
||||
public:
|
||||
CFGElement() {}
|
||||
|
||||
Kind getKind() const { return static_cast<Kind>(Data1.getInt()); }
|
||||
|
||||
Kind getDtorKind() const {
|
||||
assert(getKind() == ImplicitDtor);
|
||||
return static_cast<Kind>(Data2.getInt() + DTOR_BEGIN);
|
||||
Kind getKind() const {
|
||||
unsigned x = Data2.getInt();
|
||||
x <<= 2;
|
||||
x |= Data1.getInt();
|
||||
return (Kind) x;
|
||||
}
|
||||
|
||||
bool isValid() const { return Data1.getPointer(); }
|
||||
|
||||
bool isValid() const { return getKind() != Invalid; }
|
||||
|
||||
operator bool() const { return isValid(); }
|
||||
|
||||
template<class ElemTy> ElemTy getAs() const {
|
||||
|
||||
template<class ElemTy> const ElemTy *getAs() const {
|
||||
if (llvm::isa<ElemTy>(this))
|
||||
return *static_cast<const ElemTy*>(this);
|
||||
return ElemTy();
|
||||
return static_cast<const ElemTy*>(this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool classof(const CFGElement *E) { return true; }
|
||||
|
@ -93,13 +94,10 @@ public:
|
|||
|
||||
class CFGStmt : public CFGElement {
|
||||
public:
|
||||
CFGStmt() {}
|
||||
CFGStmt(Stmt *S) : CFGElement(S, 0) {}
|
||||
CFGStmt(Stmt *S) : CFGElement(Statement, S) {}
|
||||
|
||||
Stmt *getStmt() const { return static_cast<Stmt *>(Data1.getPointer()); }
|
||||
|
||||
operator Stmt*() const { return getStmt(); }
|
||||
|
||||
static bool classof(const CFGElement *E) {
|
||||
return E->getKind() == Statement;
|
||||
}
|
||||
|
@ -109,14 +107,12 @@ public:
|
|||
/// constructor's initialization list.
|
||||
class CFGInitializer : public CFGElement {
|
||||
public:
|
||||
CFGInitializer() {}
|
||||
CFGInitializer(CXXCtorInitializer* I)
|
||||
: CFGElement(I, Initializer) {}
|
||||
CFGInitializer(CXXCtorInitializer *initializer)
|
||||
: CFGElement(Initializer, initializer) {}
|
||||
|
||||
CXXCtorInitializer* getInitializer() const {
|
||||
return static_cast<CXXCtorInitializer*>(Data1.getPointer());
|
||||
}
|
||||
operator CXXCtorInitializer*() const { return getInitializer(); }
|
||||
|
||||
static bool classof(const CFGElement *E) {
|
||||
return E->getKind() == Initializer;
|
||||
|
@ -127,14 +123,17 @@ public:
|
|||
/// by compiler on various occasions.
|
||||
class CFGImplicitDtor : public CFGElement {
|
||||
protected:
|
||||
CFGImplicitDtor(unsigned K, void* P, void* S)
|
||||
: CFGElement(P, ImplicitDtor, S, K - DTOR_BEGIN) {}
|
||||
CFGImplicitDtor(Kind kind, const void *data1, const void *data2 = 0)
|
||||
: CFGElement(kind, data1, data2) {
|
||||
assert(kind >= DTOR_BEGIN && kind <= DTOR_END);
|
||||
}
|
||||
|
||||
public:
|
||||
CFGImplicitDtor() {}
|
||||
const CXXDestructorDecl *getDestructorDecl() const;
|
||||
|
||||
static bool classof(const CFGElement *E) {
|
||||
return E->getKind() == ImplicitDtor;
|
||||
Kind kind = E->getKind();
|
||||
return kind >= DTOR_BEGIN && kind <= DTOR_END;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -143,22 +142,20 @@ public:
|
|||
/// of leaving its local scope.
|
||||
class CFGAutomaticObjDtor: public CFGImplicitDtor {
|
||||
public:
|
||||
CFGAutomaticObjDtor() {}
|
||||
CFGAutomaticObjDtor(VarDecl* VD, Stmt* S)
|
||||
: CFGImplicitDtor(AutomaticObjectDtor, VD, S) {}
|
||||
CFGAutomaticObjDtor(const VarDecl *var, const Stmt *stmt)
|
||||
: CFGImplicitDtor(AutomaticObjectDtor, var, stmt) {}
|
||||
|
||||
VarDecl* getVarDecl() const {
|
||||
const VarDecl *getVarDecl() const {
|
||||
return static_cast<VarDecl*>(Data1.getPointer());
|
||||
}
|
||||
|
||||
// Get statement end of which triggered the destructor call.
|
||||
Stmt* getTriggerStmt() const {
|
||||
const Stmt *getTriggerStmt() const {
|
||||
return static_cast<Stmt*>(Data2.getPointer());
|
||||
}
|
||||
|
||||
static bool classof(const CFGElement *E) {
|
||||
return E->getKind() == ImplicitDtor &&
|
||||
E->getDtorKind() == AutomaticObjectDtor;
|
||||
static bool classof(const CFGElement *elem) {
|
||||
return elem->getKind() == AutomaticObjectDtor;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -166,16 +163,15 @@ public:
|
|||
/// base object in destructor.
|
||||
class CFGBaseDtor : public CFGImplicitDtor {
|
||||
public:
|
||||
CFGBaseDtor() {}
|
||||
CFGBaseDtor(const CXXBaseSpecifier *BS)
|
||||
: CFGImplicitDtor(BaseDtor, const_cast<CXXBaseSpecifier*>(BS), NULL) {}
|
||||
CFGBaseDtor(const CXXBaseSpecifier *base)
|
||||
: CFGImplicitDtor(BaseDtor, base) {}
|
||||
|
||||
const CXXBaseSpecifier *getBaseSpecifier() const {
|
||||
return static_cast<const CXXBaseSpecifier*>(Data1.getPointer());
|
||||
}
|
||||
|
||||
static bool classof(const CFGElement *E) {
|
||||
return E->getKind() == ImplicitDtor && E->getDtorKind() == BaseDtor;
|
||||
return E->getKind() == BaseDtor;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -183,16 +179,15 @@ public:
|
|||
/// member object in destructor.
|
||||
class CFGMemberDtor : public CFGImplicitDtor {
|
||||
public:
|
||||
CFGMemberDtor() {}
|
||||
CFGMemberDtor(FieldDecl *FD)
|
||||
: CFGImplicitDtor(MemberDtor, FD, NULL) {}
|
||||
CFGMemberDtor(const FieldDecl *field)
|
||||
: CFGImplicitDtor(MemberDtor, field, 0) {}
|
||||
|
||||
FieldDecl *getFieldDecl() const {
|
||||
return static_cast<FieldDecl*>(Data1.getPointer());
|
||||
const FieldDecl *getFieldDecl() const {
|
||||
return static_cast<const FieldDecl*>(Data1.getPointer());
|
||||
}
|
||||
|
||||
static bool classof(const CFGElement *E) {
|
||||
return E->getKind() == ImplicitDtor && E->getDtorKind() == MemberDtor;
|
||||
return E->getKind() == MemberDtor;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -200,16 +195,15 @@ public:
|
|||
/// at the end of full expression for temporary object.
|
||||
class CFGTemporaryDtor : public CFGImplicitDtor {
|
||||
public:
|
||||
CFGTemporaryDtor() {}
|
||||
CFGTemporaryDtor(CXXBindTemporaryExpr *E)
|
||||
: CFGImplicitDtor(TemporaryDtor, E, NULL) {}
|
||||
CFGTemporaryDtor(CXXBindTemporaryExpr *expr)
|
||||
: CFGImplicitDtor(TemporaryDtor, expr, 0) {}
|
||||
|
||||
CXXBindTemporaryExpr *getBindTemporaryExpr() const {
|
||||
return static_cast<CXXBindTemporaryExpr *>(Data1.getPointer());
|
||||
const CXXBindTemporaryExpr *getBindTemporaryExpr() const {
|
||||
return static_cast<const CXXBindTemporaryExpr *>(Data1.getPointer());
|
||||
}
|
||||
|
||||
static bool classof(const CFGElement *E) {
|
||||
return E->getKind() == ImplicitDtor && E->getDtorKind() == TemporaryDtor;
|
||||
return E->getKind() == TemporaryDtor;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -607,8 +601,8 @@ public:
|
|||
for (const_iterator I=begin(), E=end(); I != E; ++I)
|
||||
for (CFGBlock::const_iterator BI=(*I)->begin(), BE=(*I)->end();
|
||||
BI != BE; ++BI) {
|
||||
if (CFGStmt S = BI->getAs<CFGStmt>())
|
||||
O(S);
|
||||
if (const CFGStmt *stmt = BI->getAs<CFGStmt>())
|
||||
O(stmt->getStmt());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -277,8 +277,8 @@ private:
|
|||
|
||||
for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I) {
|
||||
CFGElement El = *I;
|
||||
if (CFGStmt S = El.getAs<CFGStmt>())
|
||||
ProcessStmt(S, recordStmtValues, AnalysisDirTag());
|
||||
if (const CFGStmt *S = El.getAs<CFGStmt>())
|
||||
ProcessStmt(S->getStmt(), recordStmtValues, AnalysisDirTag());
|
||||
}
|
||||
|
||||
TF.VisitTerminator(const_cast<CFGBlock*>(B));
|
||||
|
@ -293,8 +293,8 @@ private:
|
|||
|
||||
for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I) {
|
||||
CFGElement El = *I;
|
||||
if (CFGStmt S = El.getAs<CFGStmt>())
|
||||
ProcessStmt(S, recordStmtValues, AnalysisDirTag());
|
||||
if (const CFGStmt *S = El.getAs<CFGStmt>())
|
||||
ProcessStmt(S->getStmt(), recordStmtValues, AnalysisDirTag());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -219,11 +219,8 @@ public:
|
|||
/// getStmt - Return the current block-level expression associated with
|
||||
/// this builder.
|
||||
const Stmt* getStmt() const {
|
||||
CFGStmt CS = B[Idx].getAs<CFGStmt>();
|
||||
if (CS)
|
||||
return CS.getStmt();
|
||||
else
|
||||
return 0;
|
||||
const CFGStmt *CS = B[Idx].getAs<CFGStmt>();
|
||||
return CS ? CS->getStmt() : 0;
|
||||
}
|
||||
|
||||
/// getBlock - Return the CFGBlock associated with the block-level expression
|
||||
|
|
|
@ -2704,6 +2704,10 @@ CFG* CFG::buildCFG(const Decl *D, Stmt* Statement, ASTContext *C,
|
|||
return Builder.buildCFG(D, Statement, C, BO);
|
||||
}
|
||||
|
||||
const CXXDestructorDecl *CFGImplicitDtor::getDestructorDecl() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CFG: Queries for BlkExprs.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -2740,8 +2744,8 @@ static BlkExprMapTy* PopulateBlkExprMap(CFG& cfg) {
|
|||
|
||||
for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I)
|
||||
for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI)
|
||||
if (CFGStmt S = BI->getAs<CFGStmt>())
|
||||
FindSubExprAssignments(S, SubExprAssignments);
|
||||
if (const CFGStmt *S = BI->getAs<CFGStmt>())
|
||||
FindSubExprAssignments(S->getStmt(), SubExprAssignments);
|
||||
|
||||
for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I) {
|
||||
|
||||
|
@ -2749,10 +2753,10 @@ static BlkExprMapTy* PopulateBlkExprMap(CFG& cfg) {
|
|||
// block-level that are block-level expressions.
|
||||
|
||||
for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI) {
|
||||
CFGStmt CS = BI->getAs<CFGStmt>();
|
||||
if (!CS.isValid())
|
||||
const CFGStmt *CS = BI->getAs<CFGStmt>();
|
||||
if (!CS)
|
||||
continue;
|
||||
if (Expr* Exp = dyn_cast<Expr>(CS.getStmt())) {
|
||||
if (Expr* Exp = dyn_cast<Expr>(CS->getStmt())) {
|
||||
|
||||
if (BinaryOperator* B = dyn_cast<BinaryOperator>(Exp)) {
|
||||
// Assignment expressions that are not nested within another
|
||||
|
@ -2845,8 +2849,8 @@ CFG::~CFG() {
|
|||
namespace {
|
||||
|
||||
class StmtPrinterHelper : public PrinterHelper {
|
||||
typedef llvm::DenseMap<Stmt*,std::pair<unsigned,unsigned> > StmtMapTy;
|
||||
typedef llvm::DenseMap<Decl*,std::pair<unsigned,unsigned> > DeclMapTy;
|
||||
typedef llvm::DenseMap<const Stmt*,std::pair<unsigned,unsigned> > StmtMapTy;
|
||||
typedef llvm::DenseMap<const Decl*,std::pair<unsigned,unsigned> > DeclMapTy;
|
||||
StmtMapTy StmtMap;
|
||||
DeclMapTy DeclMap;
|
||||
signed currentBlock;
|
||||
|
@ -2855,42 +2859,62 @@ class StmtPrinterHelper : public PrinterHelper {
|
|||
public:
|
||||
|
||||
StmtPrinterHelper(const CFG* cfg, const LangOptions &LO)
|
||||
: currentBlock(0), currentStmt(0), LangOpts(LO) {
|
||||
: currentBlock(0), currentStmt(0), LangOpts(LO)
|
||||
{
|
||||
for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) {
|
||||
unsigned j = 1;
|
||||
for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ;
|
||||
BI != BEnd; ++BI, ++j ) {
|
||||
if (CFGStmt SE = BI->getAs<CFGStmt>()) {
|
||||
if (const CFGStmt *SE = BI->getAs<CFGStmt>()) {
|
||||
const Stmt *stmt= SE->getStmt();
|
||||
std::pair<unsigned, unsigned> P((*I)->getBlockID(), j);
|
||||
StmtMap[SE] = P;
|
||||
StmtMap[stmt] = P;
|
||||
|
||||
if (DeclStmt* DS = dyn_cast<DeclStmt>(SE.getStmt())) {
|
||||
DeclMap[DS->getSingleDecl()] = P;
|
||||
|
||||
} else if (IfStmt* IS = dyn_cast<IfStmt>(SE.getStmt())) {
|
||||
if (VarDecl* VD = IS->getConditionVariable())
|
||||
DeclMap[VD] = P;
|
||||
|
||||
} else if (ForStmt* FS = dyn_cast<ForStmt>(SE.getStmt())) {
|
||||
if (VarDecl* VD = FS->getConditionVariable())
|
||||
DeclMap[VD] = P;
|
||||
|
||||
} else if (WhileStmt* WS = dyn_cast<WhileStmt>(SE.getStmt())) {
|
||||
if (VarDecl* VD = WS->getConditionVariable())
|
||||
DeclMap[VD] = P;
|
||||
|
||||
} else if (SwitchStmt* SS = dyn_cast<SwitchStmt>(SE.getStmt())) {
|
||||
if (VarDecl* VD = SS->getConditionVariable())
|
||||
DeclMap[VD] = P;
|
||||
|
||||
} else if (CXXCatchStmt* CS = dyn_cast<CXXCatchStmt>(SE.getStmt())) {
|
||||
if (VarDecl* VD = CS->getExceptionDecl())
|
||||
DeclMap[VD] = P;
|
||||
switch (stmt->getStmtClass()) {
|
||||
case Stmt::DeclStmtClass:
|
||||
DeclMap[cast<DeclStmt>(stmt)->getSingleDecl()] = P;
|
||||
break;
|
||||
case Stmt::IfStmtClass: {
|
||||
const VarDecl *var = cast<IfStmt>(stmt)->getConditionVariable();
|
||||
if (var)
|
||||
DeclMap[var] = P;
|
||||
break;
|
||||
}
|
||||
case Stmt::ForStmtClass: {
|
||||
const VarDecl *var = cast<ForStmt>(stmt)->getConditionVariable();
|
||||
if (var)
|
||||
DeclMap[var] = P;
|
||||
break;
|
||||
}
|
||||
case Stmt::WhileStmtClass: {
|
||||
const VarDecl *var =
|
||||
cast<WhileStmt>(stmt)->getConditionVariable();
|
||||
if (var)
|
||||
DeclMap[var] = P;
|
||||
break;
|
||||
}
|
||||
case Stmt::SwitchStmtClass: {
|
||||
const VarDecl *var =
|
||||
cast<SwitchStmt>(stmt)->getConditionVariable();
|
||||
if (var)
|
||||
DeclMap[var] = P;
|
||||
break;
|
||||
}
|
||||
case Stmt::CXXCatchStmtClass: {
|
||||
const VarDecl *var =
|
||||
cast<CXXCatchStmt>(stmt)->getExceptionDecl();
|
||||
if (var)
|
||||
DeclMap[var] = P;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
virtual ~StmtPrinterHelper() {}
|
||||
|
||||
|
@ -2913,7 +2937,7 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
bool handleDecl(Decl* D, llvm::raw_ostream& OS) {
|
||||
bool handleDecl(const Decl* D, llvm::raw_ostream& OS) {
|
||||
DeclMapTy::iterator I = DeclMap.find(D);
|
||||
|
||||
if (I == DeclMap.end())
|
||||
|
@ -3031,8 +3055,8 @@ public:
|
|||
|
||||
static void print_elem(llvm::raw_ostream &OS, StmtPrinterHelper* Helper,
|
||||
const CFGElement &E) {
|
||||
if (CFGStmt CS = E.getAs<CFGStmt>()) {
|
||||
Stmt *S = CS;
|
||||
if (const CFGStmt *CS = E.getAs<CFGStmt>()) {
|
||||
Stmt *S = CS->getStmt();
|
||||
|
||||
if (Helper) {
|
||||
|
||||
|
@ -3069,8 +3093,8 @@ static void print_elem(llvm::raw_ostream &OS, StmtPrinterHelper* Helper,
|
|||
if (isa<Expr>(S))
|
||||
OS << '\n';
|
||||
|
||||
} else if (CFGInitializer IE = E.getAs<CFGInitializer>()) {
|
||||
CXXCtorInitializer* I = IE;
|
||||
} else if (const CFGInitializer *IE = E.getAs<CFGInitializer>()) {
|
||||
const CXXCtorInitializer *I = IE->getInitializer();
|
||||
if (I->isBaseInitializer())
|
||||
OS << I->getBaseClass()->getAsCXXRecordDecl()->getName();
|
||||
else OS << I->getAnyMember()->getName();
|
||||
|
@ -3084,8 +3108,8 @@ static void print_elem(llvm::raw_ostream &OS, StmtPrinterHelper* Helper,
|
|||
OS << " (Base initializer)\n";
|
||||
else OS << " (Member initializer)\n";
|
||||
|
||||
} else if (CFGAutomaticObjDtor DE = E.getAs<CFGAutomaticObjDtor>()){
|
||||
VarDecl* VD = DE.getVarDecl();
|
||||
} else if (const CFGAutomaticObjDtor *DE = E.getAs<CFGAutomaticObjDtor>()){
|
||||
const VarDecl* VD = DE->getVarDecl();
|
||||
Helper->handleDecl(VD, OS);
|
||||
|
||||
const Type* T = VD->getType().getTypePtr();
|
||||
|
@ -3097,13 +3121,13 @@ static void print_elem(llvm::raw_ostream &OS, StmtPrinterHelper* Helper,
|
|||
OS << ".~" << T->getAsCXXRecordDecl()->getName().str() << "()";
|
||||
OS << " (Implicit destructor)\n";
|
||||
|
||||
} else if (CFGBaseDtor BE = E.getAs<CFGBaseDtor>()) {
|
||||
const CXXBaseSpecifier *BS = BE.getBaseSpecifier();
|
||||
} else if (const CFGBaseDtor *BE = E.getAs<CFGBaseDtor>()) {
|
||||
const CXXBaseSpecifier *BS = BE->getBaseSpecifier();
|
||||
OS << "~" << BS->getType()->getAsCXXRecordDecl()->getName() << "()";
|
||||
OS << " (Base object destructor)\n";
|
||||
|
||||
} else if (CFGMemberDtor ME = E.getAs<CFGMemberDtor>()) {
|
||||
FieldDecl *FD = ME.getFieldDecl();
|
||||
} else if (const CFGMemberDtor *ME = E.getAs<CFGMemberDtor>()) {
|
||||
const FieldDecl *FD = ME->getFieldDecl();
|
||||
|
||||
const Type *T = FD->getType().getTypePtr();
|
||||
if (const Type *ET = T->getArrayElementTypeNoTypeQual())
|
||||
|
@ -3113,8 +3137,8 @@ static void print_elem(llvm::raw_ostream &OS, StmtPrinterHelper* Helper,
|
|||
OS << ".~" << T->getAsCXXRecordDecl()->getName() << "()";
|
||||
OS << " (Member object destructor)\n";
|
||||
|
||||
} else if (CFGTemporaryDtor TE = E.getAs<CFGTemporaryDtor>()) {
|
||||
CXXBindTemporaryExpr *BT = TE.getBindTemporaryExpr();
|
||||
} else if (const CFGTemporaryDtor *TE = E.getAs<CFGTemporaryDtor>()) {
|
||||
const CXXBindTemporaryExpr *BT = TE->getBindTemporaryExpr();
|
||||
OS << "~" << BT->getType()->getAsCXXRecordDecl()->getName() << "()";
|
||||
OS << " (Temporary object destructor)\n";
|
||||
}
|
||||
|
|
|
@ -50,11 +50,11 @@ static void Accumulate(SMap &SM, CFGBlock *B) {
|
|||
// First walk the block-level expressions.
|
||||
for (CFGBlock::iterator I = B->begin(), E = B->end(); I != E; ++I) {
|
||||
const CFGElement &CE = *I;
|
||||
CFGStmt CS = CE.getAs<CFGStmt>();
|
||||
if (!CS.isValid())
|
||||
const CFGStmt *CS = CE.getAs<CFGStmt>();
|
||||
if (!CS)
|
||||
continue;
|
||||
|
||||
CFGBlock *&Entry = SM[CS];
|
||||
CFGBlock *&Entry = SM[CS->getStmt()];
|
||||
// If 'Entry' is already initialized (e.g., a terminator was already),
|
||||
// skip.
|
||||
if (Entry)
|
||||
|
|
|
@ -31,11 +31,11 @@ static SourceLocation GetUnreachableLoc(const CFGBlock &b, SourceRange &R1,
|
|||
R1 = R2 = SourceRange();
|
||||
|
||||
if (sn < b.size()) {
|
||||
CFGStmt CS = b[sn].getAs<CFGStmt>();
|
||||
const CFGStmt *CS = b[sn].getAs<CFGStmt>();
|
||||
if (!CS)
|
||||
return SourceLocation();
|
||||
|
||||
S = CS.getStmt();
|
||||
S = CS->getStmt();
|
||||
} else if (b.getTerminator())
|
||||
S = b.getTerminator();
|
||||
else
|
||||
|
@ -49,7 +49,7 @@ static SourceLocation GetUnreachableLoc(const CFGBlock &b, SourceRange &R1,
|
|||
const BinaryOperator *BO = cast<BinaryOperator>(S);
|
||||
if (BO->getOpcode() == BO_Comma) {
|
||||
if (sn+1 < b.size())
|
||||
return b[sn+1].getAs<CFGStmt>().getStmt()->getLocStart();
|
||||
return b[sn+1].getAs<CFGStmt>()->getStmt()->getLocStart();
|
||||
const CFGBlock *n = &b;
|
||||
while (1) {
|
||||
if (n->getTerminator())
|
||||
|
@ -60,7 +60,7 @@ static SourceLocation GetUnreachableLoc(const CFGBlock &b, SourceRange &R1,
|
|||
if (n->pred_size() != 1)
|
||||
return SourceLocation();
|
||||
if (!n->empty())
|
||||
return n[0][0].getAs<CFGStmt>().getStmt()->getLocStart();
|
||||
return n[0][0].getAs<CFGStmt>()->getStmt()->getLocStart();
|
||||
}
|
||||
}
|
||||
R1 = BO->getLHS()->getSourceRange();
|
||||
|
|
|
@ -146,8 +146,8 @@ static BinaryOperator *getLogicalOperatorInChain(const CFGBlock *block) {
|
|||
if (block->empty())
|
||||
return 0;
|
||||
|
||||
CFGStmt cstmt = block->front().getAs<CFGStmt>();
|
||||
BinaryOperator *b = llvm::dyn_cast_or_null<BinaryOperator>(cstmt.getStmt());
|
||||
const CFGStmt *cstmt = block->front().getAs<CFGStmt>();
|
||||
BinaryOperator *b = llvm::dyn_cast_or_null<BinaryOperator>(cstmt->getStmt());
|
||||
|
||||
if (!b || !b->isLogicalOp())
|
||||
return 0;
|
||||
|
|
|
@ -112,8 +112,8 @@ void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G,
|
|||
// such as llvm_unreachable.
|
||||
if (!CB->empty()) {
|
||||
CFGElement First = CB->front();
|
||||
if (CFGStmt S = First.getAs<CFGStmt>()) {
|
||||
if (const CallExpr *CE = dyn_cast<CallExpr>(S.getStmt())) {
|
||||
if (const CFGStmt *S = First.getAs<CFGStmt>()) {
|
||||
if (const CallExpr *CE = dyn_cast<CallExpr>(S->getStmt())) {
|
||||
if (CE->isBuiltinCall(Ctx) == Builtin::BI__builtin_unreachable)
|
||||
continue;
|
||||
}
|
||||
|
@ -164,8 +164,8 @@ void UnreachableCodeChecker::FindUnreachableEntryPoints(const CFGBlock *CB,
|
|||
// Find the Stmt* in a CFGBlock for reporting a warning
|
||||
const Stmt *UnreachableCodeChecker::getUnreachableStmt(const CFGBlock *CB) {
|
||||
for (CFGBlock::const_iterator I = CB->begin(), E = CB->end(); I != E; ++I) {
|
||||
if (CFGStmt S = I->getAs<CFGStmt>())
|
||||
return S;
|
||||
if (const CFGStmt *S = I->getAs<CFGStmt>())
|
||||
return S->getStmt();
|
||||
}
|
||||
if (const Stmt *S = CB->getTerminator())
|
||||
return S;
|
||||
|
|
|
@ -1170,13 +1170,14 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
|
|||
}
|
||||
|
||||
if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) {
|
||||
if (CFGStmt S = BE->getFirstElement().getAs<CFGStmt>()) {
|
||||
if (IsControlFlowExpr(S)) {
|
||||
if (const CFGStmt *S = BE->getFirstElement().getAs<CFGStmt>()) {
|
||||
const Stmt *stmt = S->getStmt();
|
||||
if (IsControlFlowExpr(stmt)) {
|
||||
// Add the proper context for '&&', '||', and '?'.
|
||||
EB.addContext(S);
|
||||
EB.addContext(stmt);
|
||||
}
|
||||
else
|
||||
EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt());
|
||||
EB.addExtendedContext(PDB.getEnclosingStmtLocation(stmt).asStmt());
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -191,18 +191,20 @@ void ExprEngine::processEndWorklist(bool hasWorkRemaining) {
|
|||
void ExprEngine::processCFGElement(const CFGElement E,
|
||||
StmtNodeBuilder& builder) {
|
||||
switch (E.getKind()) {
|
||||
case CFGElement::Statement:
|
||||
ProcessStmt(E.getAs<CFGStmt>(), builder);
|
||||
break;
|
||||
case CFGElement::Initializer:
|
||||
ProcessInitializer(E.getAs<CFGInitializer>(), builder);
|
||||
break;
|
||||
case CFGElement::ImplicitDtor:
|
||||
ProcessImplicitDtor(E.getAs<CFGImplicitDtor>(), builder);
|
||||
break;
|
||||
default:
|
||||
// Suppress compiler warning.
|
||||
llvm_unreachable("Unexpected CFGElement kind.");
|
||||
case CFGElement::Invalid:
|
||||
llvm_unreachable("Unexpected CFGElement kind.");
|
||||
case CFGElement::Statement:
|
||||
ProcessStmt(E.getAs<CFGStmt>()->getStmt(), builder);
|
||||
return;
|
||||
case CFGElement::Initializer:
|
||||
ProcessInitializer(E.getAs<CFGInitializer>()->getInitializer(), builder);
|
||||
return;
|
||||
case CFGElement::AutomaticObjectDtor:
|
||||
case CFGElement::BaseDtor:
|
||||
case CFGElement::MemberDtor:
|
||||
case CFGElement::TemporaryDtor:
|
||||
ProcessImplicitDtor(*E.getAs<CFGImplicitDtor>(), builder);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -345,7 +347,7 @@ void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D,
|
|||
StmtNodeBuilder &builder) {
|
||||
Builder = &builder;
|
||||
|
||||
switch (D.getDtorKind()) {
|
||||
switch (D.getKind()) {
|
||||
case CFGElement::AutomaticObjectDtor:
|
||||
ProcessAutomaticObjDtor(cast<CFGAutomaticObjDtor>(D), builder);
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue