[cfe-commits] r114403 - in /cfe/trunk: include/clang/Analysis/CFG.h lib/Analysis/CFG.cpp
Marcin Swiderski
marcin.sfider at gmail.com
Mon Sep 20 22:58:15 PDT 2010
Author: sfider
Date: Tue Sep 21 00:58:15 2010
New Revision: 114403
URL: http://llvm.org/viewvc/llvm-project?rev=114403&view=rev
Log:
Added:
- definitions of interfaces for CFGInitializer and CFGAutomaticObjDtor,
- support for above classes to print_elem function (renamed print_stmt),
- support for VarDecls in StmtPrinterHelper.
Modified:
cfe/trunk/include/clang/Analysis/CFG.h
cfe/trunk/lib/Analysis/CFG.cpp
Modified: cfe/trunk/include/clang/Analysis/CFG.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/CFG.h?rev=114403&r1=114402&r2=114403&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/CFG.h (original)
+++ cfe/trunk/include/clang/Analysis/CFG.h Tue Sep 21 00:58:15 2010
@@ -31,6 +31,8 @@
class Decl;
class Stmt;
class Expr;
+ class VarDecl;
+ class CXXBaseOrMemberInitializer;
class CFG;
class PrinterHelper;
class LangOptions;
@@ -59,9 +61,12 @@
// 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) {}
+
public:
CFGElement() {}
- CFGElement(void *Ptr, unsigned Int) : Data1(Ptr, Int) {}
Kind getKind() const { return static_cast<Kind>(Data1.getInt()); }
@@ -101,22 +106,57 @@
}
};
+/// CFGInitializer - Represents C++ base or member initializer from
+/// constructor's initialization list.
class CFGInitializer : public CFGElement {
public:
+ CFGInitializer() {}
+ CFGInitializer(CXXBaseOrMemberInitializer* I)
+ : CFGElement(I, Initializer) {}
+
+ CXXBaseOrMemberInitializer* getInitializer() const {
+ return static_cast<CXXBaseOrMemberInitializer*>(Data1.getPointer());
+ }
+ operator CXXBaseOrMemberInitializer*() const { return getInitializer(); }
+
static bool classof(const CFGElement *E) {
return E->getKind() == Initializer;
}
};
+/// CFGImplicitDtor - Represents C++ object destructor imlicitly generated
+/// by compiler on various occasions.
class CFGImplicitDtor : public CFGElement {
+protected:
+ CFGImplicitDtor(unsigned K, void* P, void* S)
+ : CFGElement(P, Dtor, S, K - DTOR_BEGIN) {}
+
public:
+ CFGImplicitDtor() {}
+
static bool classof(const CFGElement *E) {
return E->getKind() == Dtor;
}
};
+/// CFGAutomaticObjDtor - Represents C++ object destructor implicit generated
+/// for automatic object or temporary bound to const reference at the point
+/// of leaving its local scope.
class CFGAutomaticObjDtor: public CFGImplicitDtor {
public:
+ CFGAutomaticObjDtor() {}
+ CFGAutomaticObjDtor(VarDecl* VD, Stmt* S)
+ : CFGImplicitDtor(AutomaticObjectDtor, VD, S) {}
+
+ VarDecl* getVarDecl() const {
+ return static_cast<VarDecl*>(Data1.getPointer());
+ }
+
+ // Get statement end of which triggered the destructor call.
+ Stmt* getTriggerStmt() const {
+ return static_cast<Stmt*>(Data2.getPointer());
+ }
+
static bool classof(const CFGElement *E) {
return E->getKind() == Dtor && E->getDtorKind() == AutomaticObjectDtor;
}
Modified: cfe/trunk/lib/Analysis/CFG.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=114403&r1=114402&r2=114403&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CFG.cpp (original)
+++ cfe/trunk/lib/Analysis/CFG.cpp Tue Sep 21 00:58:15 2010
@@ -1952,7 +1952,9 @@
class StmtPrinterHelper : public PrinterHelper {
typedef llvm::DenseMap<Stmt*,std::pair<unsigned,unsigned> > StmtMapTy;
+ typedef llvm::DenseMap<Decl*,std::pair<unsigned,unsigned> > DeclMapTy;
StmtMapTy StmtMap;
+ DeclMapTy DeclMap;
signed CurrentBlock;
unsigned CurrentStmt;
const LangOptions &LangOpts;
@@ -1963,11 +1965,35 @@
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 ) {
- CFGStmt CS = BI->getAs<CFGStmt>();
- if (!CS.isValid())
- continue;
- StmtMap[CS] = std::make_pair((*I)->getBlockID(),j);
+ BI != BEnd; ++BI, ++j ) {
+ if (CFGStmt SE = BI->getAs<CFGStmt>()) {
+ std::pair<unsigned, unsigned> P((*I)->getBlockID(), j);
+ StmtMap[SE] = 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;
+ }
+ }
}
}
}
@@ -1978,9 +2004,8 @@
void setBlockID(signed i) { CurrentBlock = i; }
void setStmtID(unsigned i) { CurrentStmt = i; }
- virtual bool handledStmt(Stmt* Terminator, llvm::raw_ostream& OS) {
-
- StmtMapTy::iterator I = StmtMap.find(Terminator);
+ virtual bool handledStmt(Stmt* S, llvm::raw_ostream& OS) {
+ StmtMapTy::iterator I = StmtMap.find(S);
if (I == StmtMap.end())
return false;
@@ -1993,6 +2018,21 @@
OS << "[B" << I->second.first << "." << I->second.second << "]";
return true;
}
+
+ bool handleDecl(Decl* D, llvm::raw_ostream& OS) {
+ DeclMapTy::iterator I = DeclMap.find(D);
+
+ if (I == DeclMap.end())
+ return false;
+
+ if (CurrentBlock >= 0 && I->second.first == (unsigned) CurrentBlock
+ && I->second.second == CurrentStmt) {
+ return false;
+ }
+
+ OS << "[B" << I->second.first << "." << I->second.second << "]";
+ return true;
+ }
};
} // end anonymous namespace
@@ -2095,52 +2135,74 @@
};
} // end anonymous namespace
-
-static void print_stmt(llvm::raw_ostream &OS, StmtPrinterHelper* Helper,
+static void print_elem(llvm::raw_ostream &OS, StmtPrinterHelper* Helper,
const CFGElement &E) {
- CFGStmt CS = E.getAs<CFGStmt>();
- if (!CS)
- return;
- Stmt *S = CS.getStmt();
-
- if (Helper) {
- // special printing for statement-expressions.
- if (StmtExpr* SE = dyn_cast<StmtExpr>(S)) {
- CompoundStmt* Sub = SE->getSubStmt();
-
- if (Sub->child_begin() != Sub->child_end()) {
- OS << "({ ... ; ";
- Helper->handledStmt(*SE->getSubStmt()->body_rbegin(),OS);
- OS << " })\n";
- return;
+ if (CFGStmt CS = E.getAs<CFGStmt>()) {
+ Stmt *S = CS;
+
+ if (Helper) {
+
+ // special printing for statement-expressions.
+ if (StmtExpr* SE = dyn_cast<StmtExpr>(S)) {
+ CompoundStmt* Sub = SE->getSubStmt();
+
+ if (Sub->child_begin() != Sub->child_end()) {
+ OS << "({ ... ; ";
+ Helper->handledStmt(*SE->getSubStmt()->body_rbegin(),OS);
+ OS << " })\n";
+ return;
+ }
+ }
+ // special printing for comma expressions.
+ if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
+ if (B->getOpcode() == BO_Comma) {
+ OS << "... , ";
+ Helper->handledStmt(B->getRHS(),OS);
+ OS << '\n';
+ return;
+ }
}
}
+ S->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts()));
- // special printing for comma expressions.
- if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
- if (B->getOpcode() == BO_Comma) {
- OS << "... , ";
- Helper->handledStmt(B->getRHS(),OS);
- OS << '\n';
- return;
- }
+ if (isa<CXXOperatorCallExpr>(S)) {
+ OS << " (OperatorCall)";
+ }
+ else if (isa<CXXBindTemporaryExpr>(S)) {
+ OS << " (BindTemporary)";
}
- }
- S->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts()));
-
- if (isa<CXXOperatorCallExpr>(S)) {
- OS << " (OperatorCall)";
- }
- else if (isa<CXXBindTemporaryExpr>(S)) {
- OS << " (BindTemporary)";
- }
+ // Expressions need a newline.
+ if (isa<Expr>(S))
+ OS << '\n';
+
+ } else if (CFGInitializer IE = E.getAs<CFGInitializer>()) {
+ CXXBaseOrMemberInitializer* I = IE;
+ if (I->isBaseInitializer())
+ OS << I->getBaseClass()->getAsCXXRecordDecl()->getName();
+ else OS << I->getMember()->getName();
+
+ OS << "(";
+ if (Expr* IE = I->getInit())
+ IE->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts()));
+ OS << ")";
+ if (I->isBaseInitializer())
+ OS << " (Base initializer)\n";
+ else OS << " (Member initializer)\n";
+
+ } else if (CFGAutomaticObjDtor DE = E.getAs<CFGAutomaticObjDtor>()){
+ VarDecl* VD = DE.getVarDecl();
+ Helper->handleDecl(VD, OS);
+
+ Type* T = VD->getType().getTypePtr();
+ if (const ReferenceType* RT = T->getAs<ReferenceType>())
+ T = RT->getPointeeType().getTypePtr();
- // Expressions need a newline.
- if (isa<Expr>(S))
- OS << '\n';
-}
+ OS << ".~" << T->getAsCXXRecordDecl()->getName().str() << "()";
+ OS << " (Implicit destructor)\n";
+ }
+ }
static void print_block(llvm::raw_ostream& OS, const CFG* cfg,
const CFGBlock& B,
@@ -2209,7 +2271,7 @@
if (Helper)
Helper->setStmtID(j);
- print_stmt(OS,Helper,*I);
+ print_elem(OS,Helper,*I);
}
// Print the terminator of this block.
More information about the cfe-commits
mailing list