]> granicus.if.org Git - clang/commitdiff
[analyzer] Associate diagnostics created in checkEndFunction with a return statement...
authorGeorge Karpenkov <ekarpenkov@apple.com>
Fri, 21 Sep 2018 20:36:41 +0000 (20:36 +0000)
committerGeorge Karpenkov <ekarpenkov@apple.com>
Fri, 21 Sep 2018 20:36:41 +0000 (20:36 +0000)
If not possible, use the last line of the declaration, as before.

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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@342768 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Analysis/ProgramPoint.h
lib/StaticAnalyzer/Core/CheckerManager.cpp
lib/StaticAnalyzer/Core/ExprEngine.cpp
lib/StaticAnalyzer/Core/PathDiagnostic.cpp
test/Analysis/inner-pointer.cpp
test/Analysis/malloc-free-after-return.cpp

index 25ae93fae6b840a12efa613d779198e63833d987..016abebae894d41345312a8aef6885f8a69f3203 100644 (file)
@@ -80,6 +80,7 @@ public:
               CallEnterKind,
               CallExitBeginKind,
               CallExitEndKind,
+              FunctionExitKind,
               PreImplicitCallKind,
               PostImplicitCallKind,
               MinImplicitCallKind = PreImplicitCallKind,
@@ -329,6 +330,29 @@ private:
   }
 };
 
