From c263704cb007eb95b79f37b12a8092c47146d452 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Tue, 23 Mar 2010 01:37:12 +0000 Subject: [PATCH] For forward-declared static inline functions, delay CFG-based warnings until we encounter a definition. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99243 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/AnalysisBasedWarnings.cpp | 28 +++++++++++++++++++++------- lib/Sema/AnalysisBasedWarnings.h | 3 ++- test/Sema/return.c | 3 +++ 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index a044576f5d..45b08db7e1 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -353,8 +353,14 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, // Only analyze 'static inline' functions when explicitly asked. if (!analyzeStaticInline && FD->isInlineSpecified() && - FD->getStorageClass() == FunctionDecl::Static) - return; + FD->getStorageClass() == FunctionDecl::Static) { + FD = FD->getCanonicalDecl(); + VisitFlag &visitFlag = VisitedFD[FD]; + if (visitFlag == Pending) + visitFlag = Visited; + else + return; + } } const Stmt *Body = D->getBody(); @@ -397,18 +403,26 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, if (const DeclRefExpr *DR = dyn_cast(CE->getCallee()->IgnoreParenCasts())) if (const FunctionDecl *calleeD = - dyn_cast(DR->getDecl())) + dyn_cast(DR->getDecl())) { + calleeD = calleeD->getCanonicalDecl(); if (calleeD->isInlineSpecified() && calleeD->getStorageClass() == FunctionDecl::Static) { // Have we analyzed this static inline function before? - unsigned &visited = VisitedFD[calleeD]; - if (!visited) { + VisitFlag &visitFlag = VisitedFD[calleeD]; + if (visitFlag == NotVisited) { // Mark the callee visited prior to analyzing it // so we terminate in case of recursion. - visited = 1; - IssueWarnings(DefaultPolicy, calleeD, QualType(), true); + if (calleeD->getBody()) { + visitFlag = Visited; + IssueWarnings(DefaultPolicy, calleeD, QualType(), true); + } + else { + // Delay warnings until we encounter the definition. + visitFlag = Pending; + } } } + } } } } diff --git a/lib/Sema/AnalysisBasedWarnings.h b/lib/Sema/AnalysisBasedWarnings.h index 26e973a3f4..b5db8af198 100644 --- a/lib/Sema/AnalysisBasedWarnings.h +++ b/lib/Sema/AnalysisBasedWarnings.h @@ -39,7 +39,8 @@ private: Sema &S; Policy DefaultPolicy; - llvm::DenseMap VisitedFD; + enum VisitFlag { NotVisited = 0, Visited = 1, Pending = 2 }; + llvm::DenseMap VisitedFD; public: AnalysisBasedWarnings(Sema &s); diff --git a/test/Sema/return.c b/test/Sema/return.c index fad81ad09a..fab6a82aa7 100644 --- a/test/Sema/return.c +++ b/test/Sema/return.c @@ -227,12 +227,15 @@ void test33() { // when they are used. static inline int si_has_missing_return() {} // no-warning static inline int si_has_missing_return_2() {}; // expected-warning{{control reaches end of non-void function}} +static inline int si_forward(); static inline int si_has_missing_return_3(int x) { if (x) return si_has_missing_return_3(x+1); } // expected-warning{{control may reach end of non-void function}} int test_static_inline(int x) { + si_forward(); return x ? si_has_missing_return_2() : si_has_missing_return_3(x); } +static inline int si_forward() {} // expected-warning{{control reaches end of non-void function}} -- 2.40.0