]> granicus.if.org Git - clang/commitdiff
[analyzer] Do not report use of undef on "return foo();" when the return type is...
authorAnna Zaks <ganna@apple.com>
Wed, 12 Sep 2012 22:57:40 +0000 (22:57 +0000)
committerAnna Zaks <ganna@apple.com>
Wed, 12 Sep 2012 22:57:40 +0000 (22:57 +0000)
Fixes a false positive found by analyzing LLVM code base.

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

include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
lib/StaticAnalyzer/Core/CallEvent.cpp
test/Analysis/uninit-vals-ps.c

index c403622c77c9064532575bafa5661bb2b1307239..7cbeb201c708e07e5658e91778e32f96220e6d5a 100644 (file)
@@ -293,6 +293,9 @@ public:
   /// of some kind.
   static bool isCallStmt(const Stmt *S);
 
+  /// \brief Returns the result type of a function, method declaration.
+  static QualType getDeclaredResultType(const Decl *D);
+
   // Iterator access to formal parameters and their types.
 private:
   typedef std::const_mem_fun_t<QualType, ParmVarDecl> get_type_fun;
index 7e9519968591cd615c517524b69170d35e6c3f17..33706123e85752d9471ef0fa16674c9ddf15d809 100644 (file)
@@ -16,6 +16,7 @@
 #include "ClangSACheckers.h"
 #include "clang/StaticAnalyzer/Core/Checker.h"
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
 
@@ -41,6 +42,19 @@ void ReturnUndefChecker::checkPreStmt(const ReturnStmt *RS,
   if (!C.getState()->getSVal(RetE, C.getLocationContext()).isUndef())
     return;
   
+  // "return;" is modeled to evaluate to an UndefinedValue. Allow UndefinedValue
+  // to be returned in functions returning void to support the following pattern:
+  // void foo() {
+  //  return;
+  // }
+  // void test() {
+  //   return foo();
+  // }
+  const StackFrameContext *SFC = C.getStackFrame();
+  QualType RT = CallEvent::getDeclaredResultType(SFC->getDecl());
+  if (!RT.isNull() && RT->isSpecificBuiltinType(BuiltinType::Void))
+    return;
+
   ExplodedNode *N = C.generateSink();
 
   if (!N)
index 7742d1b6b643f51a3e3634cc80509ced3a15dc25..3b4c13471b10bcf22af08ccb0593e0944e8222c8 100644 (file)
@@ -252,6 +252,16 @@ bool CallEvent::isCallStmt(const Stmt *S) {
                           || isa<CXXNewExpr>(S);
 }
 
+/// \brief Returns the result type, adjusted for references.
+QualType CallEvent::getDeclaredResultType(const Decl *D) {
+  assert(D);
+  if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(D))
+    return FD->getResultType();
+  else if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(D))
+    return MD->getResultType();
+  return QualType();
+}
+
 static void addParameterValuesToBindings(const StackFrameContext *CalleeCtx,
                                          CallEvent::BindingsTy &Bindings,
                                          SValBuilder &SVB,
index f3011570a85a9641abf72ea72b514937189a3b10..09736ef1e35e07e7a610d8fe784fee0dc16466b8 100644 (file)
@@ -122,3 +122,15 @@ int pr4631_f1_b(void)
   return x;  // no-warning
 }
 
+void foo_radar12278788() { return; }
+void test_radar12278788() {
+  return foo_radar12278788(); // no-warning
+}
+
+void foo_radar12278788_fp() { return; }
+typedef int (*RetIntFuncType)();
+typedef void (*RetVoidFuncType)();
+int test_radar12278788_FP() {
+  RetVoidFuncType f = foo_radar12278788_fp;
+  return ((RetIntFuncType)f)(); //expected-warning {{Undefined or garbage value returned to caller}}
+}