forked from OSchip/llvm-project
Add support for GCC ObjC extension "Class<protocol>". Sigh.
Found while researching <rdar://problem/6497631> Message lookup is sometimes different than gcc's. Will never be seen in user code. Needed to pass dejagnu testsuite. llvm-svn: 65244
This commit is contained in:
parent
2ac40a9ff8
commit
670e72ddc7
|
@ -73,6 +73,7 @@ class ASTContext {
|
||||||
ClassTemplateSpecializationTypes;
|
ClassTemplateSpecializationTypes;
|
||||||
llvm::FoldingSet<ObjCQualifiedInterfaceType> ObjCQualifiedInterfaceTypes;
|
llvm::FoldingSet<ObjCQualifiedInterfaceType> ObjCQualifiedInterfaceTypes;
|
||||||
llvm::FoldingSet<ObjCQualifiedIdType> ObjCQualifiedIdTypes;
|
llvm::FoldingSet<ObjCQualifiedIdType> ObjCQualifiedIdTypes;
|
||||||
|
llvm::FoldingSet<ObjCQualifiedClassType> ObjCQualifiedClassTypes;
|
||||||
/// ASTRecordLayouts - A cache mapping from RecordDecls to ASTRecordLayouts.
|
/// ASTRecordLayouts - A cache mapping from RecordDecls to ASTRecordLayouts.
|
||||||
/// This is lazily created. This is intentionally not serialized.
|
/// This is lazily created. This is intentionally not serialized.
|
||||||
llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*> ASTRecordLayouts;
|
llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*> ASTRecordLayouts;
|
||||||
|
@ -291,6 +292,10 @@ public:
|
||||||
QualType getObjCQualifiedIdType(ObjCProtocolDecl **ProtocolList,
|
QualType getObjCQualifiedIdType(ObjCProtocolDecl **ProtocolList,
|
||||||
unsigned NumProtocols);
|
unsigned NumProtocols);
|
||||||
|
|
||||||
|
/// getObjCQualifiedClassType - Return an ObjCQualifiedClassType for a
|
||||||
|
/// given 'Class' and conforming protocol list.
|
||||||
|
QualType getObjCQualifiedClassType(ObjCProtocolDecl **ProtocolList,
|
||||||
|
unsigned NumProtocols);
|
||||||
|
|
||||||
/// getTypeOfType - GCC extension.
|
/// getTypeOfType - GCC extension.
|
||||||
QualType getTypeOfExpr(Expr *e);
|
QualType getTypeOfExpr(Expr *e);
|
||||||
|
|
|
@ -69,6 +69,7 @@ namespace clang {
|
||||||
class BuiltinType;
|
class BuiltinType;
|
||||||
class ObjCInterfaceType;
|
class ObjCInterfaceType;
|
||||||
class ObjCQualifiedIdType;
|
class ObjCQualifiedIdType;
|
||||||
|
class ObjCQualifiedClassType;
|
||||||
class ObjCQualifiedInterfaceType;
|
class ObjCQualifiedInterfaceType;
|
||||||
class StmtIteratorBase;
|
class StmtIteratorBase;
|
||||||
class ClassTemplateSpecializationType;
|
class ClassTemplateSpecializationType;
|
||||||
|
@ -384,6 +385,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 isTemplateTypeParmType() const; // C++ template type parameter
|
bool isTemplateTypeParmType() const; // C++ template type parameter
|
||||||
|
|
||||||
/// isDependentType - Whether this type is a dependent type, meaning
|
/// isDependentType - Whether this type is a dependent type, meaning
|
||||||
|
@ -417,6 +419,7 @@ public:
|
||||||
const ObjCInterfaceType *getAsObjCInterfaceType() const;
|
const ObjCInterfaceType *getAsObjCInterfaceType() const;
|
||||||
const ObjCQualifiedInterfaceType *getAsObjCQualifiedInterfaceType() const;
|
const ObjCQualifiedInterfaceType *getAsObjCQualifiedInterfaceType() const;
|
||||||
const ObjCQualifiedIdType *getAsObjCQualifiedIdType() const;
|
const ObjCQualifiedIdType *getAsObjCQualifiedIdType() const;
|
||||||
|
const ObjCQualifiedClassType *getAsObjCQualifiedClassType() const;
|
||||||
const TemplateTypeParmType *getAsTemplateTypeParmType() const;
|
const TemplateTypeParmType *getAsTemplateTypeParmType() const;
|
||||||
|
|
||||||
const ClassTemplateSpecializationType *
|
const ClassTemplateSpecializationType *
|
||||||
|
@ -1744,6 +1747,49 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// ObjCQualifiedClassType - to represent Class<protocol-list>.
|
||||||
|
///
|
||||||
|
/// Duplicate protocols are removed and protocol list is canonicalized to be in
|
||||||
|
/// alphabetical order.
|
||||||
|
class ObjCQualifiedClassType : public Type,
|
||||||
|
public llvm::FoldingSetNode {
|
||||||
|
// List of protocols for this protocol conforming 'id' type
|
||||||
|
// List is sorted on protocol name. No protocol is enterred more than once.
|
||||||
|
llvm::SmallVector<ObjCProtocolDecl*, 8> Protocols;
|
||||||
|
|
||||||
|
ObjCQualifiedClassType(ObjCProtocolDecl **Protos, unsigned NumP)
|
||||||
|
: Type(ObjCQualifiedId, QualType()/*these are always canonical*/,
|
||||||
|
/*Dependent=*/false),
|
||||||
|
Protocols(Protos, Protos+NumP) { }
|
||||||
|
friend class ASTContext; // ASTContext creates these.
|
||||||
|
public:
|
||||||
|
|
||||||
|
ObjCProtocolDecl *getProtocols(unsigned i) const {
|
||||||
|
return Protocols[i];
|
||||||
|
}
|
||||||
|
unsigned getNumProtocols() const {
|
||||||
|
return Protocols.size();
|
||||||
|
}
|
||||||
|
ObjCProtocolDecl **getReferencedProtocols() {
|
||||||
|
return &Protocols[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef llvm::SmallVector<ObjCProtocolDecl*, 8>::const_iterator qual_iterator;
|
||||||
|
qual_iterator qual_begin() const { return Protocols.begin(); }
|
||||||
|
qual_iterator qual_end() const { return Protocols.end(); }
|
||||||
|
|
||||||
|
virtual void getAsStringInternal(std::string &InnerString) const;
|
||||||
|
|
||||||
|
void Profile(llvm::FoldingSetNodeID &ID);
|
||||||
|
static void Profile(llvm::FoldingSetNodeID &ID,
|
||||||
|
ObjCProtocolDecl **protocols, unsigned NumProtocols);
|
||||||
|
|
||||||
|
static bool classof(const Type *T) {
|
||||||
|
return T->getTypeClass() == ObjCQualifiedId;
|
||||||
|
}
|
||||||
|
static bool classof(const ObjCQualifiedClassType *) { return true; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
// Inline function definitions.
|
// Inline function definitions.
|
||||||
|
|
||||||
|
@ -1899,6 +1945,9 @@ inline bool Type::isObjCQualifiedInterfaceType() const {
|
||||||
inline bool Type::isObjCQualifiedIdType() const {
|
inline bool Type::isObjCQualifiedIdType() const {
|
||||||
return isa<ObjCQualifiedIdType>(CanonicalType.getUnqualifiedType());
|
return isa<ObjCQualifiedIdType>(CanonicalType.getUnqualifiedType());
|
||||||
}
|
}
|
||||||
|
inline bool Type::isObjCQualifiedClassType() const {
|
||||||
|
return isa<ObjCQualifiedClassType>(CanonicalType.getUnqualifiedType());
|
||||||
|
}
|
||||||
inline bool Type::isTemplateTypeParmType() const {
|
inline bool Type::isTemplateTypeParmType() const {
|
||||||
return isa<TemplateTypeParmType>(CanonicalType.getUnqualifiedType());
|
return isa<TemplateTypeParmType>(CanonicalType.getUnqualifiedType());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1394,6 +1394,29 @@ QualType ASTContext::getObjCQualifiedIdType(ObjCProtocolDecl **Protocols,
|
||||||
return QualType(QType, 0);
|
return QualType(QType, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getObjCQualifiedClassType - Return an ObjCQualifiedIdType for the 'Class'
|
||||||
|
/// decl and the conforming protocol list.
|
||||||
|
QualType ASTContext::getObjCQualifiedClassType(ObjCProtocolDecl **Protocols,
|
||||||
|
unsigned NumProtocols) {
|
||||||
|
// Sort the protocol list alphabetically to canonicalize it.
|
||||||
|
SortAndUniqueProtocols(Protocols, NumProtocols);
|
||||||
|
|
||||||
|
llvm::FoldingSetNodeID ID;
|
||||||
|
ObjCQualifiedIdType::Profile(ID, Protocols, NumProtocols);
|
||||||
|
|
||||||
|
void *InsertPos = 0;
|
||||||
|
if (ObjCQualifiedClassType *QT =
|
||||||
|
ObjCQualifiedClassTypes.FindNodeOrInsertPos(ID, InsertPos))
|
||||||
|
return QualType(QT, 0);
|
||||||
|
|
||||||
|
// No Match;
|
||||||
|
ObjCQualifiedClassType *QType =
|
||||||
|
new (*this,8) ObjCQualifiedClassType(Protocols, NumProtocols);
|
||||||
|
Types.push_back(QType);
|
||||||
|
ObjCQualifiedClassTypes.InsertNode(QType, InsertPos);
|
||||||
|
return QualType(QType, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/// getTypeOfExpr - Unlike many "get<Type>" functions, we can't unique
|
/// getTypeOfExpr - Unlike many "get<Type>" functions, we can't unique
|
||||||
/// TypeOfExpr AST's (since expression's are never shared). For example,
|
/// TypeOfExpr AST's (since expression's are never shared). For example,
|
||||||
/// multiple declarations that refer to "typeof(x)" all contain different
|
/// multiple declarations that refer to "typeof(x)" all contain different
|
||||||
|
|
|
@ -869,6 +869,17 @@ void ObjCQualifiedIdType::Profile(llvm::FoldingSetNodeID &ID) {
|
||||||
Profile(ID, &Protocols[0], getNumProtocols());
|
Profile(ID, &Protocols[0], getNumProtocols());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ObjCQualifiedClassType::Profile(llvm::FoldingSetNodeID &ID,
|
||||||
|
ObjCProtocolDecl **protocols,
|
||||||
|
unsigned NumProtocols) {
|
||||||
|
for (unsigned i = 0; i != NumProtocols; i++)
|
||||||
|
ID.AddPointer(protocols[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjCQualifiedClassType::Profile(llvm::FoldingSetNodeID &ID) {
|
||||||
|
Profile(ID, &Protocols[0], getNumProtocols());
|
||||||
|
}
|
||||||
|
|
||||||
/// LookThroughTypedefs - Return the ultimate type this typedef corresponds to
|
/// LookThroughTypedefs - Return the ultimate type this typedef corresponds to
|
||||||
/// potentially looking through *all* consequtive typedefs. This returns the
|
/// potentially looking through *all* consequtive typedefs. This returns the
|
||||||
/// sum of the type qualifiers, so if you have:
|
/// sum of the type qualifiers, so if you have:
|
||||||
|
@ -1345,6 +1356,22 @@ void ObjCQualifiedIdType::getAsStringInternal(std::string &InnerString) const {
|
||||||
InnerString = ObjCQIString + InnerString;
|
InnerString = ObjCQIString + InnerString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ObjCQualifiedClassType::getAsStringInternal(std::string &InnerString) const
|
||||||
|
{
|
||||||
|
if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
|
||||||
|
InnerString = ' ' + InnerString;
|
||||||
|
std::string ObjCQIString = "Class";
|
||||||
|
ObjCQIString += '<';
|
||||||
|
int num = getNumProtocols();
|
||||||
|
for (int i = 0; i < num; i++) {
|
||||||
|
ObjCQIString += getProtocols(i)->getNameAsString();
|
||||||
|
if (i < num-1)
|
||||||
|
ObjCQIString += ',';
|
||||||
|
}
|
||||||
|
ObjCQIString += '>';
|
||||||
|
InnerString = ObjCQIString + InnerString;
|
||||||
|
}
|
||||||
|
|
||||||
void TagType::getAsStringInternal(std::string &InnerString) const {
|
void TagType::getAsStringInternal(std::string &InnerString) const {
|
||||||
if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
|
if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
|
||||||
InnerString = ' ' + InnerString;
|
InnerString = ' ' + InnerString;
|
||||||
|
|
|
@ -151,6 +151,10 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS) {
|
||||||
// id<protocol-list>
|
// id<protocol-list>
|
||||||
Result = Context.getObjCQualifiedIdType((ObjCProtocolDecl**)PQ,
|
Result = Context.getObjCQualifiedIdType((ObjCProtocolDecl**)PQ,
|
||||||
DS.getNumProtocolQualifiers());
|
DS.getNumProtocolQualifiers());
|
||||||
|
else if (Result == Context.getObjCClassType())
|
||||||
|
// Support the following GCC extension: Class<protocol-list>
|
||||||
|
Result = Context.getObjCQualifiedClassType((ObjCProtocolDecl**)PQ,
|
||||||
|
DS.getNumProtocolQualifiers());
|
||||||
else
|
else
|
||||||
Diag(DS.getSourceRange().getBegin(),
|
Diag(DS.getSourceRange().getBegin(),
|
||||||
diag::warn_ignoring_objc_qualifiers) << DS.getSourceRange();
|
diag::warn_ignoring_objc_qualifiers) << DS.getSourceRange();
|
||||||
|
|
|
@ -27,3 +27,8 @@ typedef int NotAnObjCObjectType;
|
||||||
|
|
||||||
// GCC doesn't diagnose this.
|
// GCC doesn't diagnose this.
|
||||||
NotAnObjCObjectType <SomeProtocol> *obj; // expected-warning {{ignoring protocol qualifiers on non-ObjC type}}
|
NotAnObjCObjectType <SomeProtocol> *obj; // expected-warning {{ignoring protocol qualifiers on non-ObjC type}}
|
||||||
|
|
||||||
|
// GCC extension (sigh). Found while researching rdar://6497631
|
||||||
|
typedef struct objc_class *Class;
|
||||||
|
|
||||||
|
Class <SomeProtocol> UnfortunateGCCExtension;
|
||||||
|
|
Loading…
Reference in New Issue