forked from OSchip/llvm-project
Cleanup ObjCInterfaceDecl lookup for ObjC literals
llvm-svn: 243092
This commit is contained in:
parent
1e271df041
commit
b7d8563973
|
@ -2101,25 +2101,18 @@ def err_field_with_address_space : Error<
|
|||
"field may not be qualified with an address space">;
|
||||
def err_attr_objc_ownership_redundant : Error<
|
||||
"the type %0 is already explicitly ownership-qualified">;
|
||||
def err_undeclared_nsnumber : Error<
|
||||
"NSNumber must be available to use Objective-C literals">;
|
||||
def err_undeclared_nsvalue : Error<
|
||||
"NSValue must be available to use Objective-C boxed expressions">;
|
||||
def err_invalid_nsnumber_type : Error<
|
||||
"%0 is not a valid literal type for NSNumber">;
|
||||
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_non_trivially_copyable_boxed_expression_type : Error<
|
||||
"non-trivially copyable type %0 cannot be 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<
|
||||
"NSDictionary must be available to use Objective-C dictionary "
|
||||
"literals">;
|
||||
def err_undeclared_objc_literal_class : Error<
|
||||
"definition of class %0 must be available to use Objective-C "
|
||||
"%select{array literals|dictionary literals|numeric literals|boxed expressions|"
|
||||
"string literals}1">;
|
||||
def err_undeclared_boxing_method : Error<
|
||||
"declaration of %0 is missing in %1 class">;
|
||||
def err_objc_literal_method_sig : Error<
|
||||
|
|
|
@ -168,6 +168,76 @@ static bool validateBoxingMethod(Sema &S, SourceLocation Loc,
|
|||
return true;
|
||||
}
|
||||
|
||||
/// \brief Maps ObjCLiteralKind to NSClassIdKindKind
|
||||
static NSAPI::NSClassIdKindKind ClassKindFromLiteralKind(
|
||||
Sema::ObjCLiteralKind LiteralKind) {
|
||||
switch (LiteralKind) {
|
||||
case Sema::LK_Array:
|
||||
return NSAPI::ClassId_NSArray;
|
||||
case Sema::LK_Dictionary:
|
||||
return NSAPI::ClassId_NSDictionary;
|
||||
case Sema::LK_Numeric:
|
||||
return NSAPI::ClassId_NSNumber;
|
||||
case Sema::LK_String:
|
||||
return NSAPI::ClassId_NSString;
|
||||
case Sema::LK_Boxed:
|
||||
return NSAPI::ClassId_NSValue;
|
||||
|
||||
// there is no corresponding matching
|
||||
// between LK_None/LK_Block and NSClassIdKindKind
|
||||
case Sema::LK_Block:
|
||||
case Sema::LK_None:
|
||||
llvm_unreachable("LiteralKind can't be converted into a ClassKind");
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Validates ObjCInterfaceDecl availability.
|
||||
/// ObjCInterfaceDecl, used to create ObjC literals, should be defined
|
||||
/// if clang not in a debugger mode.
|
||||
static bool ValidateObjCLiteralInterfaceDecl(Sema &S, ObjCInterfaceDecl *Decl,
|
||||
SourceLocation Loc,
|
||||
Sema::ObjCLiteralKind LiteralKind) {
|
||||
if (!Decl) {
|
||||
NSAPI::NSClassIdKindKind Kind = ClassKindFromLiteralKind(LiteralKind);
|
||||
IdentifierInfo *II = S.NSAPIObj->getNSClassId(Kind);
|
||||
S.Diag(Loc, diag::err_undeclared_objc_literal_class)
|
||||
<< II->getName() << LiteralKind;
|
||||
return false;
|
||||
} else if (!Decl->hasDefinition() && !S.getLangOpts().DebuggerObjCLiteral) {
|
||||
S.Diag(Loc, diag::err_undeclared_objc_literal_class)
|
||||
<< Decl->getName() << LiteralKind;
|
||||
S.Diag(Decl->getLocation(), diag::note_forward_class);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// \brief Looks up ObjCInterfaceDecl of a given NSClassIdKindKind.
|
||||
/// Used to create ObjC literals, such as NSDictionary (@{}),
|
||||
/// NSArray (@[]) and Boxed Expressions (@())
|
||||
static ObjCInterfaceDecl *LookupObjCInterfaceDeclForLiteral(Sema &S,
|
||||
SourceLocation Loc,
|
||||
Sema::ObjCLiteralKind LiteralKind) {
|
||||
NSAPI::NSClassIdKindKind ClassKind = ClassKindFromLiteralKind(LiteralKind);
|
||||
IdentifierInfo *II = S.NSAPIObj->getNSClassId(ClassKind);
|
||||
NamedDecl *IF = S.LookupSingleName(S.TUScope, II, Loc,
|
||||
Sema::LookupOrdinaryName);
|
||||
ObjCInterfaceDecl *ID = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
|
||||
if (!ID && S.getLangOpts().DebuggerObjCLiteral) {
|
||||
ASTContext &Context = S.Context;
|
||||
TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
|
||||
ID = ObjCInterfaceDecl::Create (Context, TU, SourceLocation(), II,
|
||||
nullptr, nullptr, SourceLocation());
|
||||
}
|
||||
|
||||
if (!ValidateObjCLiteralInterfaceDecl(S, ID, Loc, LiteralKind)) {
|
||||
ID = nullptr;
|
||||
}
|
||||
|
||||
return ID;
|
||||
}
|
||||
|
||||
/// \brief Retrieve the NSNumber factory method that should be used to create
|
||||
/// an Objective-C literal for the given type.
|
||||
static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
|
||||
|
@ -197,26 +267,9 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
|
|||
// Look up the NSNumber class, if we haven't done so already. It's cached
|
||||
// in the Sema instance.
|
||||
if (!S.NSNumberDecl) {
|
||||
IdentifierInfo *NSNumberId =
|
||||
S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSNumber);
|
||||
NamedDecl *IF = S.LookupSingleName(S.TUScope, NSNumberId,
|
||||
Loc, Sema::LookupOrdinaryName);
|
||||
S.NSNumberDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
|
||||
S.NSNumberDecl = LookupObjCInterfaceDeclForLiteral(S, Loc,
|
||||
Sema::LK_Numeric);
|
||||
if (!S.NSNumberDecl) {
|
||||
if (S.getLangOpts().DebuggerObjCLiteral) {
|
||||
// Create a stub definition of NSNumber.
|
||||
S.NSNumberDecl = ObjCInterfaceDecl::Create(CX,
|
||||
CX.getTranslationUnitDecl(),
|
||||
SourceLocation(), NSNumberId,
|
||||
nullptr, nullptr,
|
||||
SourceLocation());
|
||||
} else {
|
||||
// Otherwise, require a declaration of NSNumber.
|
||||
S.Diag(Loc, diag::err_undeclared_nsnumber);
|
||||
return nullptr;
|
||||
}
|
||||
} else if (!S.NSNumberDecl->hasDefinition()) {
|
||||
S.Diag(Loc, diag::err_undeclared_nsnumber);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -457,6 +510,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
|
|||
if (RValue.isInvalid()) {
|
||||
return ExprError();
|
||||
}
|
||||
SourceLocation Loc = SR.getBegin();
|
||||
ValueExpr = RValue.get();
|
||||
QualType ValueType(ValueExpr->getType());
|
||||
if (const PointerType *PT = ValueType->getAs<PointerType>()) {
|
||||
|
@ -464,29 +518,11 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
|
|||
if (Context.hasSameUnqualifiedType(PointeeType, Context.CharTy)) {
|
||||
|
||||
if (!NSStringDecl) {
|
||||
IdentifierInfo *NSStringId =
|
||||
NSAPIObj->getNSClassId(NSAPI::ClassId_NSString);
|
||||
NamedDecl *Decl = LookupSingleName(TUScope, NSStringId,
|
||||
SR.getBegin(), LookupOrdinaryName);
|
||||
NSStringDecl = dyn_cast_or_null<ObjCInterfaceDecl>(Decl);
|
||||
NSStringDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc,
|
||||
Sema::LK_String);
|
||||
if (!NSStringDecl) {
|
||||
if (getLangOpts().DebuggerObjCLiteral) {
|
||||
// Support boxed expressions in the debugger w/o NSString declaration.
|
||||
DeclContext *TU = Context.getTranslationUnitDecl();
|
||||
NSStringDecl = ObjCInterfaceDecl::Create(Context, TU,
|
||||
SourceLocation(),
|
||||
NSStringId,
|
||||
nullptr, nullptr,
|
||||
SourceLocation());
|
||||
} else {
|
||||
Diag(SR.getBegin(), diag::err_undeclared_nsstring);
|
||||
return ExprError();
|
||||
}
|
||||
} else if (!NSStringDecl->hasDefinition()) {
|
||||
Diag(SR.getBegin(), diag::err_undeclared_nsstring);
|
||||
return ExprError();
|
||||
}
|
||||
assert(NSStringDecl && "NSStringDecl should not be NULL");
|
||||
QualType NSStringObject = Context.getObjCInterfaceType(NSStringDecl);
|
||||
NSStringPointer = Context.getObjCObjectPointerType(NSStringObject);
|
||||
}
|
||||
|
@ -520,7 +556,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
|
|||
BoxingMethod = M;
|
||||
}
|
||||
|
||||
if (!validateBoxingMethod(*this, SR.getBegin(), NSStringDecl,
|
||||
if (!validateBoxingMethod(*this, Loc, NSStringDecl,
|
||||
stringWithUTF8String, BoxingMethod))
|
||||
return ExprError();
|
||||
|
||||
|
@ -563,16 +599,16 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
|
|||
// FIXME: Do I need to do anything special with BoolTy expressions?
|
||||
|
||||
// Look for the appropriate method within NSNumber.
|
||||
BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(), ValueType);
|
||||
BoxingMethod = getNSNumberFactoryMethod(*this, Loc, ValueType);
|
||||
BoxedType = NSNumberPointer;
|
||||
} else if (const EnumType *ET = ValueType->getAs<EnumType>()) {
|
||||
if (!ET->getDecl()->isComplete()) {
|
||||
Diag(SR.getBegin(), diag::err_objc_incomplete_boxed_expression_type)
|
||||
Diag(Loc, diag::err_objc_incomplete_boxed_expression_type)
|
||||
<< ValueType << ValueExpr->getSourceRange();
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(),
|
||||
BoxingMethod = getNSNumberFactoryMethod(*this, Loc,
|
||||
ET->getDecl()->getIntegerType());
|
||||
BoxedType = NSNumberPointer;
|
||||
} else if (ValueType->isObjCBoxableRecordType()) {
|
||||
|
@ -582,29 +618,12 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
|
|||
// Look up the NSValue class, if we haven't done so already. It's cached
|
||||
// in the Sema instance.
|
||||
if (!NSValueDecl) {
|
||||
IdentifierInfo *NSValueId =
|
||||
NSAPIObj->getNSClassId(NSAPI::ClassId_NSValue);
|
||||
NamedDecl *IF = LookupSingleName(TUScope, NSValueId,
|
||||
SR.getBegin(), Sema::LookupOrdinaryName);
|
||||
NSValueDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
|
||||
NSValueDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc,
|
||||
Sema::LK_Boxed);
|
||||
if (!NSValueDecl) {
|
||||
if (getLangOpts().DebuggerObjCLiteral) {
|
||||
// Create a stub definition of NSValue.
|
||||
DeclContext *TU = Context.getTranslationUnitDecl();
|
||||
NSValueDecl = ObjCInterfaceDecl::Create(Context, TU,
|
||||
SourceLocation(), NSValueId,
|
||||
nullptr, nullptr,
|
||||
SourceLocation());
|
||||
} else {
|
||||
// Otherwise, require a declaration of NSValue.
|
||||
Diag(SR.getBegin(), diag::err_undeclared_nsvalue);
|
||||
return ExprError();
|
||||
}
|
||||
} else if (!NSValueDecl->hasDefinition()) {
|
||||
Diag(SR.getBegin(), diag::err_undeclared_nsvalue);
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
|
||||
// generate the pointer to NSValue type.
|
||||
QualType NSValueObject = Context.getObjCInterfaceType(NSValueDecl);
|
||||
NSValuePointer = Context.getObjCObjectPointerType(NSValueObject);
|
||||
|
@ -663,7 +682,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
|
|||
BoxingMethod = M;
|
||||
}
|
||||
|
||||
if (!validateBoxingMethod(*this, SR.getBegin(), NSValueDecl,
|
||||
if (!validateBoxingMethod(*this, Loc, NSValueDecl,
|
||||
ValueWithBytesObjCType, BoxingMethod))
|
||||
return ExprError();
|
||||
|
||||
|
@ -671,8 +690,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
|
|||
}
|
||||
|
||||
if (!ValueType.isTriviallyCopyableType(Context)) {
|
||||
Diag(SR.getBegin(),
|
||||
diag::err_objc_non_trivially_copyable_boxed_expression_type)
|
||||
Diag(Loc, diag::err_objc_non_trivially_copyable_boxed_expression_type)
|
||||
<< ValueType << ValueExpr->getSourceRange();
|
||||
return ExprError();
|
||||
}
|
||||
|
@ -682,12 +700,12 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
|
|||
}
|
||||
|
||||
if (!BoxingMethod) {
|
||||
Diag(SR.getBegin(), diag::err_objc_illegal_boxed_expression_type)
|
||||
Diag(Loc, diag::err_objc_illegal_boxed_expression_type)
|
||||
<< ValueType << ValueExpr->getSourceRange();
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
DiagnoseUseOfDecl(BoxingMethod, SR.getBegin());
|
||||
DiagnoseUseOfDecl(BoxingMethod, Loc);
|
||||
|
||||
ExprResult ConvertedValueExpr;
|
||||
if (ValueType->isObjCBoxableRecordType()) {
|
||||
|
@ -746,26 +764,16 @@ ExprResult Sema::BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr,
|
|||
}
|
||||
|
||||
ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
|
||||
// Look up the NSArray class, if we haven't done so already.
|
||||
if (!NSArrayDecl) {
|
||||
NamedDecl *IF = LookupSingleName(TUScope,
|
||||
NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray),
|
||||
SR.getBegin(),
|
||||
LookupOrdinaryName);
|
||||
NSArrayDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
|
||||
if (!NSArrayDecl && getLangOpts().DebuggerObjCLiteral)
|
||||
NSArrayDecl = ObjCInterfaceDecl::Create (Context,
|
||||
Context.getTranslationUnitDecl(),
|
||||
SourceLocation(),
|
||||
NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray),
|
||||
nullptr, nullptr, SourceLocation());
|
||||
SourceLocation Loc = SR.getBegin();
|
||||
|
||||
if (!NSArrayDecl) {
|
||||
NSArrayDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc,
|
||||
Sema::LK_Array);
|
||||
if (!NSArrayDecl) {
|
||||
Diag(SR.getBegin(), diag::err_undeclared_nsarray);
|
||||
return ExprError();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Find the arrayWithObjects:count: method, if we haven't done so already.
|
||||
QualType IdT = Context.getObjCIdType();
|
||||
if (!ArrayWithObjectsMethod) {
|
||||
|
@ -801,7 +809,7 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
|
|||
Method->setMethodParams(Context, Params, None);
|
||||
}
|
||||
|
||||
if (!validateBoxingMethod(*this, SR.getBegin(), NSArrayDecl, Sel, Method))
|
||||
if (!validateBoxingMethod(*this, Loc, NSArrayDecl, Sel, Method))
|
||||
return ExprError();
|
||||
|
||||
// Dig out the type that all elements should be converted to.
|
||||
|
@ -862,25 +870,16 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
|
|||
ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
|
||||
ObjCDictionaryElement *Elements,
|
||||
unsigned NumElements) {
|
||||
// Look up the NSDictionary class, if we haven't done so already.
|
||||
if (!NSDictionaryDecl) {
|
||||
NamedDecl *IF = LookupSingleName(TUScope,
|
||||
NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary),
|
||||
SR.getBegin(), LookupOrdinaryName);
|
||||
NSDictionaryDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
|
||||
if (!NSDictionaryDecl && getLangOpts().DebuggerObjCLiteral)
|
||||
NSDictionaryDecl = ObjCInterfaceDecl::Create (Context,
|
||||
Context.getTranslationUnitDecl(),
|
||||
SourceLocation(),
|
||||
NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary),
|
||||
nullptr, nullptr, SourceLocation());
|
||||
SourceLocation Loc = SR.getBegin();
|
||||
|
||||
if (!NSDictionaryDecl) {
|
||||
NSDictionaryDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc,
|
||||
Sema::LK_Dictionary);
|
||||
if (!NSDictionaryDecl) {
|
||||
Diag(SR.getBegin(), diag::err_undeclared_nsdictionary);
|
||||
return ExprError();
|
||||
return ExprError();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Find the dictionaryWithObjects:forKeys:count: method, if we haven't done
|
||||
// so already.
|
||||
QualType IdT = Context.getObjCIdType();
|
||||
|
|
|
@ -11,14 +11,14 @@ typedef unsigned int NSUInteger;
|
|||
|
||||
void checkNSArrayUnavailableDiagnostic() {
|
||||
id obj;
|
||||
id arr = @[obj]; // expected-error {{NSArray must be available to use Objective-C array literals}}
|
||||
id arr = @[obj]; // expected-error {{definition of class NSArray must be available to use Objective-C array literals}}
|
||||
}
|
||||
|
||||
@class NSArray;
|
||||
@class NSArray; // expected-note {{forward declaration of class here}}
|
||||
|
||||
void checkNSArrayFDDiagnostic() {
|
||||
id obj;
|
||||
id arr = @[obj]; // expected-error {{declaration of 'arrayWithObjects:count:' is missing in NSArray class}}
|
||||
id arr = @[obj]; // expected-error {{definition of class NSArray must be available to use Objective-C array literals}}
|
||||
}
|
||||
|
||||
@class NSString;
|
||||
|
|
|
@ -46,7 +46,7 @@ typedef union BOXABLE _BoxableUnion {
|
|||
|
||||
void checkNSValueDiagnostic() {
|
||||
NSRect rect;
|
||||
id value = @(rect); // expected-error{{NSValue must be available to use Objective-C boxed expressions}}
|
||||
id value = @(rect); // expected-error{{definition of class NSValue must be available to use Objective-C boxed expressions}}
|
||||
}
|
||||
|
||||
@interface NSValue
|
||||
|
|
|
@ -8,15 +8,15 @@
|
|||
void checkNSDictionaryUnavailableDiagnostic() {
|
||||
id key;
|
||||
id value;
|
||||
id dict = @{ key : value }; // expected-error {{NSDictionary must be available to use Objective-C dictionary literals}}
|
||||
id dict = @{ key : value }; // expected-error {{definition of class NSDictionary must be available to use Objective-C dictionary literals}}
|
||||
}
|
||||
|
||||
@class NSDictionary;
|
||||
@class NSDictionary; // expected-note {{forward declaration of class here}}
|
||||
|
||||
void checkNSDictionaryFDDiagnostic() {
|
||||
id key;
|
||||
id value;
|
||||
id dic = @{ key : value }; // expected-error {{declaration of 'dictionaryWithObjects:forKeys:count:' is missing in NSDictionary class}}
|
||||
id dic = @{ key : value }; // expected-error {{definition of class NSDictionary must be available to use Objective-C dictionary literals}}
|
||||
}
|
||||
|
||||
@interface NSNumber
|
||||
|
|
|
@ -10,20 +10,20 @@ typedef int NSInteger;
|
|||
#endif
|
||||
|
||||
void checkNSNumberUnavailableDiagnostic() {
|
||||
id num = @1000; // expected-error {{NSNumber must be available to use Objective-C literals}}
|
||||
id num = @1000; // expected-error {{definition of class NSNumber must be available to use Objective-C numeric literals}}
|
||||
|
||||
int x = 1000;
|
||||
id num1 = @(x); // expected-error {{NSNumber must be available to use Objective-C literals}}\
|
||||
id num1 = @(x); // expected-error {{definition of class NSNumber must be available to use Objective-C numeric literals}}\
|
||||
// expected-error {{illegal type 'int' used in a boxed expression}}
|
||||
}
|
||||
|
||||
@class NSNumber;
|
||||
@class NSNumber; // expected-note 2 {{forward declaration of class here}}
|
||||
|
||||
void checkNSNumberFDDiagnostic() {
|
||||
id num = @1000; // expected-error {{NSNumber must be available to use Objective-C literals}}
|
||||
id num = @1000; // expected-error {{definition of class NSNumber must be available to use Objective-C numeric literals}}
|
||||
|
||||
int x = 1000;
|
||||
id num1 = @(x); // expected-error {{declaration of 'numberWithInt:' is missing in NSNumber class}}\
|
||||
id num1 = @(x); // expected-error {{definition of class NSNumber must be available to use Objective-C numeric literals}}\
|
||||
// expected-error {{illegal type 'int' used in a boxed expression}}
|
||||
}
|
||||
|
||||
|
@ -71,10 +71,10 @@ int main() {
|
|||
}
|
||||
|
||||
// Dictionary test
|
||||
@class NSDictionary;
|
||||
@class NSDictionary; // expected-note {{forward declaration of class here}}
|
||||
|
||||
NSDictionary *err() {
|
||||
return @{@"name" : @"value"}; // expected-error {{declaration of 'dictionaryWithObjects:forKeys:count:' is missing in NSDictionary class}}
|
||||
return @{@"name" : @"value"}; // expected-error {{definition of class NSDictionary must be available to use Objective-C dictionary literals}}
|
||||
}
|
||||
|
||||
@interface NSDate : NSObject
|
||||
|
|
|
@ -48,7 +48,7 @@ struct BOXABLE NonTriviallyCopyable {
|
|||
|
||||
void checkNSValueDiagnostic() {
|
||||
NSRect rect;
|
||||
id value = @(rect); // expected-error{{NSValue must be available to use Objective-C boxed expressions}}
|
||||
id value = @(rect); // expected-error{{definition of class NSValue must be available to use Objective-C boxed expressions}}
|
||||
}
|
||||
|
||||
@interface NSValue
|
||||
|
|
Loading…
Reference in New Issue