summaryrefslogtreecommitdiffstats
path: root/lib/Analysis/CFG.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Analysis/CFG.cpp')
-rw-r--r--lib/Analysis/CFG.cpp166
1 files changed, 116 insertions, 50 deletions
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index 315e543..1adb8b8 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -12,20 +12,20 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Support/SaveAndRestore.h"
#include "clang/Analysis/CFG.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclCXX.h"
-#include "clang/AST/StmtVisitor.h"
#include "clang/AST/PrettyPrinter.h"
-#include "clang/AST/CharUnits.h"
-#include "clang/Basic/AttrKinds.h"
-#include "llvm/Support/GraphWriter.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Format.h"
+#include "clang/AST/StmtVisitor.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/GraphWriter.h"
+#include "llvm/Support/SaveAndRestore.h"
using namespace clang;
@@ -233,6 +233,44 @@ public:
}
};
+class reverse_children {
+ llvm::SmallVector<Stmt *, 12> childrenBuf;
+ ArrayRef<Stmt*> children;
+public:
+ reverse_children(Stmt *S);
+
+ typedef ArrayRef<Stmt*>::reverse_iterator iterator;
+ iterator begin() const { return children.rbegin(); }
+ iterator end() const { return children.rend(); }
+};
+
+
+reverse_children::reverse_children(Stmt *S) {
+ if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
+ children = CE->getRawSubExprs();
+ return;
+ }
+ switch (S->getStmtClass()) {
+ // Note: Fill in this switch with more cases we want to optimize.
+ case Stmt::InitListExprClass: {
+ InitListExpr *IE = cast<InitListExpr>(S);
+ children = llvm::makeArrayRef(reinterpret_cast<Stmt**>(IE->getInits()),
+ IE->getNumInits());
+ return;
+ }
+ default:
+ break;
+ }
+
+ // Default case for all other statements.
+ for (Stmt::child_range I = S->children(); I; ++I) {
+ childrenBuf.push_back(*I);
+ }
+
+ // This needs to be done *after* childrenBuf has been populated.
+ children = childrenBuf;
+}
+
/// CFGBuilder - This class implements CFG construction from an AST.
/// The builder is stateful: an instance of the builder should be used to only
/// construct a single CFG.
@@ -637,7 +675,7 @@ CFG* CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) {
E = BackpatchBlocks.end(); I != E; ++I ) {
CFGBlock *B = I->block;
- GotoStmt *G = cast<GotoStmt>(B->getTerminator());
+ const GotoStmt *G = cast<GotoStmt>(B->getTerminator());
LabelMapTy::iterator LI = LabelMap.find(G->getLabel());
// If there is no target for the goto, then we are looking at an
@@ -807,7 +845,7 @@ void CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B,
Ty = Context->getBaseElementType(Ty);
const CXXDestructorDecl *Dtor = Ty->getAsCXXRecordDecl()->getDestructor();
- if (cast<FunctionType>(Dtor->getType())->getNoReturnAttr())
+ if (Dtor->isNoReturn())
Block = createNoReturnBlock();
else
autoCreateBlock();
@@ -1166,14 +1204,19 @@ CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) {
}
/// VisitChildren - Visit the children of a Stmt.
-CFGBlock *CFGBuilder::VisitChildren(Stmt *Terminator) {
- CFGBlock *lastBlock = Block;
- for (Stmt::child_range I = Terminator->children(); I; ++I)
- if (Stmt *child = *I)
- if (CFGBlock *b = Visit(child))
- lastBlock = b;
+CFGBlock *CFGBuilder::VisitChildren(Stmt *S) {
+ CFGBlock *B = Block;
- return lastBlock;
+ // Visit the children in their reverse order so that they appear in
+ // left-to-right (natural) order in the CFG.
+ reverse_children RChildren(S);
+ for (reverse_children::iterator I = RChildren.begin(), E = RChildren.end();
+ I != E; ++I) {
+ if (Stmt *Child = *I)
+ if (CFGBlock *R = Visit(Child))
+ B = R;
+ }
+ return B;
}
CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A,
@@ -1402,7 +1445,7 @@ CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
}
if (FunctionDecl *FD = C->getDirectCallee()) {
- if (FD->hasAttr<NoReturnAttr>())
+ if (FD->isNoReturn())
NoReturn = true;
if (FD->hasAttr<NoThrowAttr>())
AddEHEdge = false;
@@ -1610,6 +1653,21 @@ CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt *DS) {
bool IsReference = false;
bool HasTemporaries = false;
+ // Guard static initializers under a branch.
+ CFGBlock *blockAfterStaticInit = 0;
+
+ if (BuildOpts.AddStaticInitBranches && VD->isStaticLocal()) {
+ // For static variables, we need to create a branch to track
+ // whether or not they are initialized.
+ if (Block) {
+ Succ = Block;
+ Block = 0;
+ if (badCFG)
+ return 0;
+ }
+ blockAfterStaticInit = Succ;
+ }
+
// Destructors of temporaries in initialization expression should be called
// after initialization finishes.
Expr *Init = VD->getInit();
@@ -1657,7 +1715,17 @@ CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt *DS) {
if (ScopePos && VD == *ScopePos)
++ScopePos;
- return Block ? Block : LastBlock;
+ CFGBlock *B = LastBlock;
+ if (blockAfterStaticInit) {
+ Succ = B;
+ Block = createBlock(false);
+ Block->setTerminator(DS);
+ addSuccessor(Block, blockAfterStaticInit);
+ addSuccessor(Block, B);
+ B = Block;
+ }
+
+ return B;
}
CFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) {
@@ -3093,19 +3161,14 @@ tryAgain:
CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(Stmt *E) {
// When visiting children for destructors we want to visit them in reverse
- // order. Because there's no reverse iterator for children must to reverse
- // them in helper vector.
- typedef SmallVector<Stmt *, 4> ChildrenVect;
- ChildrenVect ChildrenRev;
- for (Stmt::child_range I = E->children(); I; ++I) {
- if (*I) ChildrenRev.push_back(*I);
- }
-
+ // order that they will appear in the CFG. Because the CFG is built
+ // bottom-up, this means we visit them in their natural order, which
+ // reverses them in the CFG.
CFGBlock *B = Block;
- for (ChildrenVect::reverse_iterator I = ChildrenRev.rbegin(),
- L = ChildrenRev.rend(); I != L; ++I) {
- if (CFGBlock *R = VisitForTemporaryDtors(*I))
- B = R;
+ for (Stmt::child_range I = E->children(); I; ++I) {
+ if (Stmt *Child = *I)
+ if (CFGBlock *R = VisitForTemporaryDtors(Child))
+ B = R;
}
return B;
}
@@ -3190,7 +3253,7 @@ CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
// a new block for the destructor which does not have as a successor
// anything built thus far. Control won't flow out of this block.
const CXXDestructorDecl *Dtor = E->getTemporary()->getDestructor();
- if (cast<FunctionType>(Dtor->getType())->getNoReturnAttr())
+ if (Dtor->isNoReturn())
Block = createNoReturnBlock();
else
autoCreateBlock();
@@ -3294,13 +3357,12 @@ CFG* CFG::buildCFG(const Decl *D, Stmt *Statement, ASTContext *C,
const CXXDestructorDecl *
CFGImplicitDtor::getDestructorDecl(ASTContext &astContext) const {
switch (getKind()) {
- case CFGElement::Invalid:
case CFGElement::Statement:
case CFGElement::Initializer:
llvm_unreachable("getDestructorDecl should only be used with "
"ImplicitDtors");
case CFGElement::AutomaticObjectDtor: {
- const VarDecl *var = cast<CFGAutomaticObjDtor>(this)->getVarDecl();
+ const VarDecl *var = castAs<CFGAutomaticObjDtor>().getVarDecl();
QualType ty = var->getType();
ty = ty.getNonReferenceType();
while (const ArrayType *arrayType = astContext.getAsArrayType(ty)) {
@@ -3313,7 +3375,7 @@ CFGImplicitDtor::getDestructorDecl(ASTContext &astContext) const {
}
case CFGElement::TemporaryDtor: {
const CXXBindTemporaryExpr *bindExpr =
- cast<CFGTemporaryDtor>(this)->getBindTemporaryExpr();
+ castAs<CFGTemporaryDtor>().getBindTemporaryExpr();
const CXXTemporary *temp = bindExpr->getTemporary();
return temp->getDestructor();
}
@@ -3327,10 +3389,8 @@ CFGImplicitDtor::getDestructorDecl(ASTContext &astContext) const {
}
bool CFGImplicitDtor::isNoReturn(ASTContext &astContext) const {
- if (const CXXDestructorDecl *decl = getDestructorDecl(astContext)) {
- QualType ty = decl->getType();
- return cast<FunctionType>(ty)->getNoReturnAttr();
- }
+ if (const CXXDestructorDecl *DD = getDestructorDecl(astContext))
+ return DD->isNoReturn();
return false;
}
@@ -3370,7 +3430,7 @@ 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 (const CFGStmt *S = BI->getAs<CFGStmt>())
+ if (Optional<CFGStmt> S = BI->getAs<CFGStmt>())
FindSubExprAssignments(S->getStmt(), SubExprAssignments);
for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I) {
@@ -3379,7 +3439,7 @@ static BlkExprMapTy* PopulateBlkExprMap(CFG& cfg) {
// block-level that are block-level expressions.
for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI) {
- const CFGStmt *CS = BI->getAs<CFGStmt>();
+ Optional<CFGStmt> CS = BI->getAs<CFGStmt>();
if (!CS)
continue;
if (const Expr *Exp = dyn_cast<Expr>(CS->getStmt())) {
@@ -3495,7 +3555,7 @@ public:
unsigned j = 1;
for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ;
BI != BEnd; ++BI, ++j ) {
- if (const CFGStmt *SE = BI->getAs<CFGStmt>()) {
+ if (Optional<CFGStmt> SE = BI->getAs<CFGStmt>()) {
const Stmt *stmt= SE->getStmt();
std::pair<unsigned, unsigned> P((*I)->getBlockID(), j);
StmtMap[stmt] = P;
@@ -3607,6 +3667,11 @@ public:
Terminator->printPretty(OS, Helper, Policy);
}
+ void VisitDeclStmt(DeclStmt *DS) {
+ VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
+ OS << "static init " << VD->getName();
+ }
+
void VisitForStmt(ForStmt *F) {
OS << "for (" ;
if (F->getInit())
@@ -3685,7 +3750,7 @@ public:
static void print_elem(raw_ostream &OS, StmtPrinterHelper* Helper,
const CFGElement &E) {
- if (const CFGStmt *CS = E.getAs<CFGStmt>()) {
+ if (Optional<CFGStmt> CS = E.getAs<CFGStmt>()) {
const Stmt *S = CS->getStmt();
if (Helper) {
@@ -3733,7 +3798,7 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper* Helper,
if (isa<Expr>(S))
OS << '\n';
- } else if (const CFGInitializer *IE = E.getAs<CFGInitializer>()) {
+ } else if (Optional<CFGInitializer> IE = E.getAs<CFGInitializer>()) {
const CXXCtorInitializer *I = IE->getInitializer();
if (I->isBaseInitializer())
OS << I->getBaseClass()->getAsCXXRecordDecl()->getName();
@@ -3748,7 +3813,8 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper* Helper,
OS << " (Base initializer)\n";
else OS << " (Member initializer)\n";
- } else if (const CFGAutomaticObjDtor *DE = E.getAs<CFGAutomaticObjDtor>()){
+ } else if (Optional<CFGAutomaticObjDtor> DE =
+ E.getAs<CFGAutomaticObjDtor>()) {
const VarDecl *VD = DE->getVarDecl();
Helper->handleDecl(VD, OS);
@@ -3760,19 +3826,19 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper* Helper,
OS << ".~" << T->getAsCXXRecordDecl()->getName().str() << "()";
OS << " (Implicit destructor)\n";
- } else if (const CFGBaseDtor *BE = E.getAs<CFGBaseDtor>()) {
+ } else if (Optional<CFGBaseDtor> BE = E.getAs<CFGBaseDtor>()) {
const CXXBaseSpecifier *BS = BE->getBaseSpecifier();
OS << "~" << BS->getType()->getAsCXXRecordDecl()->getName() << "()";
OS << " (Base object destructor)\n";
- } else if (const CFGMemberDtor *ME = E.getAs<CFGMemberDtor>()) {
+ } else if (Optional<CFGMemberDtor> ME = E.getAs<CFGMemberDtor>()) {
const FieldDecl *FD = ME->getFieldDecl();
const Type *T = FD->getType()->getBaseElementTypeUnsafe();
OS << "this->" << FD->getName();
OS << ".~" << T->getAsCXXRecordDecl()->getName() << "()";
OS << " (Member object destructor)\n";
- } else if (const CFGTemporaryDtor *TE = E.getAs<CFGTemporaryDtor>()) {
+ } else if (Optional<CFGTemporaryDtor> TE = E.getAs<CFGTemporaryDtor>()) {
const CXXBindTemporaryExpr *BT = TE->getBindTemporaryExpr();
OS << "~" << BT->getType()->getAsCXXRecordDecl()->getName() << "()";
OS << " (Temporary object destructor)\n";
@@ -3893,7 +3959,7 @@ static void print_block(raw_ostream &OS, const CFG* cfg,
for (CFGBlock::const_pred_iterator I = B.pred_begin(), E = B.pred_end();
I != E; ++I, ++i) {
- if (i == 8 || (i-8) == 0)
+ if (i % 10 == 8)
OS << "\n ";
OS << " B" << (*I)->getBlockID();
@@ -3922,7 +3988,7 @@ static void print_block(raw_ostream &OS, const CFG* cfg,
for (CFGBlock::const_succ_iterator I = B.succ_begin(), E = B.succ_end();
I != E; ++I, ++i) {
- if (i == 8 || (i-8) % 10 == 0)
+ if (i % 10 == 8)
OS << "\n ";
if (*I)
OpenPOWER on IntegriCloud