diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/lib/Sema/AnalysisBasedWarnings.cpp | 28 | ||||
| -rw-r--r-- | clang/lib/Sema/AnalysisBasedWarnings.h | 3 | ||||
| -rw-r--r-- | clang/test/Sema/return.c | 3 | 
3 files changed, 26 insertions, 8 deletions
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index a044576f5d7..45b08db7e12 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/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<DeclRefExpr>(CE->getCallee()->IgnoreParenCasts()))                if (const FunctionDecl *calleeD = -                  dyn_cast<FunctionDecl>(DR->getDecl())) +                  dyn_cast<FunctionDecl>(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/clang/lib/Sema/AnalysisBasedWarnings.h b/clang/lib/Sema/AnalysisBasedWarnings.h index 26e973a3f40..b5db8af198f 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.h +++ b/clang/lib/Sema/AnalysisBasedWarnings.h @@ -39,7 +39,8 @@ private:    Sema &S;    Policy DefaultPolicy; -  llvm::DenseMap<const FunctionDecl*, unsigned> VisitedFD; +  enum VisitFlag { NotVisited = 0, Visited = 1, Pending = 2 }; +  llvm::DenseMap<const FunctionDecl*, VisitFlag> VisitedFD;  public:    AnalysisBasedWarnings(Sema &s); diff --git a/clang/test/Sema/return.c b/clang/test/Sema/return.c index fad81ad09ab..fab6a82aa70 100644 --- a/clang/test/Sema/return.c +++ b/clang/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}}  | 

