summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2013-04-17 18:03:48 +0000
committerJordan Rose <jordan_rose@apple.com>2013-04-17 18:03:48 +0000
commitadd14263ea96e96c9cb6c96786ccffb7e242b87f (patch)
treef5b0c1803a190cb80b209b793fa1c2effb09fc56
parentc7400488b947f9f13de99f00932c6eb0b5d22fa8 (diff)
downloadbcm5719-llvm-add14263ea96e96c9cb6c96786ccffb7e242b87f.tar.gz
bcm5719-llvm-add14263ea96e96c9cb6c96786ccffb7e242b87f.zip
[analyzer] Don't warn for returning void expressions in void blocks.
This was slightly tricky because BlockDecls don't currently store an inferred return type. However, we can rely on the fact that blocks with inferred return types will have return statements that match the inferred type. <rdar://problem/13665798> llvm-svn: 179699
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp13
-rw-r--r--clang/lib/StaticAnalyzer/Core/CallEvent.cpp14
-rw-r--r--clang/test/Analysis/uninit-vals-ps.c17
3 files changed, 40 insertions, 4 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
index 7a5d9936010..ed96c401a7a 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
@@ -55,8 +55,17 @@ void ReturnUndefChecker::checkPreStmt(const ReturnStmt *RS,
// void test() {
// return foo();
// }
- if (RT.isNull() || !RT->isVoidType())
- emitUndef(C, RetE);
+ if (!RT.isNull() && RT->isVoidType())
+ return;
+
+ // Not all blocks have explicitly-specified return types; if the return type
+ // is not available, but the return value expression has 'void' type, assume
+ // Sema already checked it.
+ if (RT.isNull() && isa<BlockDecl>(SFC->getDecl()) &&
+ RetE->getType()->isVoidType())
+ return;
+
+ emitUndef(C, RetE);
return;
}
diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index 45b2e219d9e..dfd20b8b332 100644
--- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -239,8 +239,20 @@ 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))
+ if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(D))
return MD->getResultType();
+ if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
+ // Blocks are difficult because the return type may not be stored in the
+ // BlockDecl itself. The AST should probably be enhanced, but for now we
+ // just do what we can.
+ QualType Ty = BD->getSignatureAsWritten()->getType();
+ if (const FunctionType *FT = Ty->getAs<FunctionType>())
+ if (!FT->getResultType()->isDependentType())
+ return FT->getResultType();
+
+ return QualType();
+ }
+
return QualType();
}
diff --git a/clang/test/Analysis/uninit-vals-ps.c b/clang/test/Analysis/uninit-vals-ps.c
index 09736ef1e35..ad40b15502e 100644
--- a/clang/test/Analysis/uninit-vals-ps.c
+++ b/clang/test/Analysis/uninit-vals-ps.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store=region -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store=region -fblocks -verify %s
struct FPRec {
void (*my_func)(int * x);
@@ -122,6 +122,8 @@ int pr4631_f1_b(void)
return x; // no-warning
}
+// <rdar://problem/12278788> - FP when returning a void-valued expression from
+// a void function...or block.
void foo_radar12278788() { return; }
void test_radar12278788() {
return foo_radar12278788(); // no-warning
@@ -134,3 +136,16 @@ int test_radar12278788_FP() {
RetVoidFuncType f = foo_radar12278788_fp;
return ((RetIntFuncType)f)(); //expected-warning {{Undefined or garbage value returned to caller}}
}
+
+void rdar13665798() {
+ ^() {
+ return foo_radar12278788(); // no-warning
+ }();
+ ^void() {
+ return foo_radar12278788(); // no-warning
+ }();
+ ^int() {
+ RetVoidFuncType f = foo_radar12278788_fp;
+ return ((RetIntFuncType)f)(); //expected-warning {{Undefined or garbage value returned to caller}}
+ }();
+}
OpenPOWER on IntegriCloud