Author: george.karpenkov Date: Fri Sep 21 13:36:41 2018 New Revision: 342768
URL: http://llvm.org/viewvc/llvm-project?rev=342768&view=rev Log: [analyzer] Associate diagnostics created in checkEndFunction with a return statement, if possible If not possible, use the last line of the declaration, as before. Differential Revision: https://reviews.llvm.org/D52326 Modified: cfe/trunk/include/clang/Analysis/ProgramPoint.h cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp cfe/trunk/test/Analysis/inner-pointer.cpp cfe/trunk/test/Analysis/malloc-free-after-return.cpp Modified: cfe/trunk/include/clang/Analysis/ProgramPoint.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/ProgramPoint.h?rev=342768&r1=342767&r2=342768&view=diff ============================================================================== --- cfe/trunk/include/clang/Analysis/ProgramPoint.h (original) +++ cfe/trunk/include/clang/Analysis/ProgramPoint.h Fri Sep 21 13:36:41 2018 @@ -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: Modified: cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp?rev=342768&r1=342767&r2=342768&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp Fri Sep 21 13:36:41 2018 @@ -446,9 +446,8 @@ void CheckerManager::runCheckersForEndFu // 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); } Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=342768&r1=342767&r2=342768&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Fri Sep 21 13:36:41 2018 @@ -2984,6 +2984,17 @@ struct DOTGraphTraits<ExplodedGraph*> : << 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; Modified: cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp?rev=342768&r1=342767&r2=342768&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp Fri Sep 21 13:36:41 2018 @@ -774,18 +774,20 @@ const Stmt *PathDiagnosticLocation::getS } // 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)) Modified: cfe/trunk/test/Analysis/inner-pointer.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/inner-pointer.cpp?rev=342768&r1=342767&r2=342768&view=diff ============================================================================== --- cfe/trunk/test/Analysis/inner-pointer.cpp (original) +++ cfe/trunk/test/Analysis/inner-pointer.cpp Fri Sep 21 13:36:41 2018 @@ -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(); Modified: cfe/trunk/test/Analysis/malloc-free-after-return.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc-free-after-return.cpp?rev=342768&r1=342767&r2=342768&view=diff ============================================================================== --- cfe/trunk/test/Analysis/malloc-free-after-return.cpp (original) +++ cfe/trunk/test/Analysis/malloc-free-after-return.cpp Fri Sep 21 13:36:41 2018 @@ -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}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits