Skip to content

Commit

Permalink
CFG: Add CFGElement for automatic variables that leave the scope
Browse files Browse the repository at this point in the history
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
  • Loading branch information
mgehre committed Jul 12, 2017
1 parent 3a5d082 commit 351c218
Show file tree
Hide file tree
Showing 12 changed files with 1,052 additions and 51 deletions.
1 change: 1 addition & 0 deletions clang/include/clang/Analysis/AnalysisContext.h
Expand Up @@ -426,6 +426,7 @@ class AnalysisDeclContextManager {
bool addImplicitDtors = false,
bool addInitializers = false,
bool addTemporaryDtors = false,
bool addLifetime = false,
bool synthesizeBodies = false,
bool addStaticInitBranches = false,
bool addCXXNewAllocator = true,
Expand Down
45 changes: 44 additions & 1 deletion clang/include/clang/Analysis/CFG.h
Expand Up @@ -58,6 +58,7 @@ class CFGElement {
Statement,
Initializer,
NewAllocator,
LifetimeEnds,
// dtor kind
AutomaticObjectDtor,
DeleteDtor,
Expand Down Expand Up @@ -167,6 +168,28 @@ class CFGNewAllocator : public CFGElement {
}
};

/// Represents the point where the lifetime of an automatic object ends
class CFGLifetimeEnds : public CFGElement {
public:
explicit CFGLifetimeEnds(const VarDecl *var, const Stmt *stmt)
: CFGElement(LifetimeEnds, var, stmt) {}

const VarDecl *getVarDecl() const {
return static_cast<VarDecl *>(Data1.getPointer());
}

const Stmt *getTriggerStmt() const {
return static_cast<Stmt *>(Data2.getPointer());
}

private:
friend class CFGElement;
CFGLifetimeEnds() {}
static bool isKind(const CFGElement &elem) {
return elem.getKind() == LifetimeEnds;
}
};

/// CFGImplicitDtor - Represents C++ object destructor implicitly generated
/// by compiler on various occasions.
class CFGImplicitDtor : public CFGElement {
Expand Down Expand Up @@ -701,6 +724,10 @@ class CFGBlock {
Elements.push_back(CFGAutomaticObjDtor(VD, S), C);
}

void appendLifetimeEnds(VarDecl *VD, Stmt *S, BumpVectorContext &C) {
Elements.push_back(CFGLifetimeEnds(VD, S), C);
}

void appendDeleteDtor(CXXRecordDecl *RD, CXXDeleteExpr *DE, BumpVectorContext &C) {
Elements.push_back(CFGDeleteDtor(RD, DE), C);
}
Expand All @@ -717,6 +744,19 @@ class CFGBlock {
*I = CFGAutomaticObjDtor(VD, S);
return ++I;
}

// Scope leaving must be performed in reversed order. So insertion is in two
// steps. First we prepare space for some number of elements, then we insert
// the elements beginning at the last position in prepared space.
iterator beginLifetimeEndsInsert(iterator I, size_t Cnt,
BumpVectorContext &C) {
return iterator(
Elements.insert(I.base(), Cnt, CFGLifetimeEnds(nullptr, nullptr), C));
}
iterator insertLifetimeEnds(iterator I, VarDecl *VD, Stmt *S) {
*I = CFGLifetimeEnds(VD, S);
return ++I;
}
};

/// \brief CFGCallback defines methods that should be called when a logical
Expand Down Expand Up @@ -753,6 +793,7 @@ class CFG {
bool AddEHEdges;
bool AddInitializers;
bool AddImplicitDtors;
bool AddLifetime;
bool AddTemporaryDtors;
bool AddStaticInitBranches;
bool AddCXXNewAllocator;
Expand All @@ -774,8 +815,10 @@ class CFG {

BuildOptions()
: forcedBlkExprs(nullptr), Observer(nullptr),
PruneTriviallyFalseEdges(true), AddEHEdges(false),
PruneTriviallyFalseEdges(true),
AddEHEdges(false),
AddInitializers(false), AddImplicitDtors(false),
AddLifetime(false),
AddTemporaryDtors(false), AddStaticInitBranches(false),
AddCXXNewAllocator(false), AddCXXDefaultInitExprInCtors(false) {}
};
Expand Down
22 changes: 21 additions & 1 deletion clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
Expand Up @@ -205,9 +205,15 @@ class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> {
/// Controls which C++ member functions will be considered for inlining.
CXXInlineableMemberKind CXXMemberInliningMode;

/// \sa includeImplicitDtorsInCFG
Optional<bool> IncludeImplicitDtorsInCFG;

/// \sa includeTemporaryDtorsInCFG
Optional<bool> IncludeTemporaryDtorsInCFG;


/// \sa IncludeLifetimeInCFG
Optional<bool> IncludeLifetimeInCFG;

/// \sa mayInlineCXXStandardLibrary
Optional<bool> InlineCXXStandardLibrary;

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

/// Returns whether or not implicit destructors for C++ objects should
/// be included in the CFG.
///
/// This is controlled by the 'cfg-implicit-dtors' config option, which
/// accepts the values "true" and "false".
bool includeImplicitDtorsInCFG();

/// Returns whether or not end-of-lifetime information should be included in
/// the CFG.
///
/// This is controlled by the 'cfg-lifetime' config option, which accepts
/// the values "true" and "false".
bool includeLifetimeInCFG();

/// Returns whether or not C++ standard library functions may be considered
/// for inlining.
///
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Analysis/AnalysisDeclContext.cpp
Expand Up @@ -67,6 +67,7 @@ AnalysisDeclContextManager::AnalysisDeclContextManager(bool useUnoptimizedCFG,
bool addImplicitDtors,
bool addInitializers,
bool addTemporaryDtors,
bool addLifetime,
bool synthesizeBodies,
bool addStaticInitBranch,
bool addCXXNewAllocator,
Expand All @@ -77,6 +78,7 @@ AnalysisDeclContextManager::AnalysisDeclContextManager(bool useUnoptimizedCFG,
cfgBuildOptions.AddImplicitDtors = addImplicitDtors;
cfgBuildOptions.AddInitializers = addInitializers;
cfgBuildOptions.AddTemporaryDtors = addTemporaryDtors;
cfgBuildOptions.AddLifetime = addLifetime;
cfgBuildOptions.AddStaticInitBranches = addStaticInitBranch;
cfgBuildOptions.AddCXXNewAllocator = addCXXNewAllocator;
}
Expand Down

0 comments on commit 351c218

Please sign in to comment.