зеркало из https://github.com/microsoft/clang-1.git
Add category method definitions incrementally, removing a FIXME (like we do for class implementations).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@44027 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
cffff84007
Коммит
e1e6c0d5c7
47
AST/Decl.cpp
47
AST/Decl.cpp
|
@ -388,26 +388,6 @@ void ObjcCategoryDecl::addMethods(ObjcMethodDecl **insMethods,
|
|||
AtEndLoc = endLoc;
|
||||
}
|
||||
|
||||
/// addMethods - Insert instance and methods declarations into
|
||||
/// ObjcCategoryImplDecl's CatInsMethods and CatClsMethods fields.
|
||||
///
|
||||
void ObjcCategoryImplDecl::addMethods(ObjcMethodDecl **insMethods,
|
||||
unsigned numInsMembers,
|
||||
ObjcMethodDecl **clsMethods,
|
||||
unsigned numClsMembers,
|
||||
SourceLocation AtEndLoc) {
|
||||
NumInstanceMethods = numInsMembers;
|
||||
if (numInsMembers) {
|
||||
InstanceMethods = new ObjcMethodDecl*[numInsMembers];
|
||||
memcpy(InstanceMethods, insMethods, numInsMembers*sizeof(ObjcMethodDecl*));
|
||||
}
|
||||
NumClassMethods = numClsMembers;
|
||||
if (numClsMembers) {
|
||||
ClassMethods = new ObjcMethodDecl*[numClsMembers];
|
||||
memcpy(ClassMethods, clsMethods, numClsMembers*sizeof(ObjcMethodDecl*));
|
||||
}
|
||||
}
|
||||
|
||||
ObjcIvarDecl *ObjcInterfaceDecl::lookupInstanceVariable(
|
||||
IdentifierInfo *ID, ObjcInterfaceDecl *&clsDeclared) {
|
||||
ObjcInterfaceDecl* ClassDecl = this;
|
||||
|
@ -535,3 +515,30 @@ ObjcMethodDecl *ObjcImplementationDecl::lookupClassMethod(Selector &Sel) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// lookupInstanceMethod - This method returns an instance method by looking in
|
||||
// the class implementation. Unlike interfaces, we don't look outside the
|
||||
// implementation.
|
||||
ObjcMethodDecl *ObjcCategoryImplDecl::lookupInstanceMethod(Selector &Sel) {
|
||||
ObjcMethodDecl *const*methods = getInstanceMethods();
|
||||
int methodCount = getNumInstanceMethods();
|
||||
for (int i = 0; i < methodCount; ++i) {
|
||||
if (methods[i]->getSelector() == Sel) {
|
||||
return methods[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// lookupClassMethod - This method returns an instance method by looking in
|
||||
// the class implementation. Unlike interfaces, we don't look outside the
|
||||
// implementation.
|
||||
ObjcMethodDecl *ObjcCategoryImplDecl::lookupClassMethod(Selector &Sel) {
|
||||
ObjcMethodDecl *const*methods = getClassMethods();
|
||||
int methodCount = getNumClassMethods();
|
||||
for (int i = 0; i < methodCount; ++i) {
|
||||
if (methods[i]->getSelector() == Sel) {
|
||||
return methods[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -1522,7 +1522,7 @@ void Sema::ImplCategoryMethodsVsIntfMethods(ObjcCategoryImplDecl *CatImplDecl,
|
|||
llvm::DenseSet<Selector> InsMap;
|
||||
// Check and see if instance methods in category interface have been
|
||||
// implemented in its implementation class.
|
||||
ObjcMethodDecl **methods = CatImplDecl->getInstanceMethods();
|
||||
ObjcMethodDecl *const*methods = CatImplDecl->getInstanceMethods();
|
||||
for (int i=0; i < CatImplDecl->getNumInstanceMethods(); i++)
|
||||
InsMap.insert(methods[i]->getSelector());
|
||||
|
||||
|
@ -2070,8 +2070,7 @@ void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclTy *classDecl,
|
|||
ImplMethodsVsClassMethods(IC, IDecl);
|
||||
} else {
|
||||
ObjcCategoryImplDecl* CatImplClass = cast<ObjcCategoryImplDecl>(ClassDecl);
|
||||
CatImplClass->addMethods(&insMethods[0], insMethods.size(),
|
||||
&clsMethods[0], clsMethods.size(), AtEndLoc);
|
||||
CatImplClass->setLocEnd(AtEndLoc);
|
||||
ObjcInterfaceDecl* IDecl = CatImplClass->getClassInterface();
|
||||
// Find category interface decl and then check that all methods declared
|
||||
// in this interface is implemented in the category @implementation.
|
||||
|
@ -2143,13 +2142,14 @@ Sema::DeclTy *Sema::ActOnMethodDeclaration(
|
|||
Decl *CDecl = static_cast<Decl*>(ClassDecl);
|
||||
ObjcInterfaceDecl *IDecl = 0;
|
||||
ObjcImplementationDecl *ImpDecl = 0;
|
||||
ObjcCategoryImplDecl *CatImpDecl = 0;
|
||||
if (isa<ObjcInterfaceDecl>(CDecl))
|
||||
IDecl = cast<ObjcInterfaceDecl>(CDecl);
|
||||
else if (isa<ObjcCategoryDecl>(CDecl))
|
||||
IDecl = cast<ObjcCategoryDecl>(CDecl)->getClassInterface(); // FIXME: what is this? (talk to fariborz)
|
||||
else if ((ImpDecl = dyn_cast<ObjcImplementationDecl>(CDecl)))
|
||||
IDecl = ImpDecl->getClassInterface(); // FIXME: what is this? (talk to fariborz)
|
||||
else if (isa<ObjcCategoryImplDecl>(CDecl))
|
||||
else if ((CatImpDecl = dyn_cast<ObjcCategoryImplDecl>(CDecl)))
|
||||
IDecl = cast<ObjcCategoryImplDecl>(CDecl)->getClassInterface(); // FIXME: what is this? (talk to fariborz)
|
||||
|
||||
ObjcMethodDecl* ObjcMethod = new ObjcMethodDecl(MethodLoc, EndLoc, Sel,
|
||||
|
@ -2163,13 +2163,12 @@ Sema::DeclTy *Sema::ActOnMethodDeclaration(
|
|||
ObjcMethod->setMethodParams(&Params[0], Sel.getNumArgs());
|
||||
ObjcMethod->setObjcDeclQualifier(
|
||||
CvtQTToAstBitMask(ReturnQT.getObjcDeclQualifier()));
|
||||
const ObjcMethodDecl *PrevMethod = 0;
|
||||
// For implementations (which can be very "coarse grain"), we add the
|
||||
// method now. This allows the AST to implement lookup methods that work
|
||||
// incrementally (without waiting until we parse the @end). It also allows
|
||||
// us to flag multiple declaration errors as they occur.
|
||||
if (ImpDecl) {
|
||||
// For implementations (which can be very "coarse grain"), we add the
|
||||
// method now. This allows the AST to implement lookup methods that work
|
||||
// incrementally (without waiting until we parse the @end). It also allows
|
||||
// us to flag multiple declaration errors as they occur.
|
||||
// FIXME: still need to do this for ObjcCategoryImplDecl.
|
||||
const ObjcMethodDecl *PrevMethod = 0;
|
||||
if (MethodType == tok::minus) {
|
||||
PrevMethod = ImpDecl->lookupInstanceMethod(Sel);
|
||||
ImpDecl->addInstanceMethod(ObjcMethod);
|
||||
|
@ -2177,13 +2176,21 @@ Sema::DeclTy *Sema::ActOnMethodDeclaration(
|
|||
PrevMethod = ImpDecl->lookupClassMethod(Sel);
|
||||
ImpDecl->addClassMethod(ObjcMethod);
|
||||
}
|
||||
if (PrevMethod) {
|
||||
// You can never have two method definitions with the same name.
|
||||
Diag(ObjcMethod->getLocation(), diag::error_duplicate_method_decl,
|
||||
ObjcMethod->getSelector().getName());
|
||||
Diag(PrevMethod->getLocation(), diag::err_previous_declaration);
|
||||
}
|
||||
} else if (CatImpDecl) {
|
||||
if (MethodType == tok::minus) {
|
||||
PrevMethod = CatImpDecl->lookupInstanceMethod(Sel);
|
||||
CatImpDecl->addInstanceMethod(ObjcMethod);
|
||||
} else {
|
||||
PrevMethod = CatImpDecl->lookupClassMethod(Sel);
|
||||
CatImpDecl->addClassMethod(ObjcMethod);
|
||||
}
|
||||
}
|
||||
if (PrevMethod) {
|
||||
// You can never have two method definitions with the same name.
|
||||
Diag(ObjcMethod->getLocation(), diag::error_duplicate_method_decl,
|
||||
ObjcMethod->getSelector().getName());
|
||||
Diag(PrevMethod->getLocation(), diag::err_previous_declaration);
|
||||
}
|
||||
return ObjcMethod;
|
||||
}
|
||||
|
||||
|
|
|
@ -572,36 +572,47 @@ class ObjcCategoryImplDecl : public NamedDecl {
|
|||
/// Class interface for this category implementation
|
||||
ObjcInterfaceDecl *ClassInterface;
|
||||
|
||||
/// category instance methods being implemented
|
||||
ObjcMethodDecl **InstanceMethods; // Null if category is not implementing any
|
||||
int NumInstanceMethods; // -1 if category is not implementing any
|
||||
/// implemented instance methods
|
||||
llvm::SmallVector<ObjcMethodDecl*, 32> InstanceMethods;
|
||||
|
||||
/// category class methods being implemented
|
||||
ObjcMethodDecl **ClassMethods; // Null if category is not implementing any
|
||||
int NumClassMethods; // -1 if category is not implementing any
|
||||
|
||||
public:
|
||||
/// implemented class methods
|
||||
llvm::SmallVector<ObjcMethodDecl*, 32> ClassMethods;
|
||||
|
||||
SourceLocation EndLoc;
|
||||
public:
|
||||
ObjcCategoryImplDecl(SourceLocation L, IdentifierInfo *Id,
|
||||
ObjcInterfaceDecl *classInterface)
|
||||
: NamedDecl(ObjcCategoryImpl, L, Id),
|
||||
ClassInterface(classInterface),
|
||||
InstanceMethods(0), NumInstanceMethods(-1),
|
||||
ClassMethods(0), NumClassMethods(-1) {}
|
||||
ClassInterface(classInterface) {}
|
||||
|
||||
ObjcInterfaceDecl *getClassInterface() const {
|
||||
return ClassInterface;
|
||||
}
|
||||
ObjcInterfaceDecl *getClassInterface() const { return ClassInterface; }
|
||||
|
||||
ObjcMethodDecl **getInstanceMethods() const { return InstanceMethods; }
|
||||
int getNumInstanceMethods() const { return NumInstanceMethods; }
|
||||
|
||||
ObjcMethodDecl **getClassMethods() const { return ClassMethods; }
|
||||
int getNumClassMethods() const { return NumClassMethods; }
|
||||
|
||||
void addMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers,
|
||||
ObjcMethodDecl **clsMethods, unsigned numClsMembers,
|
||||
SourceLocation AtEndLoc);
|
||||
// FIXME: Figure out how to remove the const pointer below.
|
||||
ObjcMethodDecl *const*getInstanceMethods() const {
|
||||
return &InstanceMethods[0];
|
||||
}
|
||||
int getNumInstanceMethods() const { return InstanceMethods.size(); }
|
||||
|
||||
// FIXME: Figure out how to remove the const pointer below.
|
||||
ObjcMethodDecl *const*getClassMethods() const {
|
||||
return &ClassMethods[0];
|
||||
}
|
||||
int getNumClassMethods() const { return ClassMethods.size(); }
|
||||
|
||||
void addInstanceMethod(ObjcMethodDecl *method) {
|
||||
InstanceMethods.push_back(method);
|
||||
}
|
||||
void addClassMethod(ObjcMethodDecl *method) {
|
||||
ClassMethods.push_back(method);
|
||||
}
|
||||
ObjcMethodDecl *lookupInstanceMethod(Selector &Sel);
|
||||
ObjcMethodDecl *lookupClassMethod(Selector &Sel);
|
||||
|
||||
// Location information, modeled after the Stmt API.
|
||||
SourceLocation getLocStart() const { return getLocation(); }
|
||||
SourceLocation getLocEnd() const { return EndLoc; }
|
||||
void setLocEnd(SourceLocation LE) { EndLoc = LE; };
|
||||
|
||||
static bool classof(const Decl *D) { return D->getKind() == ObjcCategoryImpl;}
|
||||
static bool classof(const ObjcCategoryImplDecl *D) { return true; }
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче