diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 1ab232943a..3db06cc0f0 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -52,7 +52,6 @@ public: PropertyDecl, // ScopedDecl // TypeDecl - ObjCInterface, Typedef, // TagDecl Enum, @@ -67,6 +66,7 @@ public: BlockVar, FileVar, ParmVar, + ObjCInterface, ObjCCompatibleAlias, ObjCMethod, ObjCClass, @@ -78,8 +78,8 @@ public: // of the class, to allow efficient classof. NamedFirst = Field, NamedLast = ParmVar, FieldFirst = Field, FieldLast = ObjCIvar, - ScopedFirst = ObjCInterface, ScopedLast = ParmVar, - TypeFirst = ObjCInterface, TypeLast = Class, + ScopedFirst = Typedef, ScopedLast = ParmVar, + TypeFirst = Typedef, TypeLast = Class, TagFirst = Enum , TagLast = Class, RecordFirst = Struct , RecordLast = Class, ValueFirst = EnumConstant , ValueLast = ParmVar, diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 595718add7..7f4a9752a5 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -191,7 +191,11 @@ public: /// Unlike C++, ObjC is a single-rooted class model. In Cocoa, classes /// typically inherit from NSObject (an exception is NSProxy). /// -class ObjCInterfaceDecl : public TypeDecl { +class ObjCInterfaceDecl : public NamedDecl { + /// TypeForDecl - This indicates the Type object that represents this + /// TypeDecl. It is a cache maintained by ASTContext::getObjCInterfaceType + Type *TypeForDecl; + friend class ASTContext; /// Class's super class. ObjCInterfaceDecl *SuperClass; @@ -227,7 +231,7 @@ class ObjCInterfaceDecl : public TypeDecl { ObjCInterfaceDecl(SourceLocation atLoc, unsigned numRefProtos, IdentifierInfo *Id, bool FD, bool isInternal) - : TypeDecl(ObjCInterface, atLoc, Id, 0), SuperClass(0), + : NamedDecl(ObjCInterface, atLoc, Id), TypeForDecl(0), SuperClass(0), ReferencedProtocols(0), NumReferencedProtocols(0), Ivars(0), NumIvars(0), InstanceMethods(0), NumInstanceMethods(0), diff --git a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h index 5ce21e4fdb..1ff9a9392b 100644 --- a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h +++ b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h @@ -63,7 +63,6 @@ public: DISPATCH_CASE(Union,RecordDecl) // FIXME: Refine. DISPATCH_CASE(Class,RecordDecl) // FIXME: Refine. DISPATCH_CASE(Enum,EnumDecl) - DISPATCH_CASE(ObjCInterface,ObjCInterfaceDecl) default: assert(false && "Subtype of ScopedDecl not handled."); } diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index e98d9b59a7..d2ad5c5f75 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -94,7 +94,14 @@ class Sema : public Action { /// with @protocol keyword, so that we can emit errors on duplicates and /// find the declarations when needed. llvm::DenseMap ObjCProtocols; - + + /// ObjCInterfaceDecls - Keep track of all class declarations declared + /// with @interface, so that we can emit errors on duplicates and + /// find the declarations when needed. + typedef llvm::DenseMap ObjCInterfaceDeclsTy; + ObjCInterfaceDeclsTy ObjCInterfaceDecls; + /// ObjCAliasDecls - Keep track of all class declarations declared /// with @compatibility_alias, so that we can emit errors on duplicates and /// find the declarations when needed. This construct is ancient and will @@ -102,7 +109,7 @@ class Sema : public Action { typedef llvm::DenseMap ObjCAliasTy; ObjCAliasTy ObjCAliasDecls; - + // Enum values used by KnownFunctionIDs (see below). enum { id_printf, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index c5901f0b91..c9ea54fa0e 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -86,19 +86,11 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { /// getObjCInterfaceDecl - Look up a for a class declaration in the scope. /// return 0 if one not found. -/// FIXME: removed this when ObjCInterfaceDecl's aren't ScopedDecl's. ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *Id) { - ScopedDecl *IDecl; - // Scan up the scope chain looking for a decl that matches this identifier - // that is in the appropriate namespace. - for (IDecl = Id->getFETokenInfo(); IDecl; - IDecl = IDecl->getNext()) - if (IDecl->getIdentifierNamespace() == Decl::IDNS_Ordinary) - break; + // The third "scope" argument is 0 since we aren't enabling lazy built-in + // creation from this context. + Decl *IDecl = LookupDecl(Id, Decl::IDNS_Ordinary, 0, false); - if (ObjCCompatibleAliasDecl *ADecl = - dyn_cast_or_null(IDecl)) - return ADecl->getClassInterface(); return dyn_cast_or_null(IDecl); } @@ -130,6 +122,9 @@ Decl *Sema::LookupDecl(const IdentifierInfo *II, unsigned NSI, // Unlike typedef's, they can only be introduced at file-scope (and are // therefore not scoped decls). They can, however, be shadowed by // other names in IDNS_Ordinary. + ObjCInterfaceDeclsTy::iterator IDI = ObjCInterfaceDecls.find(II); + if (IDI != ObjCInterfaceDecls.end()) + return IDI->second; ObjCAliasTy::iterator I = ObjCAliasDecls.find(II); if (I != ObjCAliasDecls.end()) return I->second->getClassInterface(); diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 62e7c8af1e..69a102203f 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -101,10 +101,7 @@ Sema::DeclTy *Sema::ActOnStartClassInterface( IDecl = ObjCInterfaceDecl::Create(Context, AtInterfaceLoc, NumProtocols, ClassName); - // Chain & install the interface decl into the identifier. - IDecl->setNext(ClassName->getFETokenInfo()); - ClassName->setFETokenInfo(IDecl); - + ObjCInterfaceDecls[ClassName] = IDecl; // Remember that this needs to be removed when the scope is popped. TUScope->AddDecl(IDecl); } @@ -388,8 +385,7 @@ Sema::DeclTy *Sema::ActOnStartClassImplementation( // Build, chain & install the interface decl into the identifier. IDecl = ObjCInterfaceDecl::Create(Context, AtClassImplLoc, 0, ClassName, false, true); - IDecl->setNext(ClassName->getFETokenInfo()); - ClassName->setFETokenInfo(IDecl); + ObjCInterfaceDecls[ClassName] = IDecl; IDecl->setSuperClass(SDecl); IDecl->setLocEnd(ClassLoc); @@ -597,9 +593,7 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, if (!IDecl) { // Not already seen? Make a forward decl. IDecl = ObjCInterfaceDecl::Create(Context, AtClassLoc, 0, IdentList[i], true); - // Chain & install the interface decl into the identifier. - IDecl->setNext(IdentList[i]->getFETokenInfo()); - IdentList[i]->setFETokenInfo(IDecl); + ObjCInterfaceDecls[IdentList[i]] = IDecl; // Remember that this needs to be removed when the scope is popped. TUScope->AddDecl(IDecl); diff --git a/test/Sema/check-dup-objc-decls-1.m b/test/Sema/check-dup-objc-decls-1.m index dd48ba4796..e3902bdcca 100644 --- a/test/Sema/check-dup-objc-decls-1.m +++ b/test/Sema/check-dup-objc-decls-1.m @@ -20,8 +20,7 @@ typedef int OBJECT; // expected-error {{previous definition is here}} typedef int Gorf; // expected-error {{previous definition is here}} -@interface Gorf @end // expected-error {{redefinition of 'Gorf' as different kind of symbol}} \ - // expected-error {{previous definition is here}} +@interface Gorf @end // expected-error {{redefinition of 'Gorf' as different kind of symbol}} void Gorf() // expected-error {{redefinition of 'Gorf' as different kind of symbol}} {