More support for rewriting ObjC intefaces. Still some edge cases to handle...
llvm-svn: 43493
This commit is contained in:
parent
3f156de60d
commit
c54840433f
|
|
@ -295,13 +295,13 @@ ObjcMethodDecl::~ObjcMethodDecl() {
|
|||
///
|
||||
void ObjcInterfaceDecl::addInstanceVariablesToClass(ObjcIvarDecl **ivars,
|
||||
unsigned numIvars,
|
||||
SourceLocation RB) {
|
||||
SourceLocation RBrac) {
|
||||
NumIvars = numIvars;
|
||||
if (numIvars) {
|
||||
Ivars = new ObjcIvarDecl*[numIvars];
|
||||
memcpy(Ivars, ivars, numIvars*sizeof(ObjcIvarDecl*));
|
||||
}
|
||||
RBracLoc = RB;
|
||||
setLocEnd(RBrac);
|
||||
}
|
||||
|
||||
/// ObjcAddInstanceVariablesToClassImpl - Checks for correctness of Instance
|
||||
|
|
@ -335,7 +335,7 @@ void ObjcInterfaceDecl::addMethods(ObjcMethodDecl **insMethods,
|
|||
ClassMethods = new ObjcMethodDecl*[numClsMembers];
|
||||
memcpy(ClassMethods, clsMethods, numClsMembers*sizeof(ObjcMethodDecl*));
|
||||
}
|
||||
EndLoc = endLoc;
|
||||
AtEndLoc = endLoc;
|
||||
}
|
||||
|
||||
/// addMethods - Insert instance and methods declarations into
|
||||
|
|
|
|||
|
|
@ -264,6 +264,27 @@ void RewriteTest::RewriteForwardClassDecl(ObjcClassDecl *ClassDecl) {
|
|||
}
|
||||
|
||||
void RewriteTest::RewriteInterfaceDecl(ObjcInterfaceDecl *ClassDecl) {
|
||||
|
||||
SourceLocation LocStart = ClassDecl->getLocStart();
|
||||
SourceLocation LocEnd = ClassDecl->getLocEnd();
|
||||
|
||||
const char *startBuf = SM->getCharacterData(LocStart);
|
||||
const char *endBuf = SM->getCharacterData(LocEnd);
|
||||
|
||||
// FIXME: need to consider empty class decls (no vars, methods)...
|
||||
// @interface NSConstantString : NSSimpleCString
|
||||
// @end
|
||||
|
||||
if (*endBuf != '>' && *endBuf != '}')
|
||||
// we have an identifier - scan ahead until the end of token.
|
||||
endBuf = strchr(endBuf, ' '); // FIXME: implement correctly.
|
||||
|
||||
std::string ResultStr;
|
||||
SynthesizeObjcInternalStruct(ClassDecl, ResultStr);
|
||||
|
||||
Rewrite.ReplaceText(LocStart, endBuf-startBuf+1,
|
||||
ResultStr.c_str(), ResultStr.size());
|
||||
|
||||
int nInstanceMethods = ClassDecl->getNumInstanceMethods();
|
||||
ObjcMethodDecl **instanceMethods = ClassDecl->getInstanceMethods();
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ MinimalAction::ActOnStartClassInterface(SourceLocation AtInterafceLoc,
|
|||
IdentifierInfo *ClassName, SourceLocation ClassLoc,
|
||||
IdentifierInfo *SuperName, SourceLocation SuperLoc,
|
||||
IdentifierInfo **ProtocolNames, unsigned NumProtocols,
|
||||
AttributeList *AttrList) {
|
||||
SourceLocation EndProtoLoc, AttributeList *AttrList) {
|
||||
TypeNameInfo *TI =
|
||||
new TypeNameInfo(1, ClassName->getFETokenInfo<TypeNameInfo>());
|
||||
|
||||
|
|
|
|||
|
|
@ -407,8 +407,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
|
|||
DS.Range.setEnd(Tok.getLocation());
|
||||
ConsumeToken(); // The identifier
|
||||
if (Tok.is(tok::less)) {
|
||||
SourceLocation endProtoLoc;
|
||||
llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
|
||||
ParseObjCProtocolReferences(ProtocolRefs);
|
||||
ParseObjCProtocolReferences(ProtocolRefs, endProtoLoc);
|
||||
llvm::SmallVector<DeclTy *, 8> *ProtocolDecl =
|
||||
new llvm::SmallVector<DeclTy *, 8>;
|
||||
DS.setProtocolQualifiers(ProtocolDecl);
|
||||
|
|
|
|||
|
|
@ -146,9 +146,10 @@ Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration(
|
|||
return 0;
|
||||
}
|
||||
rparenLoc = ConsumeParen();
|
||||
SourceLocation endProtoLoc;
|
||||
// Next, we need to check for any protocol references.
|
||||
if (Tok.is(tok::less)) {
|
||||
if (ParseObjCProtocolReferences(ProtocolRefs))
|
||||
if (ParseObjCProtocolReferences(ProtocolRefs, endProtoLoc))
|
||||
return 0;
|
||||
}
|
||||
if (attrList) // categories don't support attributes.
|
||||
|
|
@ -183,14 +184,15 @@ Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration(
|
|||
}
|
||||
// Next, we need to check for any protocol references.
|
||||
llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
|
||||
SourceLocation endProtoLoc;
|
||||
if (Tok.is(tok::less)) {
|
||||
if (ParseObjCProtocolReferences(ProtocolRefs))
|
||||
if (ParseObjCProtocolReferences(ProtocolRefs, endProtoLoc))
|
||||
return 0;
|
||||
}
|
||||
DeclTy *ClsType = Actions.ActOnStartClassInterface(
|
||||
atLoc, nameId, nameLoc,
|
||||
superClassId, superClassLoc, &ProtocolRefs[0],
|
||||
ProtocolRefs.size(), attrList);
|
||||
ProtocolRefs.size(), endProtoLoc, attrList);
|
||||
|
||||
if (Tok.is(tok::l_brace))
|
||||
ParseObjCClassInstanceVariables(ClsType, atLoc);
|
||||
|
|
@ -635,7 +637,8 @@ static bool CmpProtocolVals(const IdentifierInfo* const& lhs,
|
|||
/// '<' identifier-list '>'
|
||||
///
|
||||
bool Parser::ParseObjCProtocolReferences(
|
||||
llvm::SmallVectorImpl<IdentifierInfo*> &ProtocolRefs) {
|
||||
llvm::SmallVectorImpl<IdentifierInfo*> &ProtocolRefs, SourceLocation &endLoc)
|
||||
{
|
||||
assert(Tok.is(tok::less) && "expected <");
|
||||
|
||||
ConsumeToken(); // the "<"
|
||||
|
|
@ -661,9 +664,13 @@ bool Parser::ParseObjCProtocolReferences(
|
|||
// Make protocol names unique.
|
||||
ProtocolRefs.erase(std::unique(ProtocolRefs.begin(), ProtocolRefs.end()),
|
||||
ProtocolRefs.end());
|
||||
|
||||
// Consume the '>'.
|
||||
return ExpectAndConsume(tok::greater, diag::err_expected_greater);
|
||||
if (Tok.is(tok::greater)) {
|
||||
endLoc = ConsumeAnyToken();
|
||||
return false;
|
||||
}
|
||||
Diag(Tok, diag::err_expected_greater);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// objc-class-instance-variables:
|
||||
|
|
@ -811,15 +818,16 @@ Parser::DeclTy *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc) {
|
|||
&ProtocolRefs[0],
|
||||
ProtocolRefs.size());
|
||||
// Last, and definitely not least, parse a protocol declaration.
|
||||
SourceLocation endProtoLoc;
|
||||
if (Tok.is(tok::less)) {
|
||||
if (ParseObjCProtocolReferences(ProtocolRefs))
|
||||
if (ParseObjCProtocolReferences(ProtocolRefs, endProtoLoc))
|
||||
return 0;
|
||||
}
|
||||
|
||||
DeclTy *ProtoType = Actions.ActOnStartProtocolInterface(AtLoc,
|
||||
protocolName, nameLoc,
|
||||
&ProtocolRefs[0],
|
||||
ProtocolRefs.size());
|
||||
ProtocolRefs.size(), endProtoLoc);
|
||||
ParseObjCInterfaceDeclList(ProtoType, tok::objc_protocol);
|
||||
|
||||
// The @ sign was already consumed by ParseObjCInterfaceDeclList().
|
||||
|
|
|
|||
|
|
@ -235,9 +235,10 @@ Parser::StmtResult Parser::ParseIdentifierStatement(bool OnlyStatement) {
|
|||
IdentTok.getLocation(), PrevSpec,
|
||||
TypeRep);
|
||||
assert(!isInvalid && "First declspec can't be invalid!");
|
||||
SourceLocation endProtoLoc;
|
||||
if (Tok.is(tok::less)) {
|
||||
llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
|
||||
ParseObjCProtocolReferences(ProtocolRefs);
|
||||
ParseObjCProtocolReferences(ProtocolRefs, endProtoLoc);
|
||||
llvm::SmallVector<DeclTy *, 8> *ProtocolDecl =
|
||||
new llvm::SmallVector<DeclTy *, 8>;
|
||||
DS.setProtocolQualifiers(ProtocolDecl);
|
||||
|
|
|
|||
|
|
@ -472,7 +472,7 @@ public:
|
|||
IdentifierInfo *ClassName, SourceLocation ClassLoc,
|
||||
IdentifierInfo *SuperName, SourceLocation SuperLoc,
|
||||
IdentifierInfo **ProtocolNames, unsigned NumProtocols,
|
||||
AttributeList *AttrList);
|
||||
SourceLocation EndProtoLoc, AttributeList *AttrList);
|
||||
|
||||
virtual DeclTy *ActOnCompatiblityAlias(
|
||||
SourceLocation AtCompatibilityAliasLoc,
|
||||
|
|
@ -482,7 +482,8 @@ public:
|
|||
virtual DeclTy *ActOnStartProtocolInterface(
|
||||
SourceLocation AtProtoInterfaceLoc,
|
||||
IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc,
|
||||
IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs);
|
||||
IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs,
|
||||
SourceLocation EndProtoLoc);
|
||||
|
||||
virtual DeclTy *ActOnStartCategoryInterface(
|
||||
SourceLocation AtInterfaceLoc,
|
||||
|
|
|
|||
|
|
@ -941,7 +941,7 @@ Sema::DeclTy *Sema::ActOnStartClassInterface(
|
|||
IdentifierInfo *ClassName, SourceLocation ClassLoc,
|
||||
IdentifierInfo *SuperName, SourceLocation SuperLoc,
|
||||
IdentifierInfo **ProtocolNames, unsigned NumProtocols,
|
||||
AttributeList *AttrList) {
|
||||
SourceLocation EndProtoLoc, AttributeList *AttrList) {
|
||||
assert(ClassName && "Missing class identifier");
|
||||
|
||||
// Check for another declaration kind with the same name.
|
||||
|
|
@ -958,6 +958,7 @@ Sema::DeclTy *Sema::ActOnStartClassInterface(
|
|||
if (!IDecl->isForwardDecl())
|
||||
Diag(AtInterfaceLoc, diag::err_duplicate_class_def, IDecl->getName());
|
||||
else {
|
||||
IDecl->setLocation(AtInterfaceLoc);
|
||||
IDecl->setForwardDecl(false);
|
||||
IDecl->AllocIntfRefProtocols(NumProtocols);
|
||||
}
|
||||
|
|
@ -994,18 +995,23 @@ Sema::DeclTy *Sema::ActOnStartClassInterface(
|
|||
}
|
||||
}
|
||||
IDecl->setSuperClass(SuperClassEntry);
|
||||
IDecl->setLocEnd(SuperLoc);
|
||||
} else { // we have a root class.
|
||||
IDecl->setLocEnd(ClassLoc);
|
||||
}
|
||||
|
||||
/// Check then save referenced protocols
|
||||
for (unsigned int i = 0; i != NumProtocols; i++) {
|
||||
ObjcProtocolDecl* RefPDecl = ObjcProtocols[ProtocolNames[i]];
|
||||
if (!RefPDecl || RefPDecl->isForwardDecl())
|
||||
Diag(ClassLoc, diag::err_undef_protocolref,
|
||||
ProtocolNames[i]->getName(),
|
||||
ClassName->getName());
|
||||
IDecl->setIntfRefProtocols((int)i, RefPDecl);
|
||||
if (NumProtocols) {
|
||||
for (unsigned int i = 0; i != NumProtocols; i++) {
|
||||
ObjcProtocolDecl* RefPDecl = ObjcProtocols[ProtocolNames[i]];
|
||||
if (!RefPDecl || RefPDecl->isForwardDecl())
|
||||
Diag(ClassLoc, diag::err_undef_protocolref,
|
||||
ProtocolNames[i]->getName(),
|
||||
ClassName->getName());
|
||||
IDecl->setIntfRefProtocols((int)i, RefPDecl);
|
||||
}
|
||||
IDecl->setLocEnd(EndProtoLoc);
|
||||
}
|
||||
|
||||
return IDecl;
|
||||
}
|
||||
|
||||
|
|
@ -1055,7 +1061,8 @@ Sema::DeclTy *Sema::ActOnCompatiblityAlias(
|
|||
Sema::DeclTy *Sema::ActOnStartProtocolInterface(
|
||||
SourceLocation AtProtoInterfaceLoc,
|
||||
IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc,
|
||||
IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs) {
|
||||
IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs,
|
||||
SourceLocation EndProtoLoc) {
|
||||
assert(ProtocolName && "Missing protocol identifier");
|
||||
ObjcProtocolDecl *PDecl = ObjcProtocols[ProtocolName];
|
||||
if (PDecl) {
|
||||
|
|
|
|||
|
|
@ -74,8 +74,8 @@ class ObjcInterfaceDecl : public TypeDecl {
|
|||
|
||||
bool ForwardDecl; // declared with @class.
|
||||
|
||||
SourceLocation RBracLoc; // marks the end of the instance variables.
|
||||
SourceLocation EndLoc; // marks the end of the entire interface.
|
||||
SourceLocation EndLoc; // marks the '>', '}', or identifier.
|
||||
SourceLocation AtEndLoc; // marks the end of the entire interface.
|
||||
public:
|
||||
ObjcInterfaceDecl(SourceLocation atLoc, unsigned numRefProtos,
|
||||
IdentifierInfo *Id, bool FD = false)
|
||||
|
|
@ -137,14 +137,14 @@ public:
|
|||
ObjcMethodDecl *lookupInstanceMethod(Selector &Sel);
|
||||
ObjcMethodDecl *lookupClassMethod(Selector &Sel);
|
||||
|
||||
// Location information, modeled after the Stmt API. For interfaces,
|
||||
// which are fairly course grain, the end refers to the '}' token.
|
||||
// Location information, modeled after the Stmt API.
|
||||
SourceLocation getLocStart() const { return getLocation(); } // '@'interface
|
||||
SourceLocation getLocEnd() const { return RBracLoc; }
|
||||
SourceLocation getLocEnd() const { return EndLoc; }
|
||||
void setLocEnd(SourceLocation LE) { EndLoc = LE; };
|
||||
|
||||
// We also need to record the @end location.
|
||||
SourceLocation getAtEndLoc() const { return EndLoc; }
|
||||
|
||||
SourceLocation getAtEndLoc() const { return AtEndLoc; }
|
||||
|
||||
/// ImplicitInterfaceDecl - check that this is an implicitely declared
|
||||
/// ObjcInterfaceDecl node. This is for legacy objective-c @implementation
|
||||
/// declaration without an @interface declaration.
|
||||
|
|
|
|||
|
|
@ -465,6 +465,7 @@ public:
|
|||
SourceLocation SuperLoc,
|
||||
IdentifierInfo **ProtocolNames,
|
||||
unsigned NumProtocols,
|
||||
SourceLocation EndProtoLoc,
|
||||
AttributeList *AttrList) {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -485,7 +486,8 @@ public:
|
|||
IdentifierInfo *ProtocolName,
|
||||
SourceLocation ProtocolLoc,
|
||||
IdentifierInfo **ProtoRefNames,
|
||||
unsigned NumProtoRefs) {
|
||||
unsigned NumProtoRefs,
|
||||
SourceLocation EndProtoLoc) {
|
||||
return 0;
|
||||
}
|
||||
// ActOnStartCategoryInterface - this action is called immdiately after
|
||||
|
|
@ -654,7 +656,7 @@ public:
|
|||
IdentifierInfo *ClassName, SourceLocation ClassLoc,
|
||||
IdentifierInfo *SuperName, SourceLocation SuperLoc,
|
||||
IdentifierInfo **ProtocolNames, unsigned NumProtocols,
|
||||
AttributeList *AttrList);
|
||||
SourceLocation EndProtoLoc, AttributeList *AttrList);
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
|
|
|||
|
|
@ -260,7 +260,8 @@ private:
|
|||
AttributeList *prefixAttrs = 0);
|
||||
void ParseObjCClassInstanceVariables(DeclTy *interfaceDecl,
|
||||
SourceLocation atLoc);
|
||||
bool ParseObjCProtocolReferences(llvm::SmallVectorImpl<IdentifierInfo*> &);
|
||||
bool ParseObjCProtocolReferences(llvm::SmallVectorImpl<IdentifierInfo*> &,
|
||||
SourceLocation &endProtoLoc);
|
||||
void ParseObjCInterfaceDeclList(DeclTy *interfaceDecl,
|
||||
tok::ObjCKeywordKind contextKey);
|
||||
DeclTy *ParseObjCAtProtocolDeclaration(SourceLocation atLoc);
|
||||
|
|
|
|||
Loading…
Reference in New Issue