[cfe-commits] [PATCH] Treat "int (^x)()" as "int (^x)(void)" instead of a K&R style prototype

Eli Friedman eli.friedman at gmail.com
Sun May 31 04:25:39 PDT 2009


Patch per subject; this seems like the right thing to do, considering
the spec and the comment for ASTContext::typesAreBlockCompatible.
Also, the current rules for K&R-style block pointers are simply
confusing.  I'm running it by the list first to make sure this isn't
likely to break common usages of blocks.

-Eli
-------------- next part --------------
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp	(revision 72663)
+++ lib/Sema/SemaType.cpp	(working copy)
@@ -300,6 +300,9 @@
       }
       Diag(Loc, diag::warn_typecheck_function_qualifiers)
         << Result << DS.getSourceRange();
+      // Strip off the qualifiers so we don't introduce any strange behavior.
+      TypeQuals &= ~QualType::Const;
+      TypeQuals &= ~QualType::Volatile;
     }
     
     // C++ [dcl.ref]p1:
@@ -674,12 +677,17 @@
       // If blocks are disabled, emit an error.
       if (!LangOpts.Blocks)
         Diag(DeclType.Loc, diag::err_blocks_disable);
-        
-      if (!T.getTypePtr()->isFunctionType())
+
+      if (!T->isFunctionType()) {
         Diag(D.getIdentifierLoc(), diag::err_nonfunction_block_type);
-      else
+      } else {
+        // "int (^x)()" takes zero arguments.
+        if (const FunctionNoProtoType* FNPT = T->getAsFunctionNoProtoType()) {
+          T = Context.getFunctionType(FNPT->getResultType(), 0, 0, false, 0);
+        }
         T = (Context.getBlockPointerType(T)
              .getQualifiedType(DeclType.Cls.TypeQuals));
+      }
       break;
     case DeclaratorChunk::Pointer:
       // Verify that we're not building a pointer to pointer to function with
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp	(revision 72663)
+++ lib/Sema/SemaExpr.cpp	(working copy)
@@ -5215,7 +5215,7 @@
 
   QualType BlockTy;
   if (!BSI->hasPrototype)
-    BlockTy = Context.getFunctionNoProtoType(RetTy);
+    BlockTy = Context.getFunctionType(RetTy, 0, 0, false, 0);
   else
     BlockTy = Context.getFunctionType(RetTy, ArgTypes.data(), ArgTypes.size(),
                                       BSI->isVariadic, 0);
Index: test/SemaObjC/blocks.m
===================================================================
--- test/SemaObjC/blocks.m	(revision 72663)
+++ test/SemaObjC/blocks.m	(working copy)
@@ -18,7 +18,7 @@
 
 void bar4(id(^)());
 void foo4(id (^objectCreationBlock)(int)) {
-    return bar4(objectCreationBlock);
+    return bar4(objectCreationBlock); // expected-error {{incompatible block pointer types passing 'id (^)(int)', expected 'id (^)(void)'}}
 }
 
 void bar5(id(^)(void));
