]> granicus.if.org Git - clang/commitdiff
For forward-declared static inline functions, delay CFG-based warnings until we
authorTed Kremenek <kremenek@apple.com>
Tue, 23 Mar 2010 01:37:12 +0000 (01:37 +0000)
committerTed Kremenek <kremenek@apple.com>
Tue, 23 Mar 2010 01:37:12 +0000 (01:37 +0000)
encounter a definition.

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

lib/Sema/AnalysisBasedWarnings.cpp
lib/Sema/AnalysisBasedWarnings.h
test/Sema/return.c

index a044576f5d7e06de3cdf12e47fdec71c91d7558f..45b08db7e124945f2e84d71cd6312b5ca2e97335 100644 (file)
@@ -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;
+                    }
                   }
                 }
+              }
       }
     }
   }
index 26e973a3f40496db25ae58414c86b5990406a1e4..b5db8af198f48324ea24004689b0889cbaff0888 100644 (file)
@@ -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);
index fad81ad09ab372817bb164225e562182b7f3929f..fab6a82aa7042be0bc16c29e53dd115a2fcad002 100644 (file)
@@ -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}}