forked from OSchip/llvm-project
Patch to create protocol conforming class types.
llvm-svn: 42856
This commit is contained in:
parent
e99c8329af
commit
70e8f1024a
|
@ -610,6 +610,31 @@ QualType ASTContext::getObjcInterfaceType(ObjcInterfaceDecl *Decl) {
|
|||
return QualType(Decl->TypeForDecl, 0);
|
||||
}
|
||||
|
||||
/// getObjcQualifiedInterfaceType - Return a
|
||||
/// ObjcQualifiedInterfaceType type for the given interface decl and
|
||||
/// the conforming protocol list.
|
||||
QualType ASTContext::getObjcQualifiedInterfaceType(ObjcInterfaceDecl *Decl,
|
||||
ObjcProtocolDecl **Protocols, unsigned NumProtocols) {
|
||||
ObjcInterfaceType *IType =
|
||||
cast<ObjcInterfaceType>(getObjcInterfaceType(Decl));
|
||||
|
||||
llvm::FoldingSetNodeID ID;
|
||||
ObjcQualifiedInterfaceType::Profile(ID, IType, Protocols, NumProtocols);
|
||||
|
||||
void *InsertPos = 0;
|
||||
if (ObjcQualifiedInterfaceType *QT =
|
||||
ObjcQualifiedInterfaceTypes.FindNodeOrInsertPos(ID, InsertPos))
|
||||
return QualType(QT, 0);
|
||||
|
||||
// No Match;
|
||||
ObjcQualifiedInterfaceType *QType = new ObjcQualifiedInterfaceType(IType);
|
||||
for (unsigned i = 0; i != NumProtocols; i++)
|
||||
QType->setProtocols(Protocols[i]);
|
||||
Types.push_back(QType);
|
||||
ObjcQualifiedInterfaceTypes.InsertNode(QType, InsertPos);
|
||||
return QualType(QType, 0);
|
||||
}
|
||||
|
||||
/// getTypeOfExpr - Unlike many "get<Type>" functions, we can't unique
|
||||
/// TypeOfExpr AST's (since expression's are never shared). For example,
|
||||
/// multiple declarations that refer to "typeof(x)" all contain different
|
||||
|
|
|
@ -618,6 +618,19 @@ void FunctionTypeProto::Profile(llvm::FoldingSetNodeID &ID) {
|
|||
Profile(ID, getResultType(), arg_type_begin(), NumArgs, isVariadic());
|
||||
}
|
||||
|
||||
void ObjcQualifiedInterfaceType::Profile(llvm::FoldingSetNodeID &ID,
|
||||
ObjcInterfaceType *interfaceType,
|
||||
ObjcProtocolDecl **protocols,
|
||||
unsigned NumProtocols) {
|
||||
ID.AddPointer(interfaceType);
|
||||
for (unsigned i = 0; i != NumProtocols; i++)
|
||||
ID.AddPointer(protocols[i]);
|
||||
}
|
||||
|
||||
void ObjcQualifiedInterfaceType::Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getInterfaceType(), &Protocols[0], getNumProtocols());
|
||||
}
|
||||
|
||||
/// LookThroughTypedefs - Return the ultimate type this typedef corresponds to
|
||||
/// potentially looking through *all* consequtive typedefs. This returns the
|
||||
/// sum of the type qualifiers, so if you have:
|
||||
|
@ -843,6 +856,18 @@ void ObjcInterfaceType::getAsStringInternal(std::string &InnerString) const {
|
|||
InnerString = getDecl()->getIdentifier()->getName() + InnerString;
|
||||
}
|
||||
|
||||
void ObjcQualifiedInterfaceType::getAsStringInternal(
|
||||
std::string &InnerString) const {
|
||||
InnerString = getInterfaceType()->getDecl()->getName() + '<';
|
||||
int num = getNumProtocols();
|
||||
for (int i = 0; i < num; i++) {
|
||||
InnerString += getProtocols(i)->getName();
|
||||
if (i < num-1)
|
||||
InnerString += ',';
|
||||
}
|
||||
InnerString += '>';
|
||||
}
|
||||
|
||||
void TagType::getAsStringInternal(std::string &InnerString) const {
|
||||
if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
|
||||
InnerString = ' ' + InnerString;
|
||||
|
|
|
@ -403,18 +403,20 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
|
|||
TypeRep);
|
||||
if (isInvalid)
|
||||
break;
|
||||
else { // FIXME: restrict this to "id" and ObjC classnames.
|
||||
DS.Range.setEnd(Tok.getLocation());
|
||||
ConsumeToken(); // The identifier
|
||||
if (Tok.is(tok::less)) {
|
||||
llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
|
||||
ParseObjCProtocolReferences(ProtocolRefs);
|
||||
Actions.ActOnFindProtocolDeclaration(Loc,
|
||||
&ProtocolRefs[0],
|
||||
ProtocolRefs.size());
|
||||
}
|
||||
continue;
|
||||
// FIXME: restrict this to "id" and ObjC classnames.
|
||||
DS.Range.setEnd(Tok.getLocation());
|
||||
ConsumeToken(); // The identifier
|
||||
if (Tok.is(tok::less)) {
|
||||
llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
|
||||
ParseObjCProtocolReferences(ProtocolRefs);
|
||||
llvm::SmallVector<DeclTy *, 8> *ProtocolDecl =
|
||||
new llvm::SmallVector<DeclTy *, 8>;
|
||||
DS.setProtocolQualifiers(ProtocolDecl);
|
||||
Actions.FindProtocolDeclaration(Loc,
|
||||
&ProtocolRefs[0], ProtocolRefs.size(),
|
||||
*ProtocolDecl);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// FALL THROUGH.
|
||||
|
|
|
@ -378,9 +378,9 @@ Parser::DeclTy *Parser::ParseObjCMethodPrototype(DeclTy *IDecl,
|
|||
assert((Tok.is(tok::minus) || Tok.is(tok::plus)) && "expected +/-");
|
||||
|
||||
tok::TokenKind methodType = Tok.getKind();
|
||||
SourceLocation methodLoc = ConsumeToken();
|
||||
ConsumeToken();
|
||||
|
||||
DeclTy *MDecl = ParseObjCMethodDecl(methodType, methodLoc, MethodImplKind);
|
||||
DeclTy *MDecl = ParseObjCMethodDecl(methodType, MethodImplKind);
|
||||
// Since this rule is used for both method declarations and definitions,
|
||||
// the caller is (optionally) responsible for consuming the ';'.
|
||||
return MDecl;
|
||||
|
@ -394,7 +394,7 @@ Parser::DeclTy *Parser::ParseObjCMethodPrototype(DeclTy *IDecl,
|
|||
/// unsigned long const short volatile signed restrict _Complex
|
||||
/// in out inout bycopy byref oneway int char float double void _Bool
|
||||
///
|
||||
IdentifierInfo *Parser::ParseObjCSelector() {
|
||||
IdentifierInfo *Parser::ParseObjCSelector(SourceLocation &SelectorLoc) {
|
||||
switch (Tok.getKind()) {
|
||||
default:
|
||||
return 0;
|
||||
|
@ -438,7 +438,7 @@ IdentifierInfo *Parser::ParseObjCSelector() {
|
|||
case tok::kw__Bool:
|
||||
case tok::kw__Complex:
|
||||
IdentifierInfo *II = Tok.getIdentifierInfo();
|
||||
ConsumeToken();
|
||||
SelectorLoc = ConsumeToken();
|
||||
return II;
|
||||
}
|
||||
}
|
||||
|
@ -526,15 +526,14 @@ Parser::TypeTy *Parser::ParseObjCTypeName() {
|
|||
/// __attribute__((unused))
|
||||
///
|
||||
Parser::DeclTy *Parser::ParseObjCMethodDecl(tok::TokenKind mType,
|
||||
SourceLocation mLoc,
|
||||
tok::ObjCKeywordKind MethodImplKind)
|
||||
{
|
||||
// Parse the return type.
|
||||
TypeTy *ReturnType = 0;
|
||||
if (Tok.is(tok::l_paren))
|
||||
ReturnType = ParseObjCTypeName();
|
||||
|
||||
IdentifierInfo *SelIdent = ParseObjCSelector();
|
||||
SourceLocation mLoc;
|
||||
IdentifierInfo *SelIdent = ParseObjCSelector(mLoc);
|
||||
if (Tok.isNot(tok::colon)) {
|
||||
if (!SelIdent) {
|
||||
Diag(Tok, diag::err_expected_ident); // missing selector name.
|
||||
|
@ -584,7 +583,8 @@ Parser::DeclTy *Parser::ParseObjCMethodDecl(tok::TokenKind mType,
|
|||
ConsumeToken(); // Eat the identifier.
|
||||
|
||||
// Check for another keyword selector.
|
||||
SelIdent = ParseObjCSelector();
|
||||
SourceLocation Loc;
|
||||
SelIdent = ParseObjCSelector(Loc);
|
||||
if (!SelIdent && Tok.isNot(tok::colon))
|
||||
break;
|
||||
// We have a selector or a colon, continue parsing.
|
||||
|
@ -1175,7 +1175,8 @@ Parser::ExprResult Parser::ParseObjCMessageExpression() {
|
|||
ReceiverExpr = Res.Val;
|
||||
}
|
||||
// Parse objc-selector
|
||||
IdentifierInfo *selIdent = ParseObjCSelector();
|
||||
SourceLocation Loc;
|
||||
IdentifierInfo *selIdent = ParseObjCSelector(Loc);
|
||||
|
||||
llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
|
||||
llvm::SmallVector<Action::ExprTy *, 12> KeyExprs;
|
||||
|
@ -1201,7 +1202,7 @@ Parser::ExprResult Parser::ParseObjCMessageExpression() {
|
|||
KeyExprs.push_back(Res.Val);
|
||||
|
||||
// Check for another keyword selector.
|
||||
selIdent = ParseObjCSelector();
|
||||
selIdent = ParseObjCSelector(Loc);
|
||||
if (!selIdent && Tok.isNot(tok::colon))
|
||||
break;
|
||||
// We have a selector or a colon, continue parsing.
|
||||
|
|
|
@ -449,9 +449,11 @@ public:
|
|||
IdentifierInfo **IdentList,
|
||||
unsigned NumElts);
|
||||
|
||||
virtual DeclTy **ActOnFindProtocolDeclaration(SourceLocation TypeLoc,
|
||||
IdentifierInfo **ProtocolId,
|
||||
unsigned NumProtocols);
|
||||
virtual void FindProtocolDeclaration(SourceLocation TypeLoc,
|
||||
IdentifierInfo **ProtocolId,
|
||||
unsigned NumProtocols,
|
||||
llvm::SmallVector<DeclTy *, 8> &
|
||||
Protocols);
|
||||
|
||||
virtual void ActOnAddMethodsToObjcDecl(Scope* S, DeclTy *ClassDecl,
|
||||
DeclTy **allMethods, unsigned allNum);
|
||||
|
|
|
@ -987,20 +987,22 @@ Sema::DeclTy *Sema::ActOnStartProtocolInterface(
|
|||
return PDecl;
|
||||
}
|
||||
|
||||
/// ActOnFindProtocolDeclaration - This routine looks for a previously
|
||||
/// declared protocol and returns it. If not found, issues diagnostic.
|
||||
/// Will build a list of previously protocol declarations found in the list.
|
||||
Action::DeclTy **
|
||||
Sema::ActOnFindProtocolDeclaration(SourceLocation TypeLoc,
|
||||
IdentifierInfo **ProtocolId,
|
||||
unsigned NumProtocols) {
|
||||
/// FindProtocolDeclaration - This routine looks up protocols and
|
||||
/// issuer error if they are not declared. It returns list of protocol
|
||||
/// declarations in its 'Protocols' argument.
|
||||
void
|
||||
Sema::FindProtocolDeclaration(SourceLocation TypeLoc,
|
||||
IdentifierInfo **ProtocolId,
|
||||
unsigned NumProtocols,
|
||||
llvm::SmallVector<DeclTy *,8> &Protocols) {
|
||||
for (unsigned i = 0; i != NumProtocols; ++i) {
|
||||
ObjcProtocolDecl *PDecl = ObjcProtocols[ProtocolId[i]];
|
||||
if (!PDecl)
|
||||
Diag(TypeLoc, diag::err_undeclared_protocol,
|
||||
ProtocolId[i]->getName());
|
||||
else
|
||||
Protocols.push_back(PDecl);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// ActOnForwardProtocolDeclaration -
|
||||
|
|
|
@ -104,8 +104,15 @@ static QualType ConvertDeclSpecToType(const DeclSpec &DS, ASTContext &Ctx) {
|
|||
"Can't handle qualifiers on typedef names yet!");
|
||||
// FIXME: Adding a TST_objcInterface clause doesn't seem ideal, so
|
||||
// we have this "hack" for now...
|
||||
if (isa<ObjcInterfaceDecl>(D))
|
||||
return Ctx.getObjcInterfaceType(cast<ObjcInterfaceDecl>(D));
|
||||
if (ObjcInterfaceDecl *ObjcIntDecl = dyn_cast<ObjcInterfaceDecl>(D)) {
|
||||
if (DS.getProtocolQualifiers() == 0)
|
||||
return Ctx.getObjcInterfaceType(ObjcIntDecl);
|
||||
|
||||
Action::DeclTy **PPDecl = &(*DS.getProtocolQualifiers())[0];
|
||||
return Ctx.getObjcQualifiedInterfaceType(ObjcIntDecl,
|
||||
reinterpret_cast<ObjcProtocolDecl**>(PPDecl),
|
||||
DS.NumProtocolQualifiers());
|
||||
}
|
||||
// TypeQuals handled by caller.
|
||||
return Ctx.getTypedefType(cast<TypedefDecl>(D));
|
||||
}
|
||||
|
|
|
@ -739,6 +739,7 @@
|
|||
08FB7793FE84155DC02AAC07 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
|
||||
compatibilityVersion = "Xcode 2.4";
|
||||
hasScannedForEncodings = 1;
|
||||
mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
|
||||
projectDirPath = "";
|
||||
|
|
|
@ -38,6 +38,7 @@ class ASTContext {
|
|||
llvm::FoldingSet<VectorType> VectorTypes;
|
||||
llvm::FoldingSet<FunctionTypeNoProto> FunctionTypeNoProtos;
|
||||
llvm::FoldingSet<FunctionTypeProto> FunctionTypeProtos;
|
||||
llvm::FoldingSet<ObjcQualifiedInterfaceType> ObjcQualifiedInterfaceTypes;
|
||||
llvm::DenseMap<const RecordDecl*, const RecordLayout*> RecordLayoutInfo;
|
||||
RecordDecl *CFConstantStringTypeDecl;
|
||||
public:
|
||||
|
@ -118,6 +119,12 @@ public:
|
|||
/// specified typename decl.
|
||||
QualType getTypedefType(TypedefDecl *Decl);
|
||||
QualType getObjcInterfaceType(ObjcInterfaceDecl *Decl);
|
||||
|
||||
/// getObjcQualifiedInterfaceType - Return a
|
||||
/// ObjcQualifiedInterfaceType type for the given interface decl and
|
||||
/// the conforming protocol list.
|
||||
QualType getObjcQualifiedInterfaceType(ObjcInterfaceDecl *Decl,
|
||||
ObjcProtocolDecl **ProtocolList, unsigned NumProtocols);
|
||||
|
||||
/// getTypeOfType - GCC extension.
|
||||
QualType getTypeOfExpr(Expr *e);
|
||||
|
|
|
@ -47,6 +47,7 @@ namespace clang {
|
|||
class FunctionType;
|
||||
class OCUVectorType;
|
||||
class BuiltinType;
|
||||
class ObjcQualifiedInterfaceType;
|
||||
|
||||
/// QualType - For efficiency, we don't store CVR-qualified types as nodes on
|
||||
/// their own: instead each reference to a type stores the qualifiers. This
|
||||
|
@ -817,6 +818,7 @@ public:
|
|||
|
||||
class ObjcInterfaceType : public Type {
|
||||
ObjcInterfaceDecl *Decl;
|
||||
|
||||
ObjcInterfaceType(ObjcInterfaceDecl *D) :
|
||||
Type(ObjcInterface, QualType()), Decl(D) { }
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
|
@ -825,7 +827,7 @@ public:
|
|||
ObjcInterfaceDecl *getDecl() const { return Decl; }
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString) const;
|
||||
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == ObjcInterface;
|
||||
}
|
||||
|
@ -836,7 +838,7 @@ public:
|
|||
/// conforming to a list of protocols; such as, INTF<Proto1, Proto2, Proto1>.
|
||||
/// Duplicate protocols are removed and protocol list is canonicalized to be in
|
||||
/// alphabetical order.
|
||||
class ObjcQualifiedInterfaceType : public Type {
|
||||
class ObjcQualifiedInterfaceType : public Type, public llvm::FoldingSetNode {
|
||||
// Interface type for this protocol conforming object type
|
||||
ObjcInterfaceType *InterfaceType;
|
||||
|
||||
|
@ -846,10 +848,29 @@ class ObjcQualifiedInterfaceType : public Type {
|
|||
|
||||
ObjcQualifiedInterfaceType(ObjcInterfaceType *T) :
|
||||
Type(ObjcQualifiedInterface, QualType()), InterfaceType(T) { }
|
||||
|
||||
void setProtocols(ObjcProtocolDecl *pType) {
|
||||
Protocols.push_back(pType);
|
||||
}
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
public:
|
||||
|
||||
ObjcInterfaceType *getInterfaceType() const { return InterfaceType; }
|
||||
|
||||
|
||||
ObjcProtocolDecl *getProtocols(unsigned i) const {
|
||||
return Protocols[i];
|
||||
}
|
||||
unsigned getNumProtocols() const {
|
||||
return Protocols.size();
|
||||
}
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString) const;
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID);
|
||||
static void Profile(llvm::FoldingSetNodeID &ID,
|
||||
ObjcInterfaceType *interfaceType,
|
||||
ObjcProtocolDecl **protocols, unsigned NumProtocols);
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == ObjcQualifiedInterface;
|
||||
}
|
||||
|
|
|
@ -552,13 +552,14 @@ public:
|
|||
return 0;
|
||||
}
|
||||
|
||||
/// ActOnFindProtocolDeclaration - This routine looks for a previously
|
||||
/// declared protocol and returns it. If not found, issues diagnostic.
|
||||
/// Will build a list of previously protocol declarations found in the list.
|
||||
virtual DeclTy **ActOnFindProtocolDeclaration(SourceLocation TypeLoc,
|
||||
IdentifierInfo **ProtocolId,
|
||||
unsigned NumProtocols) {
|
||||
return 0;
|
||||
/// FindProtocolDeclaration - This routine looks up protocols and
|
||||
/// issues error if they are not declared. It returns list of valid
|
||||
/// protocols found.
|
||||
virtual void FindProtocolDeclaration(SourceLocation TypeLoc,
|
||||
IdentifierInfo **ProtocolId,
|
||||
unsigned NumProtocols,
|
||||
llvm::SmallVector<DeclTy *, 8> &
|
||||
Protocols) {
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -124,6 +124,9 @@ private:
|
|||
// attributes.
|
||||
AttributeList *AttrList;
|
||||
|
||||
// List of protocol qualifiers for objective-c classes.
|
||||
llvm::SmallVector<Action::DeclTy *, 8> *ProtocolQualifiers;
|
||||
|
||||
// SourceLocation info. These are null if the item wasn't specified or if
|
||||
// the setting was synthesized.
|
||||
SourceLocation StorageClassSpecLoc, SCS_threadLoc;
|
||||
|
@ -142,10 +145,12 @@ public:
|
|||
TypeQualifiers(TSS_unspecified),
|
||||
FS_inline_specified(false),
|
||||
TypeRep(0),
|
||||
AttrList(0) {
|
||||
AttrList(0),
|
||||
ProtocolQualifiers(0) {
|
||||
}
|
||||
~DeclSpec() {
|
||||
delete AttrList;
|
||||
delete ProtocolQualifiers;
|
||||
}
|
||||
// storage-class-specifier
|
||||
SCS getStorageClassSpec() const { return StorageClassSpec; }
|
||||
|
@ -248,6 +253,15 @@ public:
|
|||
}
|
||||
AttributeList *getAttributes() const { return AttrList; }
|
||||
|
||||
llvm::SmallVector<Action::DeclTy *, 8> *getProtocolQualifiers() const {
|
||||
return ProtocolQualifiers;
|
||||
}
|
||||
void setProtocolQualifiers(llvm::SmallVector<Action::DeclTy *, 8> *protos) {
|
||||
ProtocolQualifiers = protos;
|
||||
}
|
||||
unsigned NumProtocolQualifiers() const {
|
||||
return ProtocolQualifiers ? ProtocolQualifiers->size() : 0;
|
||||
}
|
||||
/// Finish - This does final analysis of the declspec, issuing diagnostics for
|
||||
/// things like "_Imaginary" (lacking an FP type). After calling this method,
|
||||
/// DeclSpec is guaranteed self-consistent, even if an error occurred.
|
||||
|
|
|
@ -275,7 +275,7 @@ private:
|
|||
DeclTy *ParseObjCTryStmt(SourceLocation atLoc);
|
||||
DeclTy *ParseObjCThrowStmt(SourceLocation atLoc);
|
||||
|
||||
IdentifierInfo *ParseObjCSelector();
|
||||
IdentifierInfo *ParseObjCSelector(SourceLocation &MethodLocation);
|
||||
// Definitions for Objective-c context sensitive keywords recognition.
|
||||
enum ObjCTypeQual {
|
||||
objc_in=0, objc_out, objc_inout, objc_oneway, objc_bycopy, objc_byref,
|
||||
|
@ -295,7 +295,7 @@ private:
|
|||
void ParseObjCMethodRequirement();
|
||||
DeclTy *ParseObjCMethodPrototype(DeclTy *classOrCat,
|
||||
tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword);
|
||||
DeclTy *ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation mLoc,
|
||||
DeclTy *ParseObjCMethodDecl(tok::TokenKind mType,
|
||||
tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword);
|
||||
void ParseObjCPropertyAttribute(DeclTy *interfaceDecl);
|
||||
void ParseObjCPropertyDecl(DeclTy *interfaceDecl);
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
// RUN: clang -fsyntax-only -verify %s
|
||||
|
||||
@protocol P1 @end
|
||||
@protocol P2 @end
|
||||
@protocol P3 @end
|
||||
|
||||
@interface INTF
|
||||
- (INTF*) METH1; // expected-error {{previous declaration is here}}
|
||||
- (INTF<P1>*) METH1; // expected-error {{duplicate declaration of method 'METH1'}}
|
||||
|
||||
- (INTF<P1,P2>*) METH2;
|
||||
- (INTF<P2,P1>*) METH2; // expected-error {{previous declaration is here}}
|
||||
- (INTF<P2,P1,P3>*) METH2; // expected-error {{duplicate declaration of method 'METH2'}}
|
||||
|
||||
- (INTF<P2,P1,P3>*) METH3;
|
||||
- (INTF<P3,P1,P2, P3>*) METH3;
|
||||
|
||||
@end
|
||||
|
||||
INTF<P2,P1,P3>* p1;
|
||||
|
Loading…
Reference in New Issue