manmanren updated this revision to Diff 52316.
manmanren added a comment.
Addressing review comments.
http://reviews.llvm.org/D18567
Files:
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaType.cpp
test/SemaObjC/block-omitted-return-type.m
test/SemaOpenCL/invalid-block.cl
Index: test/SemaObjC/block-omitted-return-type.m
===================================================================
--- /dev/null
+++ test/SemaObjC/block-omitted-return-type.m
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 %s -fblocks -verify -fsyntax-only
+
+@interface NSObject
+@end
+
+@interface Test : NSObject
+- (void)test;
+@end
+
+@implementation Test
+- (void)test
+{
+ void (^simpleBlock)() = ^ _Nonnull { //expected-warning {{attribute '_Nonnull' ignored, because it cannot be applied to omitted return type}}
+ return;
+ };
+ void (^simpleBlock2)() = ^ _Nonnull void { //expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'void'}}
+ return;
+ };
+ void (^simpleBlock3)() = ^ _Nonnull (void) { //expected-warning {{attribute '_Nonnull' ignored, because it cannot be applied to omitted return type}}
+ return;
+ };
+
+ void (^simpleBlock4)() = ^ const { //expected-warning {{'const' qualifier on omitted return type '<dependent type>' has no effect}}
+ return;
+ };
+ void (^simpleBlock5)() = ^ const void { //expected-error {{incompatible block pointer types initializing 'void (^)()' with an expression of type 'const void (^)(void)'}}
+ return;
+ };
+ void (^simpleBlock6)() = ^ const (void) { //expected-warning {{'const' qualifier on omitted return type '<dependent type>' has no effect}}
+ return;
+ };
+ void (^simpleBlock7)() = ^ _Nonnull __attribute__((align_value(128))) _Nullable const (void) { // expected-warning {{attribute '_Nullable' ignored, because it cannot be applied to omitted return type}} \
+ // expected-warning {{attribute '_Nonnull' ignored, because it cannot be applied to omitted return type}} \
+ // expected-warning {{'const' qualifier on omitted return type '<dependent type>' has no effect}} \
+ // expected-warning {{'align_value' attribute only applies to variables and typedefs}}
+ return;
+ };
+ void (^simpleBlock9)() = ^ __attribute__ ((align_value(128))) _Nonnull const (void) { // expected-warning {{attribute '_Nonnull' ignored, because it cannot be applied to omitted return type}} \
+ // expected-warning {{'const' qualifier on omitted return type '<dependent type>' has no effect}} \
+ // expected-warning {{'align_value' attribute only applies to variables and typedefs}}
+ return;
+ };
+}
+@end
Index: test/SemaOpenCL/invalid-block.cl
===================================================================
--- test/SemaOpenCL/invalid-block.cl
+++ test/SemaOpenCL/invalid-block.cl
@@ -4,16 +4,15 @@
// All blocks declarations must be const qualified and initialized.
void f1() {
- int (^bl1)() = ^() {}; // expected-error{{invalid block variable declaration - must be const qualified}}
+ int (^bl1)() = ^() {return 1;}; // expected-error{{invalid block variable declaration - must be const qualified}}
int (^const bl2)(); // expected-error{{invalid block variable declaration - must be initialized}}
- int (^const bl3)() = ^const(){
- };
+ int (^const bl3)() = ^(){return 1;};
}
// A block with extern storage class is not allowed.
-extern int (^const bl)() = ^const(){}; // expected-error{{invalid block variable declaration - using 'extern' storage class is disallowed}}
+extern int (^const bl)() = ^(){return 1;}; // expected-error{{invalid block variable declaration - using 'extern' storage class is disallowed}}
void f2() {
- extern int (^const bl)() = ^const(){}; // expected-error{{invalid block variable declaration - using 'extern' storage class is disallowed}}
+ extern int (^const bl)() = ^(){return 1;}; // expected-error{{invalid block variable declaration - using 'extern' storage class is disallowed}}
}
// A block cannot be the return value of a function.
@@ -29,22 +28,22 @@
}
// A block with variadic argument is not allowed.
-int (^const bl)(int, ...) = ^const int(int I, ...) { // expected-error {{invalid block prototype, variadic arguments are not allowed in OpenCL}}
+int (^const bl)(int, ...) = ^int(int I, ...) { // expected-error {{invalid block prototype, variadic arguments are not allowed in OpenCL}}
return 0;
};
// A block can't be used to declare an array
typedef int (^const bl1_t)(int);
void f5(int i) {
- bl1_t bl1 = ^const(int i) {return 1;};
- bl1_t bl2 = ^const(int i) {return 2;};
+ bl1_t bl1 = ^(int i) {return 1;};
+ bl1_t bl2 = ^(int i) {return 2;};
bl1_t arr[] = {bl1, bl2}; // expected-error {{array of 'bl1_t' (aka 'int (^const)(int)') type is invalid in OpenCL}}
int tmp = i ? bl1(i) // expected-error {{block type cannot be used as expression in ternary expression in OpenCL}}
: bl2(i); // expected-error {{block type cannot be used as expression in ternary expression in OpenCL}}
}
void f6(bl1_t * bl_ptr) {
- bl1_t bl = ^const(int i) {return 1;};
+ bl1_t bl = ^(int i) {return 1;};
bl1_t *p = &bl; // expected-error {{invalid argument type 'bl1_t' (aka 'int (^const)(int)') to unary expression}}
bl = *bl_ptr; // expected-error {{dereferencing pointer of type '__generic bl1_t *' (aka 'int (^const __generic *)(int)') is not allowed in OpenCL}}
}
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -734,6 +734,7 @@
// it; they probably didn't mean to specify a redundant qualifier.
typedef std::pair<DeclSpec::TQ, SourceLocation> QualLoc;
for (QualLoc Qual : {QualLoc(DeclSpec::TQ_const, DS.getConstSpecLoc()),
+ QualLoc(DeclSpec::TQ_restrict, DS.getRestrictSpecLoc()),
QualLoc(DeclSpec::TQ_volatile, DS.getVolatileSpecLoc()),
QualLoc(DeclSpec::TQ_atomic, DS.getAtomicSpecLoc())}) {
if (!(RemoveTQs & Qual.first))
@@ -1552,6 +1553,37 @@
break;
}
+ // Warn if we see type attributes for omitted return type on a block literal.
+ if (isOmittedBlockReturnType(declarator)) {
+ AttributeList *&attrs =
+ declarator.getMutableDeclSpec().getAttributes().getListRef();
+ AttributeList *cur = attrs, *prev = nullptr;
+ while (cur) {
+ AttributeList &attr = *cur;
+ // Skip attributes that were marked to be invalid or non-type
+ // attributes.
+ if (attr.isInvalid() || !attr.isTypeAttr()) {
+ prev = cur;
+ cur = cur->getNext();
+ continue;
+ }
+ S.Diag(attr.getLoc(),
+ diag::warn_block_literal_attributes_on_omitted_return_type)
+ << attr.getName();
+
+ // Remove cur from the list.
+ if (attrs == cur) {
+ attrs = attr.getNext();
+ prev = nullptr;
+ cur = cur->getNext();
+ continue;
+ }
+ prev->setNext(attr.getNext());
+ prev = cur;
+ cur = cur->getNext();
+ }
+ }
+
// Handle complex types.
if (DS.getTypeSpecComplex() == DeclSpec::TSC_complex) {
if (S.getLangOpts().Freestanding)
@@ -1586,6 +1618,12 @@
// Apply const/volatile/restrict qualifiers to T.
if (unsigned TypeQuals = DS.getTypeQualifiers()) {
+ // Warn if we see type qualifiers for omitted return type on a block literal.
+ if (isOmittedBlockReturnType(declarator)) {
+ diagnoseAndRemoveTypeQualifiers(S, DS, TypeQuals, Result, (unsigned)-1,
+ diag::warn_block_literal_qualifiers_on_omitted_return_type);
+ }
+
// Warn about CV qualifiers on function types.
// C99 6.7.3p8:
// If the specification of a function type includes any type qualifiers,
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -8386,4 +8386,12 @@
"parameterized class %0 already conforms to the protocols listed; did you "
"forget a '*'?">, InGroup<ObjCProtocolQualifiers>;
+def warn_block_literal_attributes_on_omitted_return_type : Warning<
+ "attribute %0 ignored, because it cannot be applied to omitted return type">,
+ InGroup<IgnoredAttributes>;
+
+def warn_block_literal_qualifiers_on_omitted_return_type : Warning<
+ "'%0' qualifier on omitted return type %1 has no effect">,
+ InGroup<IgnoredQualifiers>;
+
} // end of sema component.
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits