Skip to content

Commit f174670

Browse files
author
Kristof Umann
committed
[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 llvm-svn: 371765
1 parent 6be90ac commit f174670

File tree

2 files changed

+87
-30
lines changed

2 files changed

+87
-30
lines changed

clang/include/clang/Analysis/CFG.h

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,12 @@ class CFGElement {
121121
x |= Data1.getInt();
122122
return (Kind) x;
123123
}
124+
125+
void dumpToStream(llvm::raw_ostream &OS) const;
126+
127+
void dump() const {
128+
dumpToStream(llvm::errs());
129+
}
124130
};
125131

126132
class CFGStmt : public CFGElement {
@@ -650,8 +656,17 @@ class CFGBlock {
650656
}
651657

652658
bool operator!=(ElementRefImpl Other) const { return !(*this == Other); }
653-
CFGElement operator*() { return (*Parent)[Index]; }
654-
CFGElementPtr operator->() { return &*(Parent->begin() + Index); }
659+
CFGElement operator*() const { return (*Parent)[Index]; }
660+
CFGElementPtr operator->() const { return &*(Parent->begin() + Index); }
661+
662+
void dumpToStream(llvm::raw_ostream &OS) const {
663+
OS << getIndexInBlock() + 1 << ": ";
664+
(*this)->dumpToStream(OS);
665+
}
666+
667+
void dump() const {
668+
dumpToStream(llvm::errs());
669+
}
655670
};
656671

