From: Jordan Rose Date: Thu, 30 May 2013 18:14:27 +0000 (+0000) Subject: [analyzer] Don't crash if a block's signature just has the return type. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b347c76054a0a4b8e6d1fce44314f6daf3294c69;p=clang [analyzer] Don't crash if a block's signature just has the return type. It is okay to declare a block without an argument list: ^ {} or ^void {}. In these cases, the BlockDecl's signature-as-written will just contain the return type, rather than the entire function type. It is unclear if this is intentional, but the analyzer shouldn't crash because of it. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@182948 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Core/CallEvent.cpp b/lib/StaticAnalyzer/Core/CallEvent.cpp index 8ac09ebb2d..dd33e014c3 100644 --- a/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -245,12 +245,17 @@ QualType CallEvent::getDeclaredResultType(const Decl *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. + // If the block is declared without an explicit argument list, the + // signature-as-written just includes the return type, not the entire + // function type. // FIXME: All blocks should have signatures-as-written, even if the return - // type is inferred. (That's signified is with a dependent result type.) + // type is inferred. (That's signified with a dependent result type.) if (const TypeSourceInfo *TSI = BD->getSignatureAsWritten()) { - const FunctionType *FT = TSI->getType()->castAs(); - if (!FT->getResultType()->isDependentType()) - return FT->getResultType(); + QualType Ty = TSI->getType(); + if (const FunctionType *FT = Ty->getAs()) + Ty = FT->getResultType(); + if (!Ty->isDependentType()) + return Ty; } return QualType(); diff --git a/test/Analysis/blocks.m b/test/Analysis/blocks.m index 2fa5a8e1a8..6d3495cd52 100644 --- a/test/Analysis/blocks.m +++ b/test/Analysis/blocks.m @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core -analyzer-store=region -fblocks -analyzer-opt-analyze-nested-blocks -verify %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core -analyzer-store=region -fblocks -analyzer-opt-analyze-nested-blocks -verify -x objective-c++ %s //===----------------------------------------------------------------------===// // The following code is reduced using delta-debugging from Mac OS X headers: @@ -13,6 +14,10 @@ void dispatch_async(dispatch_queue_t queue, dispatch_block_t block); __attribute__((visibility("default"))) __attribute__((__malloc__)) __attribute__((__warn_unused_result__)) __attribute__((__nothrow__)) dispatch_queue_t dispatch_queue_create(const char *label, dispatch_queue_attr_t attr); typedef long dispatch_once_t; void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block); +dispatch_queue_t +dispatch_queue_create(const char *label, dispatch_queue_attr_t attr); + + typedef signed char BOOL; typedef unsigned long NSUInteger; typedef struct _NSZone NSZone; @@ -56,8 +61,8 @@ void test1(NSString *format, ...) { do { if (__builtin_expect(*(&pred), ~0l) != ~0l) dispatch_once(&pred, ^{ - logQueue = dispatch_queue_create("com.mycompany.myproduct.asl", ((void*)0)); - client = asl_open(((void*)0), "com.mycompany.myproduct", 0); + logQueue = dispatch_queue_create("com.mycompany.myproduct.asl", 0); + client = asl_open(((char*)0), "com.mycompany.myproduct", 0); }); } while (0); @@ -65,7 +70,7 @@ void test1(NSString *format, ...) { __builtin_va_start(args, format); NSString *str = [[NSString alloc] initWithFormat:format arguments:args]; - dispatch_async(logQueue, ^{ asl_log(client, ((void*)0), 4, "%s", [str UTF8String]); }); + dispatch_async(logQueue, ^{ asl_log(client, ((aslmsg)0), 4, "%s", [str UTF8String]); }); [str release]; __builtin_va_end(args); @@ -123,3 +128,21 @@ void testMessaging() { }); } @end + +void testReturnVariousSignatures() { + (void)^int(){ + return 42; + }(); + + (void)^int{ + return 42; + }(); + + (void)^(){ + return 42; + }(); + + (void)^{ + return 42; + }(); +}