forked from OSchip/llvm-project
fix several problems with the protocol qualified id handling where id was implicit.
First, fix canonical type handling of these, since protocol qualified id's are always canonical. Next, enhance SemaType to actually make these when used (instead of int) allowing them to actually be used when appropriate. Finally remove a bunch of logic relating to the mishandling of canonical types with protocol-qual id's. This fixes rdar://5986251 llvm-svn: 54083
This commit is contained in:
parent
0974b2380f
commit
a075e63bbc
|
@ -217,8 +217,7 @@ public:
|
||||||
|
|
||||||
/// getObjCQualifiedIdType - Return an ObjCQualifiedIdType for a
|
/// getObjCQualifiedIdType - Return an ObjCQualifiedIdType for a
|
||||||
/// given 'id' and conforming protocol list.
|
/// given 'id' and conforming protocol list.
|
||||||
QualType getObjCQualifiedIdType(QualType idType,
|
QualType getObjCQualifiedIdType(ObjCProtocolDecl **ProtocolList,
|
||||||
ObjCProtocolDecl **ProtocolList,
|
|
||||||
unsigned NumProtocols);
|
unsigned NumProtocols);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1227,8 +1227,8 @@ class ObjCQualifiedIdType : public Type,
|
||||||
// List is sorted on protocol name. No protocol is enterred more than once.
|
// List is sorted on protocol name. No protocol is enterred more than once.
|
||||||
llvm::SmallVector<ObjCProtocolDecl*, 8> Protocols;
|
llvm::SmallVector<ObjCProtocolDecl*, 8> Protocols;
|
||||||
|
|
||||||
ObjCQualifiedIdType(QualType can, ObjCProtocolDecl **Protos, unsigned NumP)
|
ObjCQualifiedIdType(ObjCProtocolDecl **Protos, unsigned NumP)
|
||||||
: Type(ObjCQualifiedId, can),
|
: Type(ObjCQualifiedId, QualType()/*these are always canonical*/),
|
||||||
Protocols(Protos, Protos+NumP) { }
|
Protocols(Protos, Protos+NumP) { }
|
||||||
friend class ASTContext; // ASTContext creates these.
|
friend class ASTContext; // ASTContext creates these.
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -929,8 +929,7 @@ QualType ASTContext::getObjCQualifiedInterfaceType(ObjCInterfaceDecl *Decl,
|
||||||
|
|
||||||
/// getObjCQualifiedIdType - Return an ObjCQualifiedIdType for the 'id' decl
|
/// getObjCQualifiedIdType - Return an ObjCQualifiedIdType for the 'id' decl
|
||||||
/// and the conforming protocol list.
|
/// and the conforming protocol list.
|
||||||
QualType ASTContext::getObjCQualifiedIdType(QualType idType,
|
QualType ASTContext::getObjCQualifiedIdType(ObjCProtocolDecl **Protocols,
|
||||||
ObjCProtocolDecl **Protocols,
|
|
||||||
unsigned NumProtocols) {
|
unsigned NumProtocols) {
|
||||||
// Sort the protocol list alphabetically to canonicalize it.
|
// Sort the protocol list alphabetically to canonicalize it.
|
||||||
SortAndUniqueProtocols(Protocols, NumProtocols);
|
SortAndUniqueProtocols(Protocols, NumProtocols);
|
||||||
|
@ -940,21 +939,11 @@ QualType ASTContext::getObjCQualifiedIdType(QualType idType,
|
||||||
|
|
||||||
void *InsertPos = 0;
|
void *InsertPos = 0;
|
||||||
if (ObjCQualifiedIdType *QT =
|
if (ObjCQualifiedIdType *QT =
|
||||||
ObjCQualifiedIdTypes.FindNodeOrInsertPos(ID, InsertPos))
|
ObjCQualifiedIdTypes.FindNodeOrInsertPos(ID, InsertPos))
|
||||||
return QualType(QT, 0);
|
return QualType(QT, 0);
|
||||||
|
|
||||||
// No Match;
|
// No Match;
|
||||||
QualType Canonical;
|
ObjCQualifiedIdType *QType = new ObjCQualifiedIdType(Protocols, NumProtocols);
|
||||||
if (!idType->isCanonical()) {
|
|
||||||
Canonical = getObjCQualifiedIdType(getCanonicalType(idType),
|
|
||||||
Protocols, NumProtocols);
|
|
||||||
ObjCQualifiedIdType *NewQT =
|
|
||||||
ObjCQualifiedIdTypes.FindNodeOrInsertPos(ID, InsertPos);
|
|
||||||
assert(NewQT == 0 && "Shouldn't be in the map!");
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjCQualifiedIdType *QType =
|
|
||||||
new ObjCQualifiedIdType(Canonical, Protocols, NumProtocols);
|
|
||||||
Types.push_back(QType);
|
Types.push_back(QType);
|
||||||
ObjCQualifiedIdTypes.InsertNode(QType, InsertPos);
|
ObjCQualifiedIdTypes.InsertNode(QType, InsertPos);
|
||||||
return QualType(QType, 0);
|
return QualType(QType, 0);
|
||||||
|
|
|
@ -743,8 +743,8 @@ void ObjCQualifiedInterfaceType::Profile(llvm::FoldingSetNodeID &ID) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjCQualifiedIdType::Profile(llvm::FoldingSetNodeID &ID,
|
void ObjCQualifiedIdType::Profile(llvm::FoldingSetNodeID &ID,
|
||||||
ObjCProtocolDecl **protocols,
|
ObjCProtocolDecl **protocols,
|
||||||
unsigned NumProtocols) {
|
unsigned NumProtocols) {
|
||||||
for (unsigned i = 0; i != NumProtocols; i++)
|
for (unsigned i = 0; i != NumProtocols; i++)
|
||||||
ID.AddPointer(protocols[i]);
|
ID.AddPointer(protocols[i]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,14 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DeclSpec::TST_unspecified:
|
case DeclSpec::TST_unspecified:
|
||||||
|
// "<proto1,proto2>" is an objc qualified ID with a missing id.
|
||||||
|
if (llvm::SmallVector<Action::DeclTy *, 8> *PQ=DS.getProtocolQualifiers()) {
|
||||||
|
Action::DeclTy **PPDecl = &(*PQ)[0];
|
||||||
|
Result = Context.getObjCQualifiedIdType((ObjCProtocolDecl**)(PPDecl),
|
||||||
|
DS.getNumProtocolQualifiers());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Unspecified typespec defaults to int in C90. However, the C90 grammar
|
// Unspecified typespec defaults to int in C90. However, the C90 grammar
|
||||||
// [C90 6.5] only allows a decl-spec if there was *some* type-specifier,
|
// [C90 6.5] only allows a decl-spec if there was *some* type-specifier,
|
||||||
// type-qualifier, or storage-class-specifier. If not, emit an extwarn.
|
// type-qualifier, or storage-class-specifier. If not, emit an extwarn.
|
||||||
|
@ -128,13 +136,12 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS) {
|
||||||
reinterpret_cast<ObjCProtocolDecl**>(PPDecl),
|
reinterpret_cast<ObjCProtocolDecl**>(PPDecl),
|
||||||
DS.getNumProtocolQualifiers());
|
DS.getNumProtocolQualifiers());
|
||||||
break;
|
break;
|
||||||
}
|
} else if (TypedefDecl *typeDecl = dyn_cast<TypedefDecl>(D)) {
|
||||||
else if (TypedefDecl *typeDecl = dyn_cast<TypedefDecl>(D)) {
|
|
||||||
if (Context.getObjCIdType() == Context.getTypedefType(typeDecl)
|
if (Context.getObjCIdType() == Context.getTypedefType(typeDecl)
|
||||||
&& DS.getProtocolQualifiers()) {
|
&& DS.getProtocolQualifiers()) {
|
||||||
// id<protocol-list>
|
// id<protocol-list>
|
||||||
Action::DeclTy **PPDecl = &(*DS.getProtocolQualifiers())[0];
|
Action::DeclTy **PPDecl = &(*DS.getProtocolQualifiers())[0];
|
||||||
Result = Context.getObjCQualifiedIdType(typeDecl->getUnderlyingType(),
|
Result = Context.getObjCQualifiedIdType(
|
||||||
reinterpret_cast<ObjCProtocolDecl**>(PPDecl),
|
reinterpret_cast<ObjCProtocolDecl**>(PPDecl),
|
||||||
DS.getNumProtocolQualifiers());
|
DS.getNumProtocolQualifiers());
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
// RUN: clang -fsyntax-only -verify %s
|
// RUN: clang -fsyntax-only -verify %s
|
||||||
|
// rdar://5986251
|
||||||
|
|
||||||
@protocol SomeProtocol
|
@protocol SomeProtocol
|
||||||
|
- (void) bar;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
void foo(id x) {
|
void foo(id x) {
|
||||||
bar((short<SomeProtocol>)x); // expected-error {{expected ')'}} expected-error {{to match this '('}}
|
bar((short<SomeProtocol>)x); // expected-error {{expected ')'}} expected-error {{to match this '('}}
|
||||||
bar((<SomeProtocol>)x); // expected-warning {{protocol qualifiers without 'id' is archaic}}
|
bar((<SomeProtocol>)x); // expected-warning {{protocol qualifiers without 'id' is archaic}}
|
||||||
|
|
||||||
|
[(<SomeProtocol>)x bar]; // expected-warning {{protocol qualifiers without 'id' is archaic}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue