r324800 - [analyzer] NFC: Use CFG construction contexts instead of homemade lookahead.

Artem Dergachev via cfe-commits cfe-commits at lists.llvm.org
Fri Feb 9 18:55:08 PST 2018


Author: dergachev
Date: Fri Feb  9 18:55:08 2018
New Revision: 324800

URL: http://llvm.org/viewvc/llvm-project?rev=324800&view=rev
Log:
[analyzer] NFC: Use CFG construction contexts instead of homemade lookahead.

The analyzer was relying on peeking the next CFG element during analysis
whenever it was trying to figure out what object is being constructed
by a given constructor. This information is now available in the current CFG
element in all cases that were previously supported by the analyzer,
so no complicated lookahead is necessary anymore.

No functional change intended - the context in the CFG should for now be
available if and only if it was previously discoverable via CFG lookahead.

Differential Revision: https://reviews.llvm.org/D42721

Modified:
    cfe/trunk/include/clang/Analysis/CFG.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp

Modified: cfe/trunk/include/clang/Analysis/CFG.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/CFG.h?rev=324800&r1=324799&r2=324800&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/CFG.h (original)
+++ cfe/trunk/include/clang/Analysis/CFG.h Fri Feb  9 18:55:08 2018
@@ -162,6 +162,8 @@ public:
 
   bool isNull() const { return Trigger.isNull(); }
 
+  TriggerTy getTrigger() const { return Trigger; }
+
   const Stmt *getTriggerStmt() const {
     return Trigger.dyn_cast<Stmt *>();
   }
@@ -192,6 +194,14 @@ public:
     return static_cast<ConstructionContext *>(Data2.getPointer());
   }
 
+  QualType getType() const {
+    return cast<CXXConstructExpr>(getStmt())->getType();
+  }
+
+  ConstructionContext::TriggerTy getTrigger() const {
+    return getConstructionContext()->getTrigger();
+  }
+
   const Stmt *getTriggerStmt() const {
     return getConstructionContext()->getTriggerStmt();
   }

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h?rev=324800&r1=324799&r2=324800&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h Fri Feb  9 18:55:08 2018
@@ -665,13 +665,6 @@ private:
   /// constructing into an existing region.
   const CXXConstructExpr *findDirectConstructorForCurrentCFGElement();
 
-  /// For a CXXConstructExpr, walk forward in the current CFG block to find the
-  /// CFGElement for the DeclStmt or CXXInitCtorInitializer or CXXNewExpr which
-  /// is directly constructed by this constructor. Returns None if the current
-  /// constructor expression did not directly construct into an existing
-  /// region.
-  Optional<CFGElement> findElementDirectlyInitializedByCurrentConstructor();
-
   /// For a given constructor, look forward in the current CFG block to
   /// determine the region into which an object will be constructed by \p CE.
   /// When the lookahead fails, a temporary region is returned, and the

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp?rev=324800&r1=324799&r2=324800&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp Fri Feb  9 18:55:08 2018
@@ -114,12 +114,14 @@ ExprEngine::getRegionForConstructedObjec
   const LocationContext *LCtx = Pred->getLocationContext();
   ProgramStateRef State = Pred->getState();
 
-  // See if we're constructing an existing region by looking at the next
-  // element in the CFG.
-
-  if (auto Elem = findElementDirectlyInitializedByCurrentConstructor()) {
-    if (Optional<CFGStmt> StmtElem = Elem->getAs<CFGStmt>()) {
-      if (const CXXNewExpr *CNE = dyn_cast<CXXNewExpr>(StmtElem->getStmt())) {
+  // See if we're constructing an existing region by looking at the
+  // current construction context.
+  const NodeBuilderContext &CurrBldrCtx = getBuilderContext();
+  const CFGBlock *B = CurrBldrCtx.getBlock();
+  const CFGElement &E = (*B)[currStmtIdx];
+  if (auto CC = E.getAs<CFGConstructor>()) {
+    if (const Stmt *TriggerStmt = CC->getTriggerStmt()) {
+      if (const CXXNewExpr *CNE = dyn_cast<CXXNewExpr>(TriggerStmt)) {
         if (AMgr.getAnalyzerOptions().mayInlineCXXAllocator()) {
           // TODO: Detect when the allocator returns a null pointer.
           // Constructor shall not be called in this case.
@@ -135,7 +137,7 @@ ExprEngine::getRegionForConstructedObjec
             return MR;
           }
         }
-      } else if (auto *DS = dyn_cast<DeclStmt>(StmtElem->getStmt())) {
+      } else if (auto *DS = dyn_cast<DeclStmt>(TriggerStmt)) {
         if (const auto *Var = dyn_cast<VarDecl>(DS->getSingleDecl())) {
           if (Var->getInit() && Var->getInit()->IgnoreImplicit() == CE) {
             SVal LValue = State->getLValue(Var, LCtx);
@@ -145,11 +147,9 @@ ExprEngine::getRegionForConstructedObjec
             return LValue.getAsRegion();
           }
         }
-      } else {
-        llvm_unreachable("Unexpected directly initialized element!");
       }
-    } else if (Optional<CFGInitializer> InitElem = Elem->getAs<CFGInitializer>()) {
-      const CXXCtorInitializer *Init = InitElem->getInitializer();
+      // TODO: Consider other directly initialized elements.
+    } else if (const CXXCtorInitializer *Init = CC->getTriggerInit()) {
       assert(Init->isAnyMemberInitializer());
       const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
       Loc ThisPtr =
@@ -183,53 +183,6 @@ ExprEngine::getRegionForConstructedObjec
   return MRMgr.getCXXTempObjectRegion(CE, LCtx);
 }
 
-/// Returns true if the initializer for \Elem can be a direct
-/// constructor.
-static bool canHaveDirectConstructor(CFGElement Elem){
-  // DeclStmts and CXXCtorInitializers for fields can be directly constructed.
-
-  if (Optional<CFGStmt> StmtElem = Elem.getAs<CFGStmt>()) {
-    if (isa<DeclStmt>(StmtElem->getStmt())) {
-      return true;
-    }
-    if (isa<CXXNewExpr>(StmtElem->getStmt())) {
-      return true;
-    }
-  }
-
-  if (Elem.getKind() == CFGElement::Initializer) {
-    return true;
-  }
-
-  return false;
-}
-
-Optional<CFGElement>
-ExprEngine::findElementDirectlyInitializedByCurrentConstructor() {
-  const NodeBuilderContext &CurrBldrCtx = getBuilderContext();
-  // See if we're constructing an existing region by looking at the next
-  // element in the CFG.
-  const CFGBlock *B = CurrBldrCtx.getBlock();
-  assert(isa<CXXConstructExpr>(((*B)[currStmtIdx]).castAs<CFGStmt>().getStmt()));
-  unsigned int NextStmtIdx = currStmtIdx + 1;
-  if (NextStmtIdx >= B->size())
-    return None;
-
-  CFGElement Next = (*B)[NextStmtIdx];
-
-  // Is this a destructor? If so, we might be in the middle of an assignment
-  // to a local or member: look ahead one more element to see what we find.
-  while (Next.getAs<CFGImplicitDtor>() && NextStmtIdx + 1 < B->size()) {
-    ++NextStmtIdx;
-    Next = (*B)[NextStmtIdx];
-  }
-
-  if (canHaveDirectConstructor(Next))
-    return Next;
-
-  return None;
-}
-
 const CXXConstructExpr *
 ExprEngine::findDirectConstructorForCurrentCFGElement() {
   // Go backward in the CFG to see if the previous element (ignoring
@@ -241,7 +194,6 @@ ExprEngine::findDirectConstructorForCurr
     return nullptr;
 
   const CFGBlock *B = getBuilderContext().getBlock();
-  assert(canHaveDirectConstructor((*B)[currStmtIdx]));
 
   unsigned int PreviousStmtIdx = currStmtIdx - 1;
   CFGElement Previous = (*B)[PreviousStmtIdx];




More information about the cfe-commits mailing list