+class FunctionExitPoint : public ProgramPoint {
+public:
+  explicit FunctionExitPoint(const ReturnStmt *S,
+                             const LocationContext *LC,
+                             const ProgramPointTag *tag = nullptr)
+      : ProgramPoint(S, FunctionExitKind, LC, tag) {}
+
+  const CFGBlock *getBlock() const {
+    return &getLocationContext()->getCFG()->getExit();
+  }
+
+  const ReturnStmt *getStmt() const {
+    return reinterpret_cast<const ReturnStmt *>(getData1());
+  }
+
+private:
+  friend class ProgramPoint;
+  FunctionExitPoint() = default;
+  static bool isKind(const ProgramPoint &Location) {
+    return Location.getKind() == FunctionExitKind;
+  }
+};
+
 // PostCondition represents the post program point of a branch condition.
 class PostCondition : public PostStmt {
 public:
index 712872a15d8a07275822a55bda960ec9e44c129e..3740e4bf4dfe6bd26c67f939dc8fb71100385164 100644 (file)
@@ -446,9 +446,8 @@ void CheckerManager::runCheckersForEndFunction(NodeBuilderContext &BC,
   // autotransition for it.
   NodeBuilder Bldr(Pred, Dst, BC);
   for (const auto checkFn : EndFunctionCheckers) {
-    const ProgramPoint &L = BlockEntrance(BC.Block,
-                                          Pred->getLocationContext(),
-                                          checkFn.Checker);
+    const ProgramPoint &L =
+        FunctionExitPoint(RS, Pred->getLocationContext(), checkFn.Checker);
     CheckerContext C(Bldr, Eng, Pred, L);
     checkFn(RS, C);
   }
index bf2fc56b15d6a07a12dec4ae3459a7070c08f64c..063f7444eebc03cb0114a942af0b8cc1a2984b7e 100644 (file)
@@ -2984,6 +2984,17 @@ struct DOTGraphTraits<ExplodedGraph*> : public DefaultDOTGraphTraits {
           << Loc.castAs<BlockEntrance>().getBlock()->getBlockID();
       break;
 
+    case ProgramPoint::FunctionExitKind: {
+      auto FEP = Loc.getAs<FunctionExitPoint>();
+      Out << "Function Exit: B"
+          << FEP->getBlock()->getBlockID();
+      if (const ReturnStmt *RS = FEP->getStmt()) {
+        Out << "\\l Return: S" << RS->getID(Context) << "\\l";
+        RS->printPretty(Out, /*helper=*/nullptr, Context.getPrintingPolicy(),
+                       /*Indentation=*/2, /*NewlineSymbol=*/"\\l");
+      }
+      break;
+    }
     case ProgramPoint::BlockExitKind:
       assert(false);
       break;
index 137f9312f1f30af06a06a65dc2395a53fa3124b4..a6f4f93f4df03117a33a7b99bb6cb345853b5a2b 100644 (file)
@@ -774,18 +774,20 @@ const Stmt *PathDiagnosticLocation::getStmt(const ExplodedNode *N) {
   }
   // Otherwise, see if the node's program point directly points to a statement.
   ProgramPoint P = N->getLocation();
-  if (Optional<StmtPoint> SP = P.getAs<StmtPoint>())
+  if (auto SP = P.getAs<StmtPoint>())
     return SP->getStmt();
-  if (Optional<BlockEdge> BE = P.getAs<BlockEdge>())
+  if (auto BE = P.getAs<BlockEdge>())
     return BE->getSrc()->getTerminator();
-  if (Optional<CallEnter> CE = P.getAs<CallEnter>())
+  if (auto CE = P.getAs<CallEnter>())
     return CE->getCallExpr();
-  if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>())
+  if (auto CEE = P.getAs<CallExitEnd>())
     return CEE->getCalleeContext()->getCallSite();
-  if (Optional<PostInitializer> PIPP = P.getAs<PostInitializer>())
+  if (auto PIPP = P.getAs<PostInitializer>())
     return PIPP->getInitializer()->getInit();
-  if (Optional<CallExitBegin> CEB = P.getAs<CallExitBegin>())
+  if (auto CEB = P.getAs<CallExitBegin>())
     return CEB->getReturnStmt();
+  if (auto FEP = P.getAs<FunctionExitPoint>())
+    return FEP->getStmt();
 
   return nullptr;
 }
@@ -822,17 +824,21 @@ PathDiagnosticLocation
                                           const SourceManager &SM) {
   assert(N && "Cannot create a location with a null node.");
   const Stmt *S = getStmt(N);
+  const LocationContext *LC = N->getLocationContext();
 
   if (!S) {
     // If this is an implicit call, return the implicit call point location.
     if (Optional<PreImplicitCall> PIE = N->getLocationAs<PreImplicitCall>())
       return PathDiagnosticLocation(PIE->getLocation(), SM);
+    if (auto FE = N->getLocationAs<FunctionExitPoint>()) {
+      if (const ReturnStmt *RS = FE->getStmt())
+        return PathDiagnosticLocation::createBegin(RS, SM, LC);
+    }
     S = getNextStmt(N);
   }
 
   if (S) {
     ProgramPoint P = N->getLocation();
-    const LocationContext *LC = N->getLocationContext();
 
     // For member expressions, return the location of the '.' or '->'.
     if (const auto *ME = dyn_cast<MemberExpr>(S))
index f8f6c11baef7db76b8ef22a63fcb8b38d436f6a6..25d7069ed346cca22428a8658deb905f6437632a 100644 (file)
@@ -412,8 +412,9 @@ const char *escape_via_return_local() {
   std::string s;
   return s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
                     // expected-note@-1 {{Inner buffer of 'std::string' deallocated by call to destructor}}
-} // expected-warning {{Inner pointer of container used after re/deallocation}}
-// expected-note@-1 {{Inner pointer of container used after re/deallocation}}
+                    // expected-warning@-2 {{Inner pointer of container used after re/deallocation}}
+                    // expected-note@-3 {{Inner pointer of container used after re/deallocation}}
+}
 
 
 char *c();
index 80b443d87dadcdf2ec8e92cf136d1609d1863397..cebd79a1a15e034f6710d7f2bfe6668befb6b6bd 100644 (file)
@@ -17,5 +17,5 @@ int *freeAfterReturnTemp() {
 
 int *freeAfterReturnLocal() {
   S X;
-  return X.getData();
-} // expected-warning {{Use of memory after it is freed}}
+  return X.getData(); // expected-warning {{Use of memory after it is freed}}
+}