[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