diff options
| -rw-r--r-- | clang/include/clang/Analysis/ProgramPoint.h | 24 | ||||
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/CheckerManager.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 11 | ||||
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp | 20 | ||||
| -rw-r--r-- | clang/test/Analysis/inner-pointer.cpp | 5 | ||||
| -rw-r--r-- | clang/test/Analysis/malloc-free-after-return.cpp | 4 | 
6 files changed, 55 insertions, 14 deletions
diff --git a/clang/include/clang/Analysis/ProgramPoint.h b/clang/include/clang/Analysis/ProgramPoint.h index 25ae93fae6b..016abebae89 100644 --- a/clang/include/clang/Analysis/ProgramPoint.h +++ b/clang/include/clang/Analysis/ProgramPoint.h @@ -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: diff --git a/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp b/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp index 712872a15d8..3740e4bf4df 100644 --- a/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp @@ -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);    } diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index bf2fc56b15d..063f7444eeb 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -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; diff --git a/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp index 137f9312f1f..a6f4f93f4df 100644 --- a/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ b/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -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)) diff --git a/clang/test/Analysis/inner-pointer.cpp b/clang/test/Analysis/inner-pointer.cpp index f8f6c11baef..25d7069ed34 100644 --- a/clang/test/Analysis/inner-pointer.cpp +++ b/clang/test/Analysis/inner-pointer.cpp @@ -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(); diff --git a/clang/test/Analysis/malloc-free-after-return.cpp b/clang/test/Analysis/malloc-free-after-return.cpp index 80b443d87da..cebd79a1a15 100644 --- a/clang/test/Analysis/malloc-free-after-return.cpp +++ b/clang/test/Analysis/malloc-free-after-return.cpp @@ -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}} +}  | 

