[clang] ea93d7d - [CFG] Add an option to expand CXXDefaultInitExpr into aggregate initialization

Gabor Horvath via cfe-commits cfe-commits at lists.llvm.org
Tue Dec 17 17:56:30 PST 2019


Author: Gabor Horvath
Date: 2019-12-17T17:56:06-08:00
New Revision: ea93d7d6421612e9ea51b321eaf97fbdd64fe39b

URL: https://github.com/llvm/llvm-project/commit/ea93d7d6421612e9ea51b321eaf97fbdd64fe39b
DIFF: https://github.com/llvm/llvm-project/commit/ea93d7d6421612e9ea51b321eaf97fbdd64fe39b.diff

LOG: [CFG] Add an option to expand CXXDefaultInitExpr into aggregate initialization

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

Added: 
    clang/test/Analysis/aggrinit-cfg-output.cpp

Modified: 
    clang/include/clang/Analysis/CFG.h
    clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
    clang/lib/Analysis/CFG.cpp
    clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp
    clang/test/Analysis/analyzer-config.c

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Analysis/CFG.h b/clang/include/clang/Analysis/CFG.h
index ea3d8b2921a7..93de3178e661 100644
--- a/clang/include/clang/Analysis/CFG.h
+++ b/clang/include/clang/Analysis/CFG.h
@@ -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;

diff  --git a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
index d853fb74f9c7..00febf688195 100644
--- a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
+++ b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
@@ -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)

diff  --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index e10bfd805933..07945a80a311 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -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);
@@ -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);
 
@@ -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());

diff  --git a/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp b/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp
index 94fc09e64aa0..fdd03c75920d 100644
--- a/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp
@@ -44,6 +44,8 @@ AnalysisManager::AnalysisManager(ASTContext &ASTCtx,
       options(Options) {
   AnaCtxMgr.getCFGBuildOptions().setAllAlwaysAdd();
   AnaCtxMgr.getCFGBuildOptions().OmitImplicitValueInitializers = true;
+  AnaCtxMgr.getCFGBuildOptions().AddCXXDefaultInitExprInAggregates =
+      Options.ShouldIncludeDefaultInitForAggregates;
 }
 
 AnalysisManager::~AnalysisManager() {

diff  --git a/clang/test/Analysis/aggrinit-cfg-output.cpp b/clang/test/Analysis/aggrinit-cfg-output.cpp
new file mode 100644
index 000000000000..2e95a7f9e24f
--- /dev/null
+++ b/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
+

diff  --git a/clang/test/Analysis/analyzer-config.c b/clang/test/Analysis/analyzer-config.c
index 42e5269511fc..4707da3b9a3a 100644
--- a/clang/test/Analysis/analyzer-config.c
+++ b/clang/test/Analysis/analyzer-config.c
@@ -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
@@ -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


        


More information about the cfe-commits mailing list