Skip to content

Commit 351c218

Browse files
committedJul 12, 2017
CFG: Add CFGElement for automatic variables that leave the scope
Summary: This mimics the implementation for the implicit destructors. The generation of this scope leaving elements is hidden behind a flag to the CFGBuilder, thus it should not affect existing code. Currently, I'm missing a test (it's implicitly tested by the clang-tidy lifetime checker that I'm proposing). I though about a test using debug.DumpCFG, but then I would have to add an option to StaticAnalyzer/Core/AnalyzerOptions to enable the scope leaving CFGElement, which would only be useful to that particular test. Any other ideas how I could make a test for this feature? Reviewers: krememek, jordan_rose Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D15031 llvm-svn: 307759
1 parent 3a5d082 commit 351c218

File tree

12 files changed

+1052
-51
lines changed

12 files changed

+1052
-51
lines changed
 

‎clang/include/clang/Analysis/AnalysisContext.h

+1
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,7 @@ class AnalysisDeclContextManager {
426426
bool addImplicitDtors = false,
427427
bool addInitializers = false,
428428
bool addTemporaryDtors = false,
429+
bool addLifetime = false,
429430
bool synthesizeBodies = false,
430431
bool addStaticInitBranches = false,
431432
bool addCXXNewAllocator = true,

‎clang/include/clang/Analysis/CFG.h

+44-1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class CFGElement {
5858
Statement,
5959
Initializer,
6060
NewAllocator,
61+
LifetimeEnds,
6162
// dtor kind
6263
AutomaticObjectDtor,
6364
DeleteDtor,
@@ -167,6 +168,28 @@ class CFGNewAllocator : public CFGElement {
167168
}
168169
};
169170

171+
/// Represents the point where the lifetime of an automatic object ends
172+
class CFGLifetimeEnds : public CFGElement {
173+
public:
174+
explicit CFGLifetimeEnds(const VarDecl *var, const Stmt *stmt)
175+
: CFGElement(LifetimeEnds, var, stmt) {}
176+
177+
const VarDecl *getVarDecl() const {
178+
return static_cast<VarDecl *>(Data1.getPointer());
179+
}
180+
181+
const Stmt *getTriggerStmt() const {
182+
return static_cast<Stmt *>(Data2.getPointer());
183+
}
184+
185+
private:
186+
friend class CFGElement;
187+
CFGLifetimeEnds() {}
188+
static bool isKind(const CFGElement &elem) {
189+
return elem.getKind() == LifetimeEnds;
190+
}
191+
};
192+
170193
/// CFGImplicitDtor - Represents C++ object destructor implicitly generated
171194
/// by compiler on various occasions.
172195
class CFGImplicitDtor : public CFGElement {
@@ -701,6 +724,10 @@ class CFGBlock {
701724
Elements.push_back(CFGAutomaticObjDtor(VD, S), C);
702725
}
703726

727+
void appendLifetimeEnds(VarDecl *VD, Stmt *S, BumpVectorContext &C) {
728+
Elements.push_back(CFGLifetimeEnds(VD, S), C);
729+
}
730+
704731
void appendDeleteDtor(CXXRecordDecl *RD, CXXDeleteExpr *DE, BumpVectorContext &C) {
705732
Elements.push_back(CFGDeleteDtor(RD, DE), C);
706733
}
@@ -717,6 +744,19 @@ class CFGBlock {
717744
*I = CFGAutomaticObjDtor(VD, S);
718745
return ++I;
719746
}
747+
748+
// Scope leaving must be performed in reversed order. So insertion is in two
749+
// steps. First we prepare space for some number of elements, then we insert
750+
// the elements beginning at the last position in prepared space.
751+
iterator beginLifetimeEndsInsert(iterator I, size_t Cnt,
752+
BumpVectorContext &C) {
753+
return iterator(
754+
Elements.insert(I.base(), Cnt, CFGLifetimeEnds(nullptr, nullptr), C));
755+
}
756+
iterator insertLifetimeEnds(iterator I, VarDecl *VD, Stmt *S) {
757+
*I = CFGLifetimeEnds(VD, S);
758+
return ++I;
759+
}
720760
};
721761

722762
/// \brief CFGCallback defines methods that should be called when a logical
@@ -753,6 +793,7 @@ class CFG {
753793
bool AddEHEdges;
754794
bool AddInitializers;
755795
bool AddImplicitDtors;
796+
bool AddLifetime;
756797
bool AddTemporaryDtors;
757798
bool AddStaticInitBranches;
758799
bool AddCXXNewAllocator;
@@ -774,8 +815,10 @@ class CFG {
774815

775816
BuildOptions()
776817
: forcedBlkExprs(nullptr), Observer(nullptr),
777-
PruneTriviallyFalseEdges(true), AddEHEdges(false),
818+
PruneTriviallyFalseEdges(true),
819+
AddEHEdges(false),
778820
AddInitializers(false), AddImplicitDtors(false),
821+
AddLifetime(false),
779822
AddTemporaryDtors(false), AddStaticInitBranches(false),
780823
AddCXXNewAllocator(false), AddCXXDefaultInitExprInCtors(false) {}
781824
};

‎clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h

+21-1
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,15 @@ class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> {
205205
/// Controls which C++ member functions will be considered for inlining.
206206
CXXInlineableMemberKind CXXMemberInliningMode;
207207

208+
/// \sa includeImplicitDtorsInCFG
209+
Optional<bool> IncludeImplicitDtorsInCFG;
210+
208211
/// \sa includeTemporaryDtorsInCFG
209212
Optional<bool> IncludeTemporaryDtorsInCFG;
210-
213+
214+
/// \sa IncludeLifetimeInCFG
215+
Optional<bool> IncludeLifetimeInCFG;
216+
211217
/// \sa mayInlineCXXStandardLibrary
212218
Optional<bool> InlineCXXStandardLibrary;
213219

@@ -395,6 +401,20 @@ class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> {
395401
/// accepts the values "true" and "false".
396402
bool includeTemporaryDtorsInCFG();
397403

404+
/// Returns whether or not implicit destructors for C++ objects should
405+
/// be included in the CFG.
406+
///
407+
/// This is controlled by the 'cfg-implicit-dtors' config option, which
408+
/// accepts the values "true" and "false".
409+
bool includeImplicitDtorsInCFG();
410+
411+
/// Returns whether or not end-of-lifetime information should be included in
412+
/// the CFG.
413+
///
414+
/// This is controlled by the 'cfg-lifetime' config option, which accepts
415+
/// the values "true" and "false".
416+
bool includeLifetimeInCFG();
417+
398418
/// Returns whether or not C++ standard library functions may be considered
399419
/// for inlining.
400420
///

‎clang/lib/Analysis/AnalysisDeclContext.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ AnalysisDeclContextManager::AnalysisDeclContextManager(bool useUnoptimizedCFG,
6767
bool addImplicitDtors,
6868
bool addInitializers,
6969
bool addTemporaryDtors,
70+
bool addLifetime,
7071
bool synthesizeBodies,
7172
bool addStaticInitBranch,
7273
bool addCXXNewAllocator,
@@ -77,6 +78,7 @@ AnalysisDeclContextManager::AnalysisDeclContextManager(bool useUnoptimizedCFG,
7778
cfgBuildOptions.AddImplicitDtors = addImplicitDtors;
7879
cfgBuildOptions.AddInitializers = addInitializers;
7980
cfgBuildOptions.AddTemporaryDtors = addTemporaryDtors;
81+
cfgBuildOptions.AddLifetime = addLifetime;
8082
cfgBuildOptions.AddStaticInitBranches = addStaticInitBranch;
8183
cfgBuildOptions.AddCXXNewAllocator = addCXXNewAllocator;
8284
}

0 commit comments

Comments
 (0)
Please sign in to comment.