@@ -28,7 +28,7 @@
 
 void bar6(id(^)(int));
 void foo6(id (^objectCreationBlock)()) {
-    return bar6(objectCreationBlock); // expected-error {{incompatible block pointer types passing 'id (^)()', expected 'id (^)(int)'}}
+    return bar6(objectCreationBlock); // expected-error {{incompatible block pointer types passing 'id (^)(void)', expected 'id (^)(int)'}}
 }
 
 void foo7(id (^x)(int)) {
Index: test/Sema/block-call.c
===================================================================
--- test/Sema/block-call.c	(revision 72663)
+++ test/Sema/block-call.c	(working copy)
@@ -7,13 +7,13 @@
   int (*FPL) (int) = FP; // C doesn't consider this an error.
   
   // For Blocks, the ASTContext::typesAreBlockCompatible() makes sure this is an error.
-  int (^PFR) (int) = IFP;	// expected-error {{incompatible block pointer types initializing 'int (^)()', expected 'int (^)(int)'}}
+  int (^PFR) (int) = IFP;	// expected-error {{incompatible block pointer types initializing 'int (^)(void)', expected 'int (^)(int)'}}
 	PFR = II;	// OK
 
-	int (^IFP) () = PFR;
+	int (^IFP) () = PFR; // expected-error {{incompatible block pointer types initializing 'int (^)(int)', expected 'int (^)(void)'}}
 
 
-	const int (^CIC) () = IFP; // expected-error {{incompatible block pointer types initializing 'int (^)()', expected 'int const (^)()'}}
+	const int (^CIC) () = IFP; // expected-error {{incompatible block pointer types initializing 'int (^)(void)', expected 'int const (^)(void)'}}
 
 
 	const int (^CICC) () = CIC;
@@ -22,7 +22,7 @@
 
 	int * const (^IPCC1) () = IPCC; 
 
-	int * (^IPCC2) () = IPCC;	// expected-error {{incompatible block pointer types initializing 'int *const (^)()', expected 'int *(^)()'}}
+	int * (^IPCC2) () = IPCC;	// expected-error {{incompatible block pointer types initializing 'int *const (^)(void)', expected 'int *(^)(void)'}}
 
 	int (^IPCC3) (const int) = PFR;
 
@@ -35,11 +35,11 @@
 	int (^IPCC6) (int, char (^CArg) (float))  = IPCC4; // expected-error {{incompatible block pointer types initializing 'int (^)(int, char (^)(double))', expected 'int (^)(int, char (^)(float))'}}
 
 	IPCC2 = 0;
-	IPCC2 = 1; // expected-error {{invalid conversion assigning integer 'int', expected block pointer 'int *(^)()'}}
+	IPCC2 = 1; // expected-error {{invalid conversion assigning integer 'int', expected block pointer 'int *(^)(void)'}}
 	int (^x)() = 0;
-	int (^y)() = 3;   // expected-error {{invalid conversion initializing integer 'int', expected block pointer 'int (^)()'}}
+	int (^y)() = 3;   // expected-error {{invalid conversion initializing integer 'int', expected block pointer 'int (^)(void)'}}
 	int a = 1;
-	int (^z)() = a+4;   // expected-error {{invalid conversion initializing integer 'int', expected block pointer 'int (^)()'}}
+	int (^z)() = a+4;   // expected-error {{invalid conversion initializing integer 'int', expected block pointer 'int (^)(void)'}}
 }
 
 int blah() {
Index: test/Sema/block-args.c
===================================================================
--- test/Sema/block-args.c	(revision 72663)
+++ test/Sema/block-args.c	(working copy)
@@ -18,7 +18,7 @@
   ^{return 1;}();
   ^{return 2;}(arg); // expected-error {{too many arguments to block call}}
   ^(void){return 3;}(1); // expected-error {{too many arguments to block call}}
-  ^(){return 4;}(arg);   // C style (...), ok.
+  ^(){return 4;}(arg); // expected-error {{too many arguments to block call}}
   ^(int x, ...){return 5;}(arg, arg);   // Explicit varargs, ok.
 }
 
Index: test/Sema/block-misc.c
===================================================================
--- test/Sema/block-misc.c	(revision 72663)
+++ test/Sema/block-misc.c	(working copy)
@@ -144,7 +144,7 @@
 
 void (^test15f)(void);
 void test15() {
-  foo(^{ return LESS; });	// expected-error {{incompatible block pointer types passing 'int (^)(void)', expected 'long (^)()'}}
+  foo(^{ return LESS; });	// expected-error {{incompatible block pointer types passing 'int (^)(void)', expected 'long (^)(void)'}}
 }
 
 __block int test16i;  // expected-error {{__block attribute not allowed, only allowed on local variables}}
@@ -165,7 +165,7 @@
 
   f(1 ? bp : vp);
   f(1 ? vp : bp);
-  f(1 ? bp : bp1); // expected-error {{incompatible operand types ('void (^)(int)' and 'void (^)()')}}
+  f(1 ? bp : bp1); // expected-error {{incompatible operand types ('void (^)(int)' and 'void (^)(void)')}}
   (void)(bp > rp); // expected-error {{invalid operands}}
   (void)(bp > 0); // expected-error {{invalid operands}}
   (void)(bp > bp); // expected-error {{invalid operands}}
Index: test/CodeGen/blocks.c
===================================================================
--- test/CodeGen/blocks.c	(revision 72663)
+++ test/CodeGen/blocks.c	(working copy)
@@ -2,7 +2,7 @@
 void (^f)(void) = ^{};
 
 // rdar://6768379
-int f0(int (^a0)()) {
+int f0(int (^a0)(int, int, int)) {
   return a0(1, 2, 3);
 }
 


More information about the cfe-commits mailing list