Skip to content

Commit

Permalink
[CFG] Add an option to expand CXXDefaultInitExpr into aggregate initi…
Browse files Browse the repository at this point in the history
…alization

This is useful for clients that are relying on linearized CFGs for evaluating
subexpressions and want the default initializer to be evaluated properly.

The upcoming lifetime analysis is using this but it might also be useful
for the static analyzer at some point.

Differential Revision: https://reviews.llvm.org/D71642
  • Loading branch information
Xazax-hun committed Dec 18, 2019
1 parent 547659a commit ea93d7d
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 4 deletions.
1 change: 1 addition & 0 deletions clang/include/clang/Analysis/CFG.h
Expand Up @@ -1248,6 +1248,7 @@ class CFG {
bool AddStaticInitBranches = false;
bool AddCXXNewAllocator = false;
bool AddCXXDefaultInitExprInCtors = false;
bool AddCXXDefaultInitExprInAggregates = false;
bool AddRichCXXConstructors = false;
bool MarkElidedCXXConstructors = false;
bool AddVirtualBaseBranches = false;
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
Expand Up @@ -112,6 +112,12 @@ ANALYZER_OPTION(
bool, ShouldIncludeScopesInCFG, "cfg-scopes",
"Whether or not scope information should be included in the CFG.", false)

ANALYZER_OPTION(bool, ShouldIncludeDefaultInitForAggregates,
"cfg-expand-default-aggr-inits",
"Whether or not inline CXXDefaultInitializers for aggregate "
"initialization in the CFG.",
false)

ANALYZER_OPTION(
bool, MayInlineTemplateFunctions, "c++-template-inlining",
"Whether or not templated functions may be considered for inlining.", true)
Expand Down
32 changes: 29 additions & 3 deletions clang/lib/Analysis/CFG.cpp
Expand Up @@ -542,6 +542,7 @@ class CFGBuilder {

private:
// Visitors to walk an AST and construct the CFG.
CFGBlock *VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc);
CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc);
CFGBlock *VisitBinaryOperator(BinaryOperator *B, AddStmtChoice asc);
CFGBlock *VisitBreakStmt(BreakStmt *B);
Expand Down Expand Up @@ -2140,6 +2141,9 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc,
return Block;
return VisitStmt(S, asc);

case Stmt::InitListExprClass:
return VisitInitListExpr(cast<InitListExpr>(S), asc);

case Stmt::AddrLabelExprClass:
return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc);

Expand Down Expand Up @@ -2346,15 +2350,37 @@ CFGBlock *CFGBuilder::VisitChildren(Stmt *S) {
// Visit the children in their reverse order so that they appear in
// left-to-right (natural) order in the CFG.
reverse_children RChildren(S);
for (reverse_children::iterator I = RChildren.begin(), E = RChildren.end();
I != E; ++I) {
if (Stmt *Child = *I)
for (Stmt *Child : RChildren) {
if (Child)
if (CFGBlock *R = Visit(Child))
B = R;
}
return B;
}

CFGBlock *CFGBuilder::VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc) {
if (asc.alwaysAdd(*this, ILE)) {
autoCreateBlock();
appendStmt(Block, ILE);
}
CFGBlock *B = Block;

reverse_children RChildren(ILE);
for (Stmt *Child : RChildren) {
if (!Child)
continue;
if (CFGBlock *R = Visit(Child))
B = R;
if (BuildOpts.AddCXXDefaultInitExprInAggregates) {
if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Child))
if (Stmt *Child = DIE->getExpr())
if (CFGBlock *R = Visit(Child))
B = R;
}
}
return B;
}

CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A,
AddStmtChoice asc) {
AddressTakenLabels.insert(A->getLabel());
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp
Expand Up @@ -44,6 +44,8 @@ AnalysisManager::AnalysisManager(ASTContext &ASTCtx,
options(Options) {
AnaCtxMgr.getCFGBuildOptions().setAllAlwaysAdd();
AnaCtxMgr.getCFGBuildOptions().OmitImplicitValueInitializers = true;
AnaCtxMgr.getCFGBuildOptions().AddCXXDefaultInitExprInAggregates =
Options.ShouldIncludeDefaultInitForAggregates;
}

AnalysisManager::~AnalysisManager() {
Expand Down
28 changes: 28 additions & 0 deletions clang/test/Analysis/aggrinit-cfg-output.cpp
@@ -0,0 +1,28 @@
// RUN: %clang_cc1 -analyze -analyzer-checker=debug.DumpCFG -analyzer-config cfg-expand-default-aggr-inits=true %s > %t 2>&1
// RUN: FileCheck --input-file=%t %s

static char a[] = "foobar";

struct StringRef {
const char *member = nullptr;
int len = 3;
};

int main() {
StringRef s{a};
(void)s;
}

// CHECK: [B1]
// CHECK-NEXT: 1: a
// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, ArrayToPointerDecay, char *)
// CHECK-NEXT: 3: [B1.2] (ImplicitCastExpr, NoOp, const char *)
// CHECK-NEXT: 4: 3
// CHECK-NEXT: 5:
// CHECK-NEXT: 6: {[B1.1]}
// CHECK-NEXT: 7: StringRef s{a};
// CHECK-NEXT: 8: s
// CHECK-NEXT: 9: (void)[B1.8] (CStyleCastExpr, ToVoid, void)
// CHECK-NEXT: Preds (1): B2
// CHECK-NEXT: Succs (1): B0

3 changes: 2 additions & 1 deletion clang/test/Analysis/analyzer-config.c
Expand Up @@ -19,6 +19,7 @@
// CHECK-NEXT: c++-temp-dtor-inlining = true
// CHECK-NEXT: c++-template-inlining = true
// CHECK-NEXT: cfg-conditional-static-initializers = true
// CHECK-NEXT: cfg-expand-default-aggr-inits = false
// CHECK-NEXT: cfg-implicit-dtors = true
// CHECK-NEXT: cfg-lifetime = false
// CHECK-NEXT: cfg-loopexit = false
Expand Down Expand Up @@ -98,4 +99,4 @@
// CHECK-NEXT: unroll-loops = false
// CHECK-NEXT: widen-loops = false
// CHECK-NEXT: [stats]
// CHECK-NEXT: num-entries = 95
// CHECK-NEXT: num-entries = 96

0 comments on commit ea93d7d

Please sign in to comment.