657672
template <bool IsReverse, bool IsConst> class ElementRefIterator {

clang/lib/Analysis/CFG.cpp

Lines changed: 70 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4999,6 +4999,8 @@ class StmtPrinterHelper : public PrinterHelper {
49994999
public:
50005000
StmtPrinterHelper(const CFG* cfg, const LangOptions &LO)
50015001
: LangOpts(LO) {
5002+
if (!cfg)
5003+
return;
50025004
for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) {
50035005
unsigned j = 1;
50045006
for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ;
@@ -5320,10 +5322,22 @@ static void print_construction_context(raw_ostream &OS,
53205322
}
53215323
}
53225324

5325+
static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
5326+
const CFGElement &E);
5327+
5328+
void CFGElement::dumpToStream(llvm::raw_ostream &OS) const {
5329+
StmtPrinterHelper Helper(nullptr, {});
5330+
print_elem(OS, Helper, *this);
5331+
}
5332+
53235333
static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
53245334
const CFGElement &E) {
5325-
if (Optional<CFGStmt> CS = E.getAs<CFGStmt>()) {
5326-
const Stmt *S = CS->getStmt();
5335+
switch (E.getKind()) {
5336+
case CFGElement::Kind::Statement:
5337+
case CFGElement::Kind::CXXRecordTypedCall:
5338+
case CFGElement::Kind::Constructor: {
5339+
CFGStmt CS = E.castAs<CFGStmt>();
5340+
const Stmt *S = CS.getStmt();
53275341
assert(S != nullptr && "Expecting non-null Stmt");
53285342

53295343
// special printing for statement-expressions.
@@ -5375,12 +5389,18 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
53755389
// Expressions need a newline.
53765390
if (isa<Expr>(S))
53775391
OS << '\n';
5378-
} else if (Optional<CFGInitializer> IE = E.getAs<CFGInitializer>()) {
5379-
print_initializer(OS, Helper, IE->getInitializer());
5392+
5393+
break;
5394+
}
5395+
5396+
case CFGElement::Kind::Initializer:
5397+
print_initializer(OS, Helper, E.castAs<CFGInitializer>().getInitializer());
53805398
OS << '\n';
5381-
} else if (Optional<CFGAutomaticObjDtor> DE =
5382-
E.getAs<CFGAutomaticObjDtor>()) {
5383-
const VarDecl *VD = DE->getVarDecl();
5399+
break;
5400+
5401+
case CFGElement::Kind::AutomaticObjectDtor: {
5402+
CFGAutomaticObjDtor DE = E.castAs<CFGAutomaticObjDtor>();
5403+
const VarDecl *VD = DE.getVarDecl();
53845404
Helper.handleDecl(VD, OS);
53855405

53865406
QualType T = VD->getType();
@@ -5390,53 +5410,75 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
53905410
OS << ".~";
53915411
T.getUnqualifiedType().print(OS, PrintingPolicy(Helper.getLangOpts()));
53925412
OS << "() (Implicit destructor)\n";
5393-
} else if (Optional<CFGLifetimeEnds> DE = E.getAs<CFGLifetimeEnds>()) {
5394-
const VarDecl *VD = DE->getVarDecl();
5395-
Helper.handleDecl(VD, OS);
5413+
break;
5414+
}
53965415

5416+
case CFGElement::Kind::LifetimeEnds:
5417+
Helper.handleDecl(E.castAs<CFGLifetimeEnds>().getVarDecl(), OS);
53975418
OS << " (Lifetime ends)\n";
5398-
} else if (Optional<CFGLoopExit> LE = E.getAs<CFGLoopExit>()) {
5399-
const Stmt *LoopStmt = LE->getLoopStmt();
5400-
OS << LoopStmt->getStmtClassName() << " (LoopExit)\n";
5401-
} else if (Optional<CFGScopeBegin> SB = E.getAs<CFGScopeBegin>()) {
5419+
break;
5420+
5421+
case CFGElement::Kind::LoopExit:
5422+
OS << E.castAs<CFGLoopExit>().getLoopStmt()->getStmtClassName() << " (LoopExit)\n";
5423+
break;
5424+
5425+
case CFGElement::Kind::ScopeBegin:
54025426
OS << "CFGScopeBegin(";
5403-
if (const VarDecl *VD = SB->getVarDecl())
5427+
if (const VarDecl *VD = E.castAs<CFGScopeBegin>().getVarDecl())
54045428
OS << VD->getQualifiedNameAsString();
54055429
OS << ")\n";
5406-
} else if (Optional<CFGScopeEnd> SE = E.getAs<CFGScopeEnd>()) {
5430+
break;
5431+
5432+
case CFGElement::Kind::ScopeEnd:
54075433
OS << "CFGScopeEnd(";
5408-
if (const VarDecl *VD = SE->getVarDecl())
5434+
if (const VarDecl *VD = E.castAs<CFGScopeEnd>().getVarDecl())
54095435
OS << VD->getQualifiedNameAsString();
54105436
OS << ")\n";
5411-
} else if (Optional<CFGNewAllocator> NE = E.getAs<CFGNewAllocator>()) {
5437+
break;
5438+
5439+
case CFGElement::Kind::NewAllocator:
54125440
OS << "CFGNewAllocator(";
5413-
if (const CXXNewExpr *AllocExpr = NE->getAllocatorExpr())
5441+
if (const CXXNewExpr *AllocExpr = E.castAs<CFGNewAllocator>().getAllocatorExpr())
54145442
AllocExpr->getType().print(OS, PrintingPolicy(Helper.getLangOpts()));
54155443
OS << ")\n";
5416-
} else if (Optional<CFGDeleteDtor> DE = E.getAs<CFGDeleteDtor>()) {
5417-
const CXXRecordDecl *RD = DE->getCXXRecordDecl();
5444+
break;
5445+
5446+
case CFGElement::Kind::DeleteDtor: {
5447+
CFGDeleteDtor DE = E.castAs<CFGDeleteDtor>();
5448+
const CXXRecordDecl *RD = DE.getCXXRecordDecl();
54185449
if (!RD)
54195450
return;
54205451
CXXDeleteExpr *DelExpr =
5421-
const_cast<CXXDeleteExpr*>(DE->getDeleteExpr());
5452+
const_cast<CXXDeleteExpr*>(DE.getDeleteExpr());
54225453
Helper.handledStmt(cast<Stmt>(DelExpr->getArgument()), OS);
54235454
OS << "->~" << RD->getName().str() << "()";
54245455
OS << " (Implicit destructor)\n";
5425-
} else if (Optional<CFGBaseDtor> BE = E.getAs<CFGBaseDtor>()) {
5426-
const CXXBaseSpecifier *BS = BE->getBaseSpecifier();
5456+
break;
5457+
}
5458+
5459+
case CFGElement::Kind::BaseDtor: {
5460+
const CXXBaseSpecifier *BS = E.castAs<CFGBaseDtor>().getBaseSpecifier();
54275461
OS << "~" << BS->getType()->getAsCXXRecordDecl()->getName() << "()";
54285462
OS << " (Base object destructor)\n";
5429-
} else if (Optional<CFGMemberDtor> ME = E.getAs<CFGMemberDtor>()) {
5430-
const FieldDecl *FD = ME->getFieldDecl();
5463+
break;
5464+
}
5465+
5466+
case CFGElement::Kind::MemberDtor: {
5467+
const FieldDecl *FD = E.castAs<CFGMemberDtor>().getFieldDecl();
54315468
const Type *T = FD->getType()->getBaseElementTypeUnsafe();
54325469
OS << "this->" << FD->getName();
54335470
OS << ".~" << T->getAsCXXRecordDecl()->getName() << "()";
54345471
OS << " (Member object destructor)\n";
5435-
} else if (Optional<CFGTemporaryDtor> TE = E.getAs<CFGTemporaryDtor>()) {
5436-
const CXXBindTemporaryExpr *BT = TE->getBindTemporaryExpr();
5472+
break;
5473+
}
5474+
5475+
case CFGElement::Kind::TemporaryDtor: {
5476+
const CXXBindTemporaryExpr *BT = E.castAs<CFGTemporaryDtor>().getBindTemporaryExpr();
54375477
OS << "~";
54385478
BT->getType().print(OS, PrintingPolicy(Helper.getLangOpts()));
54395479
OS << "() (Temporary object destructor)\n";
5480+
break;
5481+
}
54405482
}
54415483
}
54425484

0 commit comments

Comments
 (0)