r371765 - [CFG] Add dumps for CFGElement and CFGElementRef
Kristof Umann via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 12 12:52:34 PDT 2019
Author: szelethus
Date: Thu Sep 12 12:52:34 2019
New Revision: 371765
URL: http://llvm.org/viewvc/llvm-project?rev=371765&view=rev
Log:
[CFG] Add dumps for CFGElement and CFGElementRef
Seems like we never had these, so here we go! I also did some refactoring as I
was chasing a bug unrelated to this revision.
Differential Revision: https://reviews.llvm.org/D66715
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=371765&r1=371764&r2=371765&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/CFG.h (original)
+++ cfe/trunk/include/clang/Analysis/CFG.h Thu Sep 12 12:52:34 2019
@@ -121,6 +121,12 @@ public:
x |= Data1.getInt();
return (Kind) x;
}
+
+ void dumpToStream(llvm::raw_ostream &OS) const;
+
+ void dump() const {
+ dumpToStream(llvm::errs());
+ }
};
class CFGStmt : public CFGElement {
@@ -650,8 +656,17 @@ class CFGBlock {
}
bool operator!=(ElementRefImpl Other) const { return !(*this == Other); }
- CFGElement operator*() { return (*Parent)[Index]; }
- CFGElementPtr operator->() { return &*(Parent->begin() + Index); }
+ CFGElement operator*() const { return (*Parent)[Index]; }
+ CFGElementPtr operator->() const { return &*(Parent->begin() + Index); }
+
+ void dumpToStream(llvm::raw_ostream &OS) const {
+ OS << getIndexInBlock() + 1 << ": ";
+ (*this)->dumpToStream(OS);
+ }
+
+ void dump() const {
+ dumpToStream(llvm::errs());
+ }
};
template <bool IsReverse, bool IsConst> class ElementRefIterator {
Modified: cfe/trunk/lib/Analysis/CFG.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=371765&r1=371764&r2=371765&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CFG.cpp (original)
+++ cfe/trunk/lib/Analysis/CFG.cpp Thu Sep 12 12:52:34 2019
@@ -4999,6 +4999,8 @@ class StmtPrinterHelper : public Printer
public:
StmtPrinterHelper(const CFG* cfg, const LangOptions &LO)
: LangOpts(LO) {
+ if (!cfg)
+ return;
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() ;
@@ -5321,9 +5323,21 @@ static void print_construction_context(r
}
static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
+ const CFGElement &E);
+
+void CFGElement::dumpToStream(llvm::raw_ostream &OS) const {
+ StmtPrinterHelper Helper(nullptr, {});
+ print_elem(OS, Helper, *this);
+}
+
+static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
const CFGElement &E) {
- if (Optional<CFGStmt> CS = E.getAs<CFGStmt>()) {
- const Stmt *S = CS->getStmt();
+ switch (E.getKind()) {
+ case CFGElement::Kind::Statement:
+ case CFGElement::Kind::CXXRecordTypedCall:
+ case CFGElement::Kind::Constructor: {
+ CFGStmt CS = E.castAs<CFGStmt>();
+ const Stmt *S = CS.getStmt();
assert(S != nullptr && "Expecting non-null Stmt");
// special printing for statement-expressions.
@@ -5375,12 +5389,18 @@ static void print_elem(raw_ostream &OS,
// Expressions need a newline.
if (isa<Expr>(S))
OS << '\n';
- } else if (Optional<CFGInitializer> IE = E.getAs<CFGInitializer>()) {
- print_initializer(OS, Helper, IE->getInitializer());
+
+ break;
+ }
+
+ case CFGElement::Kind::Initializer:
+ print_initializer(OS, Helper, E.castAs<CFGInitializer>().getInitializer());
OS << '\n';
- } else if (Optional<CFGAutomaticObjDtor> DE =
- E.getAs<CFGAutomaticObjDtor>()) {
- const VarDecl *VD = DE->getVarDecl();
+ break;
+
+ case CFGElement::Kind::AutomaticObjectDtor: {
+ CFGAutomaticObjDtor DE = E.castAs<CFGAutomaticObjDtor>();
+ const VarDecl *VD = DE.getVarDecl();
Helper.handleDecl(VD, OS);
QualType T = VD->getType();
@@ -5390,53 +5410,75 @@ static void print_elem(raw_ostream &OS,
OS << ".~";
T.getUnqualifiedType().print(OS, PrintingPolicy(Helper.getLangOpts()));
OS << "() (Implicit destructor)\n";
- } else if (Optional<CFGLifetimeEnds> DE = E.getAs<CFGLifetimeEnds>()) {
- const VarDecl *VD = DE->getVarDecl();
- Helper.handleDecl(VD, OS);
+ break;
+ }
+ case CFGElement::Kind::LifetimeEnds:
+ Helper.handleDecl(E.castAs<CFGLifetimeEnds>().getVarDecl(), OS);
OS << " (Lifetime ends)\n";
- } else if (Optional<CFGLoopExit> LE = E.getAs<CFGLoopExit>()) {
- const Stmt *LoopStmt = LE->getLoopStmt();
- OS << LoopStmt->getStmtClassName() << " (LoopExit)\n";
- } else if (Optional<CFGScopeBegin> SB = E.getAs<CFGScopeBegin>()) {
+ break;
+
+ case CFGElement::Kind::LoopExit:
+ OS << E.castAs<CFGLoopExit>().getLoopStmt()->getStmtClassName() << " (LoopExit)\n";
+ break;
+
+ case CFGElement::Kind::ScopeBegin:
OS << "CFGScopeBegin(";
- if (const VarDecl *VD = SB->getVarDecl())
+ if (const VarDecl *VD = E.castAs<CFGScopeBegin>().getVarDecl())
OS << VD->getQualifiedNameAsString();
OS << ")\n";
- } else if (Optional<CFGScopeEnd> SE = E.getAs<CFGScopeEnd>()) {
+ break;
+
+ case CFGElement::Kind::ScopeEnd:
OS << "CFGScopeEnd(";
- if (const VarDecl *VD = SE->getVarDecl())
+ if (const VarDecl *VD = E.castAs<CFGScopeEnd>().getVarDecl())
OS << VD->getQualifiedNameAsString();
OS << ")\n";
- } else if (Optional<CFGNewAllocator> NE = E.getAs<CFGNewAllocator>()) {
+ break;
+
+ case CFGElement::Kind::NewAllocator:
OS << "CFGNewAllocator(";
- if (const CXXNewExpr *AllocExpr = NE->getAllocatorExpr())
+ if (const CXXNewExpr *AllocExpr = E.castAs<CFGNewAllocator>().getAllocatorExpr())
AllocExpr->getType().print(OS, PrintingPolicy(Helper.getLangOpts()));
OS << ")\n";
- } else if (Optional<CFGDeleteDtor> DE = E.getAs<CFGDeleteDtor>()) {
- const CXXRecordDecl *RD = DE->getCXXRecordDecl();
+ break;
+
+ case CFGElement::Kind::DeleteDtor: {
+ CFGDeleteDtor DE = E.castAs<CFGDeleteDtor>();
+ const CXXRecordDecl *RD = DE.getCXXRecordDecl();
if (!RD)
return;
CXXDeleteExpr *DelExpr =
- const_cast<CXXDeleteExpr*>(DE->getDeleteExpr());
+ const_cast<CXXDeleteExpr*>(DE.getDeleteExpr());
Helper.handledStmt(cast<Stmt>(DelExpr->getArgument()), OS);
OS << "->~" << RD->getName().str() << "()";
OS << " (Implicit destructor)\n";
- } else if (Optional<CFGBaseDtor> BE = E.getAs<CFGBaseDtor>()) {
- const CXXBaseSpecifier *BS = BE->getBaseSpecifier();
+ break;
+ }
+
+ case CFGElement::Kind::BaseDtor: {
+ const CXXBaseSpecifier *BS = E.castAs<CFGBaseDtor>().getBaseSpecifier();
OS << "~" << BS->getType()->getAsCXXRecordDecl()->getName() << "()";
OS << " (Base object destructor)\n";
- } else if (Optional<CFGMemberDtor> ME = E.getAs<CFGMemberDtor>()) {
- const FieldDecl *FD = ME->getFieldDecl();
+ break;
+ }
+
+ case CFGElement::Kind::MemberDtor: {
+ const FieldDecl *FD = E.castAs<CFGMemberDtor>().getFieldDecl();
const Type *T = FD->getType()->getBaseElementTypeUnsafe();
OS << "this->" << FD->getName();
OS << ".~" << T->getAsCXXRecordDecl()->getName() << "()";
OS << " (Member object destructor)\n";
- } else if (Optional<CFGTemporaryDtor> TE = E.getAs<CFGTemporaryDtor>()) {
- const CXXBindTemporaryExpr *BT = TE->getBindTemporaryExpr();
+ break;
+ }
+
+ case CFGElement::Kind::TemporaryDtor: {
+ const CXXBindTemporaryExpr *BT = E.castAs<CFGTemporaryDtor>().getBindTemporaryExpr();
OS << "~";
BT->getType().print(OS, PrintingPolicy(Helper.getLangOpts()));
OS << "() (Temporary object destructor)\n";
+ break;
+ }
}
}
More information about the cfe-commits
mailing list