[cfe-commits] r76508 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/DeclObjC.h include/clang/Basic/DiagnosticSemaKinds.td lib/AST/ASTContext.cpp lib/AST/DeclObjC.cpp lib/Sema/SemaDeclObjC.cpp test/SemaObjC/category-1.m
Argiris Kirtzidis
akyrtzi at gmail.com
Mon Jul 20 17:05:53 PDT 2009
Author: akirtzidis
Date: Mon Jul 20 19:05:53 2009
New Revision: 76508
URL: http://llvm.org/viewvc/llvm-project?rev=76508&view=rev
Log:
- Introduce ASTContext::getObjCImplementation() and ASTContext::setObjCImplementation() which use a DenseMap to associate
an interface/category with its implementation (if one exists).
- Introduce ObjCInterfaceDecl::get/setImplementation() and ObjCCategoryDecl::get/setImplementation() that use the above methods.
- Add a compiler error for when a category is reimplemented.
Modified:
cfe/trunk/include/clang/AST/ASTContext.h
cfe/trunk/include/clang/AST/DeclObjC.h
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/DeclObjC.cpp
cfe/trunk/lib/Sema/SemaDeclObjC.cpp
cfe/trunk/test/SemaObjC/category-1.m
Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=76508&r1=76507&r2=76508&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Mon Jul 20 19:05:53 2009
@@ -97,6 +97,9 @@
llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*> ASTRecordLayouts;
llvm::DenseMap<const ObjCContainerDecl*, const ASTRecordLayout*> ObjCLayouts;
+ /// \brief Mapping from ObjCContainers to their ObjCImplementations.
+ llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*> ObjCImpls;
+
llvm::DenseMap<unsigned, FixedWidthIntType*> SignedFixedWidthIntTypes;
llvm::DenseMap<unsigned, FixedWidthIntType*> UnsignedFixedWidthIntTypes;
@@ -804,6 +807,18 @@
return Res;
}
+ /// \brief Get the implementation of ObjCInterfaceDecl,or NULL if none exists.
+ ObjCImplementationDecl *getObjCImplementation(ObjCInterfaceDecl *D);
+ /// \brief Get the implementation of ObjCCategoryDecl, or NULL if none exists.
+ ObjCCategoryImplDecl *getObjCImplementation(ObjCCategoryDecl *D);
+
+ /// \brief Set the implementation of ObjCInterfaceDecl.
+ void setObjCImplementation(ObjCInterfaceDecl *IFaceD,
+ ObjCImplementationDecl *ImplD);
+ /// \brief Set the implementation of ObjCCategoryDecl.
+ void setObjCImplementation(ObjCCategoryDecl *CatD,
+ ObjCCategoryImplDecl *ImplD);
+
private:
ASTContext(const ASTContext&); // DO NOT IMPLEMENT
void operator=(const ASTContext&); // DO NOT IMPLEMENT
Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=76508&r1=76507&r2=76508&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Mon Jul 20 19:05:53 2009
@@ -427,7 +427,10 @@
const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const {
return ReferencedProtocols;
}
-
+
+ ObjCImplementationDecl *getImplementation() const;
+ void setImplementation(ObjCImplementationDecl *ImplD);
+
ObjCCategoryDecl *FindCategoryDeclaration(IdentifierInfo *CategoryId) const;
typedef ObjCList<ObjCProtocolDecl>::iterator protocol_iterator;
@@ -775,7 +778,10 @@
ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
void setClassInterface(ObjCInterfaceDecl *IDecl) { ClassInterface = IDecl; }
-
+
+ ObjCCategoryImplDecl *getImplementation() const;
+ void setImplementation(ObjCCategoryImplDecl *ImplD);
+
/// setProtocolList - Set the list of protocols that this interface
/// implements.
void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num,
@@ -828,7 +834,7 @@
const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
- void setClassInterface(ObjCInterfaceDecl *IFace) { ClassInterface = IFace; }
+ void setClassInterface(ObjCInterfaceDecl *IFace);
void addInstanceMethod(ObjCMethodDecl *method) {
// FIXME: Context should be set correctly before we get here.
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=76508&r1=76507&r2=76508&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Jul 20 19:05:53 2009
@@ -168,6 +168,8 @@
"duplicate definition of category %1 on interface %0">;
def err_conflicting_super_class : Error<"conflicting super class name %0">;
def err_dup_implementation_class : Error<"reimplementation of class %0">;
+def err_dup_implementation_category : Error<
+ "reimplementation of category %1 for class %0">;
def err_conflicting_ivar_type : Error<
"instance variable %0 has conflicting type: %1 vs %2">;
def err_conflicting_ivar_bitwidth : Error<
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=76508&r1=76507&r2=76508&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Mon Jul 20 19:05:53 2009
@@ -824,6 +824,36 @@
return count;
}
+/// \brief Get the implementation of ObjCInterfaceDecl,or NULL if none exists.
+ObjCImplementationDecl *ASTContext::getObjCImplementation(ObjCInterfaceDecl *D) {
+ llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*>::iterator
+ I = ObjCImpls.find(D);
+ if (I != ObjCImpls.end())
+ return cast<ObjCImplementationDecl>(I->second);
+ return 0;
+}
+/// \brief Get the implementation of ObjCCategoryDecl, or NULL if none exists.
+ObjCCategoryImplDecl *ASTContext::getObjCImplementation(ObjCCategoryDecl *D) {
+ llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*>::iterator
+ I = ObjCImpls.find(D);
+ if (I != ObjCImpls.end())
+ return cast<ObjCCategoryImplDecl>(I->second);
+ return 0;
+}
+
+/// \brief Set the implementation of ObjCInterfaceDecl.
+void ASTContext::setObjCImplementation(ObjCInterfaceDecl *IFaceD,
+ ObjCImplementationDecl *ImplD) {
+ assert(IFaceD && ImplD && "Passed null params");
+ ObjCImpls[IFaceD] = ImplD;
+}
+/// \brief Set the implementation of ObjCCategoryDecl.
+void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD,
+ ObjCCategoryImplDecl *ImplD) {
+ assert(CatD && ImplD && "Passed null params");
+ ObjCImpls[CatD] = ImplD;
+}
+
/// getInterfaceLayoutImpl - Get or compute information about the
/// layout of the given interface.
///
Modified: cfe/trunk/lib/AST/DeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=76508&r1=76507&r2=76508&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclObjC.cpp (original)
+++ cfe/trunk/lib/AST/DeclObjC.cpp Mon Jul 20 19:05:53 2009
@@ -363,6 +363,15 @@
Decl::Destroy(C);
}
+ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const {
+ return getASTContext().getObjCImplementation(
+ const_cast<ObjCInterfaceDecl*>(this));
+}
+
+void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) {
+ getASTContext().setObjCImplementation(this, ImplD);
+}
+
/// FindCategoryDeclaration - Finds category declaration in the list of
/// categories for this class and returns it. Name of the category is passed
@@ -529,6 +538,16 @@
return new (C) ObjCCategoryDecl(DC, L, Id);
}
+ObjCCategoryImplDecl *ObjCCategoryDecl::getImplementation() const {
+ return getASTContext().getObjCImplementation(
+ const_cast<ObjCCategoryDecl*>(this));
+}
+
+void ObjCCategoryDecl::setImplementation(ObjCCategoryImplDecl *ImplD) {
+ getASTContext().setObjCImplementation(this, ImplD);
+}
+
+
//===----------------------------------------------------------------------===//
// ObjCCategoryImplDecl
//===----------------------------------------------------------------------===//
@@ -547,6 +566,23 @@
addDecl(property);
}
+void ObjCImplDecl::setClassInterface(ObjCInterfaceDecl *IFace) {
+ ASTContext &Ctx = getASTContext();
+
+ if (ObjCImplementationDecl *ImplD
+ = dyn_cast_or_null<ObjCImplementationDecl>(this))
+ if (IFace)
+ Ctx.setObjCImplementation(IFace, ImplD);
+
+ else if (ObjCCategoryImplDecl *ImplD =
+ dyn_cast_or_null<ObjCCategoryImplDecl>(this)) {
+ if (ObjCCategoryDecl *CD = IFace->FindCategoryDeclaration(getIdentifier()))
+ Ctx.setObjCImplementation(CD, ImplD);
+ }
+
+ ClassInterface = IFace;
+}
+
/// FindPropertyImplIvarDecl - This method lookup the ivar in the list of
/// properties implemented in this category @implementation block and returns
/// the implemented property that uses it.
Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=76508&r1=76507&r2=76508&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Mon Jul 20 19:05:53 2009
@@ -605,6 +605,19 @@
IdentifierInfo *ClassName, SourceLocation ClassLoc,
IdentifierInfo *CatName, SourceLocation CatLoc) {
ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName);
+ ObjCCategoryDecl *CatIDecl = 0;
+ if (IDecl) {
+ CatIDecl = IDecl->FindCategoryDeclaration(CatName);
+ if (!CatIDecl) {
+ // Category @implementation with no corresponding @interface.
+ // Create and install one.
+ CatIDecl = ObjCCategoryDecl::Create(Context, CurContext, SourceLocation(),
+ CatName);
+ CatIDecl->setClassInterface(IDecl);
+ CatIDecl->insertNextClassCategory();
+ }
+ }
+
ObjCCategoryImplDecl *CDecl =
ObjCCategoryImplDecl::Create(Context, CurContext, AtCatImplLoc, CatName,
IDecl);
@@ -615,8 +628,17 @@
// FIXME: PushOnScopeChains?
CurContext->addDecl(CDecl);
- /// TODO: Check that CatName, category name, is not used in another
- // implementation.
+ /// Check that CatName, category name, is not used in another implementation.
+ if (CatIDecl) {
+ if (CatIDecl->getImplementation()) {
+ Diag(ClassLoc, diag::err_dup_implementation_category) << ClassName
+ << CatName;
+ Diag(CatIDecl->getImplementation()->getLocation(),
+ diag::note_previous_definition);
+ } else
+ CatIDecl->setImplementation(CDecl);
+ }
+
ObjCCategoryImpls.push_back(CDecl);
CheckObjCDeclScope(CDecl);
@@ -697,8 +719,10 @@
if (LookupObjCImplementation(ClassName))
// FIXME: Don't leak everything!
Diag(ClassLoc, diag::err_dup_implementation_class) << ClassName;
- else // add it to the list.
+ else { // add it to the list.
+ IDecl->setImplementation(IMPDecl);
PushOnScopeChains(IMPDecl, TUScope);
+ }
return DeclPtrTy::make(IMPDecl);
}
Modified: cfe/trunk/test/SemaObjC/category-1.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/category-1.m?rev=76508&r1=76507&r2=76508&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/category-1.m (original)
+++ cfe/trunk/test/SemaObjC/category-1.m Mon Jul 20 19:05:53 2009
@@ -53,4 +53,8 @@
@implementation XCRemoteComputerManager
@end
+ at implementation XCRemoteComputerManager(x) // expected-note {{previous definition is here}}
+ at end
+ at implementation XCRemoteComputerManager(x) // expected-error {{reimplementation of category 'x' for class 'XCRemoteComputerManager'}}
+ at end
More information about the cfe-commits
mailing list