OpenCLKernelMetadata->addOperand(kernelMDNode);
}
+/// Determine whether the function F ends with a return stmt.
+static bool endsWithReturn(const Decl* F) {
+ const Stmt *Body = nullptr;
+ if (auto *FD = dyn_cast_or_null<FunctionDecl>(F))
+ Body = FD->getBody();
+ else if (auto *OMD = dyn_cast_or_null<ObjCMethodDecl>(F))
+ Body = OMD->getBody();
+
+ if (auto *CS = dyn_cast_or_null<CompoundStmt>(Body)) {
+ auto LastStmt = CS->body_rbegin();
+ if (LastStmt != CS->body_rend())
+ return isa<ReturnStmt>(*LastStmt);
+ }
+ return false;
+}
+
void CodeGenFunction::StartFunction(GlobalDecl GD,
QualType RetTy,
llvm::Function *Fn,
if (RetTy->isVoidType()) {
// Void type; nothing to return.
ReturnValue = 0;
+
+ // Count the implicit return.
+ if (!endsWithReturn(D))
+ ++NumReturnExprs;
} else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect &&
!hasScalarEvaluationKind(CurFnInfo->getReturnType())) {
// Indirect aggregate return; emit returned value directly into sret slot.
// CHECK: @objc_msgSend{{.*}} !dbg ![[MSG7:[0-9]+]]
// CHECK: ret {{.*}} !dbg ![[RET7:[0-9]+]]
+// CHECK: define {{.*}}testCleanupVoid
+// CHECK: icmp ne {{.*}}!dbg ![[SKIP1:[0-9]+]]
+// CHECK-NEXT: br {{.*}}, label %[[CLEANUP:.*]], label
+// CHECK: [[CLEANUP]]:
+// CHECK-NEXT: !dbg ![[RET8:[0-9]+]]
+// CHECK: @objc_storeStrong{{.*}}, !dbg ![[ARC8:[0-9]+]]
+// CHECK: ret {{.*}} !dbg ![[RET8]]
+
+typedef signed char BOOL;
@interface NSObject
+ (id)alloc;
return 1;
}
+- (void)testCleanupVoid:(BOOL)skip withDelegate: (AppDelegate *) delegate {
+ static BOOL skip_all;
+ // CHECK: ![[SKIP1]] = metadata !{i32 [[@LINE+1]], i32 0,
+ if (!skip_all) {
+ if (!skip) {
+ return;
+ }
+ NSString *s = @"bar";
+ if (!skip) {
+ [delegate testVoid :s];
+ }
+ }
+ // CHECK: ![[RET8]] = metadata !{i32 [[@LINE+2]], i32 0,
+ // CHECK: ![[ARC8]] = metadata !{i32 [[@LINE+1]], i32 0,
+}
+
@end