Fix <rdar://problem/6770276> Support Class<Proto> syntax.

llvm-svn: 76741
This commit is contained in:
Steve Naroff 2009-07-22 16:07:01 +00:00
parent a3a4dd5d03
commit 51d4f79ffa
10 changed files with 24 additions and 21 deletions

View File

@ -402,6 +402,7 @@ public:
bool isObjCInterfaceType() const; // NSString or NSString<foo> bool isObjCInterfaceType() const; // NSString or NSString<foo>
bool isObjCQualifiedInterfaceType() const; // NSString<foo> bool isObjCQualifiedInterfaceType() const; // NSString<foo>
bool isObjCQualifiedIdType() const; // id<foo> bool isObjCQualifiedIdType() const; // id<foo>
bool isObjCQualifiedClassType() const; // Class<foo>
bool isObjCIdType() const; // id bool isObjCIdType() const; // id
bool isObjCClassType() const; // Class bool isObjCClassType() const; // Class
bool isObjCBuiltinType() const; // 'id' or 'Class' bool isObjCBuiltinType() const; // 'id' or 'Class'
@ -1950,7 +1951,7 @@ public:
Protocols.size(); Protocols.size();
} }
/// isObjCQualifiedClassType - true for "Class <p>". /// isObjCQualifiedClassType - true for "Class <p>".
bool isQualifiedClassType() const { bool isObjCQualifiedClassType() const {
return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCClass) && return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCClass) &&
Protocols.size(); Protocols.size();
} }
@ -2137,6 +2138,11 @@ inline bool Type::isObjCQualifiedIdType() const {
return OPT->isObjCQualifiedIdType(); return OPT->isObjCQualifiedIdType();
return false; return false;
} }
inline bool Type::isObjCQualifiedClassType() const {
if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType())
return OPT->isObjCQualifiedClassType();
return false;
}
inline bool Type::isObjCIdType() const { inline bool Type::isObjCIdType() const {
if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType()) if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType())
return OPT->isObjCIdType(); return OPT->isObjCIdType();

View File

@ -1961,8 +1961,6 @@ def ext_c99_array_usage : Extension<
"use of C99-specific array features, accepted as an extension">; "use of C99-specific array features, accepted as an extension">;
def err_invalid_protocol_qualifiers : Error< def err_invalid_protocol_qualifiers : Error<
"invalid protocol qualifiers on non-ObjC type">; "invalid protocol qualifiers on non-ObjC type">;
def err_qualified_class_unsupported : Error<
"protocol qualified 'Class' is unsupported">;
def warn_ivar_use_hidden : Warning< def warn_ivar_use_hidden : Warning<
"local declaration of %0 hides instance variable">; "local declaration of %0 hides instance variable">;
def error_ivar_use_in_class_method : Error< def error_ivar_use_in_class_method : Error<

View File

@ -1742,9 +1742,6 @@ static void SortAndUniqueProtocols(ObjCProtocolDecl **&Protocols,
QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT, QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT,
ObjCProtocolDecl **Protocols, ObjCProtocolDecl **Protocols,
unsigned NumProtocols) { unsigned NumProtocols) {
if (InterfaceT.isNull())
InterfaceT = ObjCBuiltinIdTy;
// Sort the protocol list alphabetically to canonicalize it. // Sort the protocol list alphabetically to canonicalize it.
if (NumProtocols) if (NumProtocols)
SortAndUniqueProtocols(Protocols, NumProtocols); SortAndUniqueProtocols(Protocols, NumProtocols);

View File

@ -1603,7 +1603,7 @@ void ObjCObjectPointerType::getAsStringInternal(std::string &InnerString,
if (isObjCIdType() || isObjCQualifiedIdType()) if (isObjCIdType() || isObjCQualifiedIdType())
ObjCQIString = "id"; ObjCQIString = "id";
else if (isObjCClassType()) else if (isObjCClassType() || isObjCQualifiedClassType())
ObjCQIString = "Class"; ObjCQIString = "Class";
else else
ObjCQIString = getInterfaceDecl()->getNameAsString(); ObjCQIString = getInterfaceDecl()->getNameAsString();

View File

@ -512,8 +512,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
} }
// Handle messages to id. // Handle messages to id.
if (ReceiverCType == Context.getCanonicalType(Context.getObjCIdType()) || if (ReceiverCType->isObjCIdType() || ReceiverCType->isBlockPointerType() ||
ReceiverCType->isBlockPointerType() ||
Context.isObjCNSObjectType(RExpr->getType())) { Context.isObjCNSObjectType(RExpr->getType())) {
ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool( ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(
Sel, SourceRange(lbrac,rbrac)); Sel, SourceRange(lbrac,rbrac));
@ -528,7 +527,8 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
} }
// Handle messages to Class. // Handle messages to Class.
if (ReceiverCType == Context.getCanonicalType(Context.getObjCClassType())) { if (ReceiverCType->isObjCClassType() ||
ReceiverCType->isObjCQualifiedClassType()) {
ObjCMethodDecl *Method = 0; ObjCMethodDecl *Method = 0;
if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
@ -538,6 +538,9 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
if (!Method) if (!Method)
Method = LookupPrivateClassMethod(Sel, ClassDecl); Method = LookupPrivateClassMethod(Sel, ClassDecl);
// FIXME: if we still haven't found a method, we need to look in
// protocols (if we have qualifiers).
} }
if (Method && DiagnoseUseOfDecl(Method, receiverLoc)) if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
return true; return true;

View File

@ -101,7 +101,7 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
case DeclSpec::TST_unspecified: case DeclSpec::TST_unspecified:
// "<proto1,proto2>" is an objc qualified ID with a missing id. // "<proto1,proto2>" is an objc qualified ID with a missing id.
if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) { if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
Result = Context.getObjCObjectPointerType(QualType(), Result = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy,
(ObjCProtocolDecl**)PQ, (ObjCProtocolDecl**)PQ,
DS.getNumProtocolQualifiers()); DS.getNumProtocolQualifiers());
break; break;
@ -220,14 +220,14 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
DS.getNumProtocolQualifiers()); DS.getNumProtocolQualifiers());
else if (Result->isObjCIdType()) else if (Result->isObjCIdType())
// id<protocol-list> // id<protocol-list>
Result = Context.getObjCObjectPointerType(QualType(), Result = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy,
(ObjCProtocolDecl**)PQ, DS.getNumProtocolQualifiers()); (ObjCProtocolDecl**)PQ, DS.getNumProtocolQualifiers());
else if (Result->isObjCClassType()) { else if (Result->isObjCClassType()) {
if (DeclLoc.isInvalid()) if (DeclLoc.isInvalid())
DeclLoc = DS.getSourceRange().getBegin(); DeclLoc = DS.getSourceRange().getBegin();
// Class<protocol-list> // Class<protocol-list>
Diag(DeclLoc, diag::err_qualified_class_unsupported) Result = Context.getObjCObjectPointerType(Context.ObjCBuiltinClassTy,
<< DS.getSourceRange(); (ObjCProtocolDecl**)PQ, DS.getNumProtocolQualifiers());
} else { } else {
if (DeclLoc.isInvalid()) if (DeclLoc.isInvalid())
DeclLoc = DS.getSourceRange().getBegin(); DeclLoc = DS.getSourceRange().getBegin();

View File

@ -40,8 +40,8 @@ id objc_getClass(const char *s);
{ {
int i = [(id <Func>)self class_func0]; int i = [(id <Func>)self class_func0];
i += [(id <Func>)super class_func0]; // expected-error {{cannot cast 'super' (it isn't an expression)}} i += [(id <Func>)super class_func0]; // expected-error {{cannot cast 'super' (it isn't an expression)}}
i += [(Class <Func>)self class_func0]; // expected-error {{protocol qualified 'Class' is unsupported}} i += [(Class <Func>)self class_func0]; //
return i + [(Class <Func>)super class_func0]; // expected-error {{protocol qualified 'Class' is unsupported}} // expected-error {{cannot cast 'super' (it isn't an expression)}} return i + [(Class <Func>)super class_func0]; // // expected-error {{cannot cast 'super' (it isn't an expression)}}
} }
+ (int) class_func3 + (int) class_func3
{ {

View File

@ -28,8 +28,7 @@ typedef int NotAnObjCObjectType;
// GCC doesn't diagnose this. // GCC doesn't diagnose this.
NotAnObjCObjectType <SomeProtocol> *obj; // expected-error {{invalid protocol qualifiers on non-ObjC type}} NotAnObjCObjectType <SomeProtocol> *obj; // expected-error {{invalid protocol qualifiers on non-ObjC type}}
// Decided not to support the following GCC extension. Found while researching rdar://6497631
typedef struct objc_class *Class; typedef struct objc_class *Class;
Class <SomeProtocol> UnfortunateGCCExtension; // expected-error {{protocol qualified 'Class' is unsupported}} Class <SomeProtocol> UnfortunateGCCExtension;

View File

@ -3,7 +3,7 @@
__attribute ((unavailable)) __attribute ((unavailable))
@protocol FwProto; // expected-note{{marked unavailable}} @protocol FwProto; // expected-note{{marked unavailable}}
Class <FwProto> cFw = 0; // expected-warning {{'FwProto' is unavailable}} expected-error{{protocol qualified 'Class' is unsupported}} Class <FwProto> cFw = 0; // expected-warning {{'FwProto' is unavailable}}
__attribute ((deprecated)) @protocol MyProto1 __attribute ((deprecated)) @protocol MyProto1
@ -31,7 +31,7 @@ __attribute ((deprecated)) @protocol MyProto1
Class <MyProto1> clsP1 = 0; // expected-warning {{'MyProto1' is deprecated}} expected-error{{protocol qualified 'Class' is unsupported}} Class <MyProto1> clsP1 = 0; // expected-warning {{'MyProto1' is deprecated}}
@protocol FwProto @end // expected-note{{marked unavailable}} @protocol FwProto @end // expected-note{{marked unavailable}}

View File

@ -23,7 +23,7 @@ id objc_getClass(const char *s);
@interface Derived2: Object <Func> @interface Derived2: Object <Func>
@end @end
static void doSomething(Class <Func> unsupportedObjectType) { // expected-error {{protocol qualified 'Class' is unsupported}} static void doSomething(Class <Func> unsupportedObjectType) {
[unsupportedObjectType class_func0]; [unsupportedObjectType class_func0];
} }