From: Marcin Swiderski Date: Tue, 21 Sep 2010 05:58:15 +0000 (+0000) Subject: Added: X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1cff132e48e0ccc253c34e5a2fb12718bd4e7d2e;p=clang Added: - definitions of interfaces for CFGInitializer and CFGAutomaticObjDtor, - support for above classes to print_elem function (renamed print_stmt), - support for VarDecls in StmtPrinterHelper. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@114403 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h index 82f254f7a8..e0719feed0 100644 --- a/include/clang/Analysis/CFG.h +++ b/include/clang/Analysis/CFG.h @@ -31,6 +31,8 @@ namespace clang { class Decl; class Stmt; class Expr; + class VarDecl; + class CXXBaseOrMemberInitializer; class CFG; class PrinterHelper; class LangOptions; @@ -59,9 +61,12 @@ protected: // The int bits are used to mark the dtor kind. llvm::PointerIntPair 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(Data1.getInt()); } @@ -101,22 +106,57 @@ public: } }; +/// 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(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(Data1.getPointer()); + } + + // Get statement end of which triggered the destructor call. + Stmt* getTriggerStmt() const { + return static_cast(Data2.getPointer()); + } + static bool classof(const CFGElement *E) { return E->getKind() == Dtor && E->getDtorKind() == AutomaticObjectDtor; } diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index d9a375fc02..5e2b6a3fc9 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -1952,7 +1952,9 @@ namespace { class StmtPrinterHelper : public PrinterHelper { typedef llvm::DenseMap > StmtMapTy; + typedef llvm::DenseMap > DeclMapTy; StmtMapTy StmtMap; + DeclMapTy DeclMap; signed CurrentBlock; unsigned CurrentStmt; const LangOptions &LangOpts; @@ -1963,11 +1965,35 @@ public: 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(); - if (!CS.isValid()) - continue; - StmtMap[CS] = std::make_pair((*I)->getBlockID(),j); + BI != BEnd; ++BI, ++j ) { + if (CFGStmt SE = BI->getAs()) { + std::pair P((*I)->getBlockID(), j); + StmtMap[SE] = P; + + if (DeclStmt* DS = dyn_cast(SE.getStmt())) { + DeclMap[DS->getSingleDecl()] = P; + + } else if (IfStmt* IS = dyn_cast(SE.getStmt())) { + if (VarDecl* VD = IS->getConditionVariable()) + DeclMap[VD] = P; + + } else if (ForStmt* FS = dyn_cast(SE.getStmt())) { + if (VarDecl* VD = FS->getConditionVariable()) + DeclMap[VD] = P; + + } else if (WhileStmt* WS = dyn_cast(SE.getStmt())) { + if (VarDecl* VD = WS->getConditionVariable()) + DeclMap[VD] = P; + + } else if (SwitchStmt* SS = dyn_cast(SE.getStmt())) { + if (VarDecl* VD = SS->getConditionVariable()) + DeclMap[VD] = P; + + } else if (CXXCatchStmt* CS = dyn_cast(SE.getStmt())) { + if (VarDecl* VD = CS->getExceptionDecl()) + DeclMap[VD] = P; + } + } } } } @@ -1978,9 +2004,8 @@ public: 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 @@ public: 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 @@ public: }; } // 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(); - if (!CS) - return; - Stmt *S = CS.getStmt(); - - if (Helper) { - // special printing for statement-expressions. - if (StmtExpr* SE = dyn_cast(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()) { + Stmt *S = CS; + + if (Helper) { + + // special printing for statement-expressions. + if (StmtExpr* SE = dyn_cast(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(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(S)) { - if (B->getOpcode() == BO_Comma) { - OS << "... , "; - Helper->handledStmt(B->getRHS(),OS); - OS << '\n'; - return; - } + if (isa(S)) { + OS << " (OperatorCall)"; + } + else if (isa(S)) { + OS << " (BindTemporary)"; } - } - S->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts())); - - if (isa(S)) { - OS << " (OperatorCall)"; - } - else if (isa(S)) { - OS << " (BindTemporary)"; - } + // Expressions need a newline. + if (isa(S)) + OS << '\n'; + } else if (CFGInitializer IE = E.getAs()) { + CXXBaseOrMemberInitializer* I = IE; + if (I->isBaseInitializer()) + OS << I->getBaseClass()->getAsCXXRecordDecl()->getName(); + else OS << I->getMember()->getName(); - // Expressions need a newline. - if (isa(S)) - OS << '\n'; -} + 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()){ + VarDecl* VD = DE.getVarDecl(); + Helper->handleDecl(VD, OS); + + Type* T = VD->getType().getTypePtr(); + if (const ReferenceType* RT = T->getAs()) + T = RT->getPointeeType().getTypePtr(); + + 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 @@ static void print_block(llvm::raw_ostream& OS, const CFG* cfg, if (Helper) Helper->setStmtID(j); - print_stmt(OS,Helper,*I); + print_elem(OS,Helper,*I); } // Print the terminator of this block.