From f5343ff93a9549c49469dee366733e1e31ab836e Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Tue, 15 May 2012 19:17:44 +0000 Subject: [PATCH] Allow objc @() syntax for enum types. Previously we would reject it as illegal using a value of enum type and on ObjC++ it was illegal to use an enumerator as well. rdar://11454917 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156843 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 2 + lib/Sema/SemaExprObjC.cpp | 11 ++++ test/SemaObjC/boxing-illegal-types.m | 37 ++++++++++++++ test/SemaObjCXX/boxing-illegal-types.mm | 58 ++++++++++++++++++++++ 4 files changed, 108 insertions(+) create mode 100644 test/SemaObjCXX/boxing-illegal-types.mm diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index b1b40446ea..7436f8b396 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1540,6 +1540,8 @@ def err_undeclared_nsstring : Error< "cannot box a string value because NSString has not been declared">; def err_objc_illegal_boxed_expression_type : Error< "illegal type %0 used in a boxed expression">; +def err_objc_incomplete_boxed_expression_type : Error< + "incomplete type %0 used in a boxed expression">; def err_undeclared_nsarray : Error< "NSArray must be available to use Objective-C array literals">; def err_undeclared_nsdictionary : Error< diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 7ade400c53..9a5a27960c 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -539,6 +539,17 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { // Look for the appropriate method within NSNumber. BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(), ValueType); BoxedType = NSNumberPointer; + + } else if (const EnumType *ET = ValueType->getAs()) { + if (!ET->getDecl()->isComplete()) { + Diag(SR.getBegin(), diag::err_objc_incomplete_boxed_expression_type) + << ValueType << ValueExpr->getSourceRange(); + return ExprError(); + } + + BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(), + ET->getDecl()->getIntegerType()); + BoxedType = NSNumberPointer; } if (!BoxingMethod) { diff --git a/test/SemaObjC/boxing-illegal-types.m b/test/SemaObjC/boxing-illegal-types.m index 777109493d..ad45b11f2d 100644 --- a/test/SemaObjC/boxing-illegal-types.m +++ b/test/SemaObjC/boxing-illegal-types.m @@ -1,5 +1,29 @@ // RUN: %clang_cc1 -fsyntax-only -verify -Wattributes %s +typedef long NSInteger; +typedef unsigned long NSUInteger; +typedef signed char BOOL; + +@interface NSNumber +@end +@interface NSNumber (NSNumberCreation) ++ (NSNumber *)numberWithChar:(char)value; ++ (NSNumber *)numberWithUnsignedChar:(unsigned char)value; ++ (NSNumber *)numberWithShort:(short)value; ++ (NSNumber *)numberWithUnsignedShort:(unsigned short)value; ++ (NSNumber *)numberWithInt:(int)value; ++ (NSNumber *)numberWithUnsignedInt:(unsigned int)value; ++ (NSNumber *)numberWithLong:(long)value; ++ (NSNumber *)numberWithUnsignedLong:(unsigned long)value; ++ (NSNumber *)numberWithLongLong:(long long)value; ++ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value; ++ (NSNumber *)numberWithFloat:(float)value; ++ (NSNumber *)numberWithDouble:(double)value; ++ (NSNumber *)numberWithBool:(BOOL)value; ++ (NSNumber *)numberWithInteger:(NSInteger)value; ++ (NSNumber *)numberWithUnsignedInteger:(NSUInteger)value; +@end + typedef struct { int x, y, z; } point; @@ -19,3 +43,16 @@ void testPointers() { void testInvalid() { @(not_defined); // expected-error {{use of undeclared identifier 'not_defined'}} } + +enum MyEnum { + ME_foo +}; + +enum ForwE; + +void testEnum(void *p) { + enum MyEnum myen; + id box = @(myen); + box = @(ME_foo); + box = @(*(enum ForwE*)p); // expected-error {{incomplete type 'enum ForwE' used in a boxed expression}} +} diff --git a/test/SemaObjCXX/boxing-illegal-types.mm b/test/SemaObjCXX/boxing-illegal-types.mm new file mode 100644 index 0000000000..7729753fb9 --- /dev/null +++ b/test/SemaObjCXX/boxing-illegal-types.mm @@ -0,0 +1,58 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wattributes %s + +typedef long NSInteger; +typedef unsigned long NSUInteger; +typedef signed char BOOL; + +@interface NSNumber +@end +@interface NSNumber (NSNumberCreation) ++ (NSNumber *)numberWithChar:(char)value; ++ (NSNumber *)numberWithUnsignedChar:(unsigned char)value; ++ (NSNumber *)numberWithShort:(short)value; ++ (NSNumber *)numberWithUnsignedShort:(unsigned short)value; ++ (NSNumber *)numberWithInt:(int)value; ++ (NSNumber *)numberWithUnsignedInt:(unsigned int)value; ++ (NSNumber *)numberWithLong:(long)value; ++ (NSNumber *)numberWithUnsignedLong:(unsigned long)value; ++ (NSNumber *)numberWithLongLong:(long long)value; ++ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value; ++ (NSNumber *)numberWithFloat:(float)value; ++ (NSNumber *)numberWithDouble:(double)value; ++ (NSNumber *)numberWithBool:(BOOL)value; ++ (NSNumber *)numberWithInteger:(NSInteger)value; ++ (NSNumber *)numberWithUnsignedInteger:(NSUInteger)value; +@end + +typedef struct { + int x, y, z; +} point; + +void testStruct() { + point p = { 0, 0, 0 }; + id boxed = @(p); // expected-error {{illegal type 'point' used in a boxed expression}} +} + +void testPointers() { + void *null = 0; + id boxed_null = @(null); // expected-error {{illegal type 'void *' used in a boxed expression}} + int numbers[] = { 0, 1, 2 }; + id boxed_numbers = @(numbers); // expected-error {{illegal type 'int *' used in a boxed expression}} +} + +void testInvalid() { + @(not_defined); // expected-error {{use of undeclared identifier 'not_defined'}} +} + +enum MyEnum { + ME_foo +}; + +enum ForwE; // expected-error {{ISO C++ forbids forward references to 'enum' types}} + +void testEnum(void *p) { + enum MyEnum myen; + id box = @(myen); + box = @(ME_foo); + box = @(*(enum ForwE*)p); // expected-error {{incomplete type 'enum ForwE' used in a boxed expression}} +} -- 2.40.0