/// getObjCQualifiedIdType - Return an ObjCQualifiedIdType for a
/// given 'id' and conforming protocol list.
- QualType getObjCQualifiedIdType(QualType idType,
- ObjCProtocolDecl **ProtocolList,
+ QualType getObjCQualifiedIdType(ObjCProtocolDecl **ProtocolList,
unsigned NumProtocols);
// List is sorted on protocol name. No protocol is enterred more than once.
llvm::SmallVector<ObjCProtocolDecl*, 8> Protocols;
- ObjCQualifiedIdType(QualType can, ObjCProtocolDecl **Protos, unsigned NumP)
- : Type(ObjCQualifiedId, can),
+ ObjCQualifiedIdType(ObjCProtocolDecl **Protos, unsigned NumP)
+ : Type(ObjCQualifiedId, QualType()/*these are always canonical*/),
Protocols(Protos, Protos+NumP) { }
friend class ASTContext; // ASTContext creates these.
public:
virtual void getAsStringInternal(std::string &InnerString) const;
void Profile(llvm::FoldingSetNodeID &ID);
- static void Profile(llvm::FoldingSetNodeID &ID,
+ static void Profile(llvm::FoldingSetNodeID &ID,
ObjCProtocolDecl **protocols, unsigned NumProtocols);
static bool classof(const Type *T) {
/// getObjCQualifiedIdType - Return an ObjCQualifiedIdType for the 'id' decl
/// and the conforming protocol list.
-QualType ASTContext::getObjCQualifiedIdType(QualType idType,
- ObjCProtocolDecl **Protocols,
+QualType ASTContext::getObjCQualifiedIdType(ObjCProtocolDecl **Protocols,
unsigned NumProtocols) {
// Sort the protocol list alphabetically to canonicalize it.
SortAndUniqueProtocols(Protocols, NumProtocols);
void *InsertPos = 0;
if (ObjCQualifiedIdType *QT =
- ObjCQualifiedIdTypes.FindNodeOrInsertPos(ID, InsertPos))
+ ObjCQualifiedIdTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(QT, 0);
// No Match;
- QualType Canonical;
- 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);
+ ObjCQualifiedIdType *QType = new ObjCQualifiedIdType(Protocols, NumProtocols);
Types.push_back(QType);
ObjCQualifiedIdTypes.InsertNode(QType, InsertPos);
return QualType(QType, 0);
}
void ObjCQualifiedIdType::Profile(llvm::FoldingSetNodeID &ID,
- ObjCProtocolDecl **protocols,
- unsigned NumProtocols) {
+ ObjCProtocolDecl **protocols,
+ unsigned NumProtocols) {
for (unsigned i = 0; i != NumProtocols; i++)
ID.AddPointer(protocols[i]);
}
}
break;
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
// [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.
reinterpret_cast<ObjCProtocolDecl**>(PPDecl),
DS.getNumProtocolQualifiers());
break;
- }
- else if (TypedefDecl *typeDecl = dyn_cast<TypedefDecl>(D)) {
+ } else if (TypedefDecl *typeDecl = dyn_cast<TypedefDecl>(D)) {
if (Context.getObjCIdType() == Context.getTypedefType(typeDecl)
&& DS.getProtocolQualifiers()) {
// id<protocol-list>
Action::DeclTy **PPDecl = &(*DS.getProtocolQualifiers())[0];
- Result = Context.getObjCQualifiedIdType(typeDecl->getUnderlyingType(),
+ Result = Context.getObjCQualifiedIdType(
reinterpret_cast<ObjCProtocolDecl**>(PPDecl),
DS.getNumProtocolQualifiers());
break;
// RUN: clang -fsyntax-only -verify %s
+// rdar://5986251
@protocol SomeProtocol
+- (void) bar;
@end
void foo(id x) {
bar((short<SomeProtocol>)x); // expected-error {{expected ')'}} expected-error {{to match this '('}}
bar((<SomeProtocol>)x); // expected-warning {{protocol qualifiers without 'id' is archaic}}
+
+ [(<SomeProtocol>)x bar]; // expected-warning {{protocol qualifiers without 'id' is archaic}}
}