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>
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@179699
91177308-0d34-0410-b5e6-
96231b3b80d8
// 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;
}
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();
}
-// 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);
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
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}}
+ }();
+}