diff --git a/clang/Sema/SemaDecl.cpp b/clang/Sema/SemaDecl.cpp index 42024b1adb4c..ca39e6e606bb 100644 --- a/clang/Sema/SemaDecl.cpp +++ b/clang/Sema/SemaDecl.cpp @@ -868,13 +868,30 @@ Sema::DeclTy *Sema::ObjcStartClassInterface(SourceLocation AtInterfaceLoc, IdentifierInfo **ProtocolNames, unsigned NumProtocols, AttributeList *AttrList) { assert(ClassName && "Missing class identifier"); - ObjcInterfaceDecl *IDecl; - + + ObjcInterfaceDecl* IDecl; + + if (Context.getObjCInterfaceDecl(ClassName)) + Diag(AtInterfaceLoc, diag::err_duplicate_class_def, ClassName->getName()); + IDecl = new ObjcInterfaceDecl(AtInterfaceLoc, ClassName); // Chain & install the interface decl into the identifier. IDecl->setNext(ClassName->getFETokenInfo()); ClassName->setFETokenInfo(IDecl); + + if (SuperName) { + const ObjcInterfaceDecl* SuperClassEntry = + Context.getObjCInterfaceDecl(SuperName); + + if (!SuperClassEntry) { + Diag(AtInterfaceLoc, diag::err_undef_superclass, SuperName->getName(), + ClassName->getName()); + } + } + + Context.setObjCInterfaceDecl(ClassName, IDecl); + return IDecl; } diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 76a51fc254ae..f9a33e579507 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -37,8 +37,10 @@ class ASTContext { llvm::FoldingSet FunctionTypeNoProtos; llvm::FoldingSet FunctionTypeProtos; llvm::DenseMap RecordLayoutInfo; + llvm::DenseMap ClassNameInfo; RecordDecl *CFConstantStringTypeDecl; public: + SourceManager &SourceMgr; TargetInfo &Target; IdentifierTable &Idents; @@ -157,6 +159,12 @@ public: /// position information. const RecordLayout &getRecordLayout(const RecordDecl *D, SourceLocation L); + const ObjcInterfaceDecl* getObjCInterfaceDecl(const IdentifierInfo* ClassName) + { return ClassNameInfo[ClassName]; } + void setObjCInterfaceDecl(const IdentifierInfo* ClassName, + const ObjcInterfaceDecl* InterfaceDecl) + { ClassNameInfo[ClassName] = InterfaceDecl; } + //===--------------------------------------------------------------------===// // Type Operators //===--------------------------------------------------------------------===// diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def index 059edecb868d..445f3bf2b80c 100644 --- a/clang/include/clang/Basic/DiagnosticKinds.def +++ b/clang/include/clang/Basic/DiagnosticKinds.def @@ -408,6 +408,11 @@ DIAG(err_objc_protocol_optional, ERROR, "@optional may be specified in protocols only") DIAG(err_missing_catch_finally, ERROR, "@try statment without a @catch and @finally clause") +DIAG(err_undef_superclass, ERROR, + "cannot find interface declaration for '%0', superclass of '%1'") +DIAG(err_duplicate_class_def, ERROR, + "duplicate interface declaration for class '%0'") + //===----------------------------------------------------------------------===// // Semantic Analysis diff --git a/clang/test/Sema/undef-superclass-1.m b/clang/test/Sema/undef-superclass-1.m new file mode 100644 index 000000000000..0b5b7c10d0bd --- /dev/null +++ b/clang/test/Sema/undef-superclass-1.m @@ -0,0 +1,18 @@ +@class SUPER, Y; + +@interface INTF :SUPER // expected-error {{cannot find interface declaration for 'SUPER', superclass of 'INTF'}} +@end + +@interface SUPER @end + +@interface INTF1 : SUPER +@end + +@interface INTF2 : INTF1 +@end + +@interface INTF3 : Y // expected-error {{cannot find interface declaration for 'Y', superclass of 'INTF3'}} +@end + +@interface INTF1 // expected-error {{duplicate interface declaration for class 'INTF1'}} +@end