NoQ updated this revision to Diff 105897.
NoQ edited the summary of this revision.
NoQ added a comment.
Herald added a subscriber: mgorny.

This other diff implements approach (1) through a draft of a checker (that 
doesn't model much yet). I had to additionally make sure we already have a 
region to construct metadata for, in spirit of https://reviews.llvm.org/D27202.

For easier comparison, i thought it'd be better to stick it to the same 
differential revision.


https://reviews.llvm.org/D35216

Files:
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/CMakeLists.txt
  lib/StaticAnalyzer/Checkers/StdInitializerListChecker.cpp
  lib/StaticAnalyzer/Core/ExprEngine.cpp
  lib/StaticAnalyzer/Core/ProgramState.cpp
  test/Analysis/initializer.cpp
  test/Analysis/temporaries-callback-order.cpp

Index: test/Analysis/temporaries-callback-order.cpp
===================================================================
--- test/Analysis/temporaries-callback-order.cpp
+++ test/Analysis/temporaries-callback-order.cpp
@@ -18,14 +18,12 @@
 
 void seeIfCheckBindWorks() {
   // This should trigger checkBind. The rest of the code shouldn't.
-  // This also triggers checkRegionChanges after that.
   // Note that this function is analyzed first, so the messages would be on top.
   int x = 1;
 }
 
 // seeIfCheckBindWorks():
 // CHECK: Bind
-// CHECK-NEXT: RegionChanges
 
 // testTemporaries():
 // CHECK-NEXT: RegionChanges
Index: test/Analysis/initializer.cpp
===================================================================
--- test/Analysis/initializer.cpp
+++ test/Analysis/initializer.cpp
@@ -1,7 +1,9 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-inlining=constructors -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks,cplusplus.StdInitializerList,debug.ExprInspection -analyzer-config c++-inlining=constructors -std=c++11 -verify %s
 
 void clang_analyzer_eval(bool);
 
+#include "Inputs/system-header-simulator-cxx.h"
+
 class A {
   int x;
 public:
@@ -204,3 +206,13 @@
    const char(&f)[2];
 };
 }
+
+namespace CXX_initializer_lists {
+struct C {
+  C(std::initializer_list<int *> list);
+};
+void foo() {
+  int *x = new int;
+  C c{x}; // no-warning
+}
+}
Index: lib/StaticAnalyzer/Core/ProgramState.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ProgramState.cpp
+++ lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -116,13 +116,18 @@
                                       const LocationContext *LCtx,
                                       bool notifyChanges) const {
   ProgramStateManager &Mgr = getStateManager();
-  ProgramStateRef newState = makeWithStore(Mgr.StoreMgr->Bind(getStore(),
-                                                             LV, V));
+  ProgramStateRef NewState =
+      makeWithStore(Mgr.StoreMgr->Bind(getStore(), LV, V));
   const MemRegion *MR = LV.getAsRegion();
-  if (MR && Mgr.getOwningEngine() && notifyChanges)
-    return Mgr.getOwningEngine()->processRegionChange(newState, MR, LCtx);
+  if (MR && Mgr.getOwningEngine() && notifyChanges) {
+    NewState = Mgr.getOwningEngine()->processRegionChange(NewState, MR, LCtx);
+    if (!NewState)
+      return nullptr;
+    return Mgr.getOwningEngine()->processPointerEscapedOnBind(NewState, LV, V,
+                                                              LCtx);
+  }
 
-  return newState;
+  return NewState;
 }
 
 ProgramStateRef ProgramState::bindDefault(SVal loc,
Index: lib/StaticAnalyzer/Core/ExprEngine.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1074,12 +1074,19 @@
       for (ExplodedNodeSet::iterator it = preVisit.begin(), et = preVisit.end();
            it != et; ++it) {
         ExplodedNode *N = *it;
+        ProgramStateRef State = N->getState();
         const LocationContext *LCtx = N->getLocationContext();
-        SVal result = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx,
-                                                   resultType,
-                                                   currBldrCtx->blockCount());
-        ProgramStateRef state = N->getState()->BindExpr(Ex, LCtx, result);
-        Bldr2.generateNode(S, N, state);
+        SVal Result;
+        if (isa<CXXStdInitializerListExpr>(Ex)) {
+          const MemRegion *InitListRegion =
+              svalBuilder.getRegionManager().getCXXStaticTempObjectRegion(Ex);
+          Result = State->getSVal(InitListRegion);
+        } else {
+          Result = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx, resultType,
+                                                currBldrCtx->blockCount());
+        }
+        State = State->BindExpr(Ex, LCtx, Result);
+        Bldr2.generateNode(S, N, State);
       }
 
       getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);
@@ -2232,7 +2239,7 @@
       // same state.
       SVal StoredVal = State->getSVal(regionLoc->getRegion());
       if (StoredVal != Val)
-        escapes = (State == (State->bindLoc(*regionLoc, Val, LCtx)));
+        escapes = (State == (State->bindLoc(*regionLoc, Val, LCtx, false)));
     }
   }
 
Index: lib/StaticAnalyzer/Checkers/StdInitializerListChecker.cpp
===================================================================
--- /dev/null
+++ lib/StaticAnalyzer/Checkers/StdInitializerListChecker.cpp
@@ -0,0 +1,53 @@
+//===-- StdInitializerListChecker.cpp -----------------------------*- C++ -*--//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines a checker that models the API of C++11 std::initializer_list class.
+// It doesn't emit warnings, at least for now.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/AST/ExprCXX.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class StdInitializerListChecker
+    : public Checker<check::PostStmt<CXXStdInitializerListExpr>> {
+public:
+  void checkPostStmt(const CXXStdInitializerListExpr *S,
+                     CheckerContext &C) const;
+};
+} // end anonymous namespace
+
+void StdInitializerListChecker::checkPostStmt(
+    const CXXStdInitializerListExpr *S, CheckerContext &C) const {
+  QualType ElementType =
+      QualType(S->getSubExpr()->getType()->getArrayElementTypeNoTypeQual(), 0);
+
+  nonloc::LazyCompoundVal V = C.getSVal(S).castAs<nonloc::LazyCompoundVal>();
+  const MemRegion *R = V.getRegion();
+
+  const LocationContext *LCtx = C.getLocationContext();
+  SymbolRef Sym = C.getSymbolManager().getMetadataSymbol(
+      R, S, ElementType, LCtx, C.blockCount(), this);
+  Loc MetaLoc = loc::MemRegionVal(
+      C.getSValBuilder().getRegionManager().getSymbolicRegion(Sym));
+
+  SVal ListData = C.getSVal(S->getSubExpr());
+  C.addTransition(C.getState()->bindLoc(MetaLoc, ListData, LCtx, true));
+}
+
+void ento::registerStdInitializerListChecker(CheckerManager &mgr) {
+  mgr.registerChecker<StdInitializerListChecker>();
+}
Index: lib/StaticAnalyzer/Checkers/CMakeLists.txt
===================================================================
--- lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -76,6 +76,7 @@
   SimpleStreamChecker.cpp
   StackAddrEscapeChecker.cpp
   StdLibraryFunctionsChecker.cpp
+  StdInitializerListChecker.cpp
   StreamChecker.cpp
   TaintTesterChecker.cpp
   TestAfterDivZeroChecker.cpp
Index: include/clang/StaticAnalyzer/Checkers/Checkers.td
===================================================================
--- include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -272,6 +272,10 @@
   HelpText<"Checks C++ copy and move assignment operators for self assignment">,
   DescFile<"CXXSelfAssignmentChecker.cpp">;
 
+def StdInitializerListChecker : Checker<"StdInitializerList">,
+  HelpText<"Models std::initializer_list API.">,
+  DescFile<"StdInitializerListChecker.cpp">;
+
 } // end: "cplusplus"
 
 let ParentPackage = CplusplusOptIn in {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to