diff options
author | Sebastian Redl <sebastian.redl@getdesigned.at> | 2010-08-09 21:55:28 +0000 |
---|---|---|
committer | Sebastian Redl <sebastian.redl@getdesigned.at> | 2010-08-09 21:55:28 +0000 |
commit | 74c730ad1f6818b676b0bad46d806a9176950328 (patch) | |
tree | 5c18340b3ff50d40bbb77954d0b75ebd34550eb0 /lib/Sema | |
parent | 35cc9627340b15232139b3c43fcde5973e7fad30 (diff) |
- Make ObjCInterfaceDecl redeclarable, and create separate decl nodes for forward declarations and the definition.
- Eagerly create ObjCInterfaceTypes for declarations.
- The two above changes lead to a 0.5% increase in memory use and no speed regression when parsing Cocoa.h. On the other hand, now chained PCH works when there's a forward declaration in one PCH and the interface definition in another.
- Add HandleInterestingDecl to ASTConsumer. PCHReader passes the "interesting" decls it finds to this function instead of HandleTopLevelDecl. The default implementation forwards to HandleTopLevelDecl, but ASTUnit's handler for example ignores them. This fixes a potential crash when lazy loading of PCH data would cause ASTUnit's "top level" declaration collection to change while being iterated.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110610 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Sema.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 26 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 39 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 159 |
4 files changed, 117 insertions, 109 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index aeb4db987d..11d7a9191f 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -89,7 +89,7 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) { ObjCInterfaceDecl *ProtocolDecl = ObjCInterfaceDecl::Create(Context, CurContext, SourceLocation(), &Context.Idents.get("Protocol"), - SourceLocation(), true); + SourceLocation(), 0, true); Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl)); PushOnScopeChains(ProtocolDecl, TUScope, false); } diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 52ac8dd649..f12e1839e5 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -3748,20 +3748,28 @@ static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext, for (DeclContext::decl_iterator D = Ctx->decls_begin(), DEnd = Ctx->decls_end(); D != DEnd; ++D) { - // Record any interfaces we find. - if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D)) - if ((!OnlyForwardDeclarations || Class->isForwardDecl()) && - (!OnlyUnimplemented || !Class->getImplementation())) - Results.AddResult(Result(Class, 0), CurContext, 0, false); + // Record any interfaces we find. Forward declarations are never registered + // in the lexical contest, so if we're only looking for those, don't bother. + if (!OnlyForwardDeclarations) + if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D)) + if (!OnlyUnimplemented || !Class->getImplementation()) + Results.AddResult(Result(Class, 0), CurContext, 0, false); // Record any forward-declared interfaces we find. if (ObjCClassDecl *Forward = dyn_cast<ObjCClassDecl>(*D)) { for (ObjCClassDecl::iterator C = Forward->begin(), CEnd = Forward->end(); - C != CEnd; ++C) - if ((!OnlyForwardDeclarations || C->getInterface()->isForwardDecl()) && - (!OnlyUnimplemented || !C->getInterface()->getImplementation())) - Results.AddResult(Result(C->getInterface(), 0), CurContext, + C != CEnd; ++C) { + ObjCInterfaceDecl *IDecl = C->getInterface(); + ObjCInterfaceDecl *IDef = IDecl->getDefinition(); + // If there's a definition, and we're looking for everything, then we + // already added the decl in question above. + if (!OnlyForwardDeclarations && !OnlyUnimplemented && IDef) + continue; + if ((!OnlyForwardDeclarations || !IDef) && + (!OnlyUnimplemented || !IDef || !IDef->getImplementation())) + Results.AddResult(Result(IDecl, 0), CurContext, 0, false); + } } } } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 200b8fd681..e6c5170357 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -606,45 +606,6 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { } } -/// \brief Look for an Objective-C class in the translation unit. -/// -/// \param Id The name of the Objective-C class we're looking for. If -/// typo-correction fixes this name, the Id will be updated -/// to the fixed name. -/// -/// \param IdLoc The location of the name in the translation unit. -/// -/// \param TypoCorrection If true, this routine will attempt typo correction -/// if there is no class with the given name. -/// -/// \returns The declaration of the named Objective-C class, or NULL if the -/// class could not be found. -ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id, - SourceLocation IdLoc, - bool TypoCorrection) { - // The third "scope" argument is 0 since we aren't enabling lazy built-in - // creation from this context. - NamedDecl *IDecl = LookupSingleName(TUScope, Id, IdLoc, LookupOrdinaryName); - - if (!IDecl && TypoCorrection) { - // Perform typo correction at the given location, but only if we - // find an Objective-C class name. - LookupResult R(*this, Id, IdLoc, LookupOrdinaryName); - if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) && - (IDecl = R.getAsSingle<ObjCInterfaceDecl>())) { - Diag(IdLoc, diag::err_undef_interface_suggest) - << Id << IDecl->getDeclName() - << FixItHint::CreateReplacement(IdLoc, IDecl->getNameAsString()); - Diag(IDecl->getLocation(), diag::note_previous_decl) - << IDecl->getDeclName(); - - Id = IDecl->getIdentifier(); - } - } - - return dyn_cast_or_null<ObjCInterfaceDecl>(IDecl); -} - /// getNonFieldDeclScope - Retrieves the innermost scope, starting /// from S, where a non-field would be declared. This routine copes /// with the difference between C and C++ scoping rules in structs and diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 9e0d250536..283376bfde 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -20,6 +20,50 @@ #include "clang/Parse/DeclSpec.h" using namespace clang; +/// \brief Look for an Objective-C class in the translation unit. +/// +/// \param Id The name of the Objective-C class we're looking for. If +/// typo-correction fixes this name, the Id will be updated +/// to the fixed name. +/// +/// \param IdLoc The location of the name in the translation unit. +/// +/// \param TypoCorrection If true, this routine will attempt typo correction +/// if there is no class with the given name. +/// +/// \returns The declaration of the named Objective-C class, which is also the +/// definition if one is available, or NULL if the class could not be found. +ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id, + SourceLocation IdLoc, + bool TypoCorrection) { + // The third "scope" argument is 0 since we aren't enabling lazy built-in + // creation from this context. + NamedDecl *Decl = LookupSingleName(TUScope, Id, IdLoc, LookupOrdinaryName); + + if (!Decl && TypoCorrection) { + // Perform typo correction at the given location, but only if we + // find an Objective-C class name. + LookupResult R(*this, Id, IdLoc, LookupOrdinaryName); + if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) && + (Decl = R.getAsSingle<ObjCInterfaceDecl>())) { + Diag(IdLoc, diag::err_undef_interface_suggest) + << Id << Decl->getDeclName() + << FixItHint::CreateReplacement(IdLoc, Decl->getNameAsString()); + Diag(Decl->getLocation(), diag::note_previous_decl) + << Decl->getDeclName(); + + Id = Decl->getIdentifier(); + } + } + + ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(Decl); + if (IDecl) { + if (ObjCInterfaceDecl *Def = IDecl->getDefinition()) + IDecl = Def; + } + return IDecl; +} + /// ActOnStartOfObjCMethodDef - This routine sets up parameters; invisible /// and user declared, in the method definition's AST. void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, DeclPtrTy D) { @@ -65,6 +109,8 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, SourceLocation EndProtoLoc, AttributeList *AttrList) { assert(ClassName && "Missing class identifier"); + bool Invalid = false; + // Check for another declaration kind with the same name. NamedDecl *PrevDecl = LookupSingleName(TUScope, ClassName, ClassLoc, LookupOrdinaryName, ForRedeclaration); @@ -72,42 +118,35 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) { Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName; Diag(PrevDecl->getLocation(), diag::note_previous_definition); + // Set the new decl invalid and ignore the old. + Invalid = true; + PrevDecl = 0; } - ObjCInterfaceDecl* IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); - if (IDecl) { + ObjCInterfaceDecl *ODecl = cast_or_null<ObjCInterfaceDecl>(PrevDecl); + if (ODecl) { // Class already seen. Is it a forward declaration? - if (!IDecl->isForwardDecl()) { - IDecl->setInvalidDecl(); - Diag(AtInterfaceLoc, diag::err_duplicate_class_def)<<IDecl->getDeclName(); - Diag(IDecl->getLocation(), diag::note_previous_definition); + if (ObjCInterfaceDecl *Def = ODecl->getDefinition()) { + Invalid = true; + Diag(AtInterfaceLoc, diag::err_duplicate_class_def) << Def->getDeclName(); + Diag(Def->getLocation(), diag::note_previous_definition); - // Return the previous class interface. - // FIXME: don't leak the objects passed in! - return DeclPtrTy::make(IDecl); - } else { - IDecl->setLocation(AtInterfaceLoc); - IDecl->setForwardDecl(false); - IDecl->setClassLoc(ClassLoc); - - // Since this ObjCInterfaceDecl was created by a forward declaration, - // we now add it to the DeclContext since it wasn't added before - // (see ActOnForwardClassDeclaration). - IDecl->setLexicalDeclContext(CurContext); - CurContext->addDecl(IDecl); - - if (AttrList) - ProcessDeclAttributeList(TUScope, IDecl, AttrList); + // Return the previous class interface and ignore the new one. + return DeclPtrTy::make(ODecl); } - } else { - IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, - ClassName, ClassLoc); - if (AttrList) - ProcessDeclAttributeList(TUScope, IDecl, AttrList); - - PushOnScopeChains(IDecl, TUScope); } + ObjCInterfaceDecl *IDecl = + ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, + ClassName, ClassLoc, ODecl); + if (Invalid) + IDecl->setInvalidDecl(); + + if (AttrList) + ProcessDeclAttributeList(TUScope, IDecl, AttrList); + + PushOnScopeChains(IDecl, TUScope); + if (SuperName) { // Check if a different kind of symbol declared in this scope. PrevDecl = LookupSingleName(TUScope, SuperName, SuperLoc, @@ -125,6 +164,8 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, } } + // Since we just pushed IDecl on the scope chain, if PrevDecl is the same + // class, it will be the same declaration. if (PrevDecl == IDecl) { Diag(SuperLoc, diag::err_recursive_superclass) << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc); @@ -140,11 +181,11 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, if (PrevDecl && SuperClassDecl == 0) { // The previous declaration was not a class decl. Check if we have a // typedef. If we do, get the underlying class type. - if (const TypedefDecl *TDecl = dyn_cast_or_null<TypedefDecl>(PrevDecl)) { + if (const TypedefDecl *TDecl = dyn_cast_or_null<TypedefDecl>(PrevDecl)){ QualType T = TDecl->getUnderlyingType(); if (T->isObjCObjectType()) { - if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface()) - SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl); + if (NamedDecl *NDecl = T->getAs<ObjCObjectType>()->getInterface()) + SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(NDecl); } } @@ -159,6 +200,11 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, } } + if (SuperClassDecl) { + if (ObjCInterfaceDecl *Def = SuperClassDecl->getDefinition()) + SuperClassDecl = Def; + } + if (!dyn_cast_or_null<TypedefDecl>(PrevDecl)) { if (!SuperClassDecl) Diag(SuperLoc, diag::err_undef_superclass) @@ -530,7 +576,7 @@ Sema::DeclPtrTy Sema::ActOnStartClassImplementation( IdentifierInfo *ClassName, SourceLocation ClassLoc, IdentifierInfo *SuperClassname, SourceLocation SuperClassLoc) { - ObjCInterfaceDecl* IDecl = 0; + ObjCInterfaceDecl *IDecl = 0, *ODecl = 0; // Check for another declaration kind with the same name. NamedDecl *PrevDecl = LookupSingleName(TUScope, ClassName, ClassLoc, LookupOrdinaryName, @@ -538,11 +584,10 @@ Sema::DeclPtrTy Sema::ActOnStartClassImplementation( if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) { Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName; Diag(PrevDecl->getLocation(), diag::note_previous_definition); - } else if ((IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl))) { - // If this is a forward declaration of an interface, warn. - if (IDecl->isForwardDecl()) { + } else if ((ODecl = cast_or_null<ObjCInterfaceDecl>(PrevDecl))) { + // If we can't find a definition of the interface, warn. + if (!(IDecl = ODecl->getDefinition())) { Diag(ClassLoc, diag::warn_undef_interface) << ClassName; - IDecl = 0; } } else { // We did not find anything with the name ClassName; try to correct for @@ -552,7 +597,7 @@ Sema::DeclPtrTy Sema::ActOnStartClassImplementation( (IDecl = R.getAsSingle<ObjCInterfaceDecl>())) { // Suggest the (potentially) correct interface name. However, put the // fix-it hint itself in a separate note, since changing the name in - // the warning would make the fix-it change semantics.However, don't + // the warning would make the fix-it change semantics. Also, don't // provide a code-modification hint or use the typo name for recovery, // because this is just a warning. The program may actually be correct. Diag(ClassLoc, diag::warn_undef_interface_suggest) @@ -599,16 +644,11 @@ Sema::DeclPtrTy Sema::ActOnStartClassImplementation( // FIXME: Do we support attributes on the @implementation? If so we should // copy them over. IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassImplLoc, - ClassName, ClassLoc, false, true); + ClassName, ClassLoc, ODecl, false, true); IDecl->setSuperClass(SDecl); IDecl->setLocEnd(ClassLoc); PushOnScopeChains(IDecl, TUScope); - } else { - // Mark the interface as being completed, even if it was just as - // @class ....; - // declaration; the user cannot reopen it. - IDecl->setForwardDecl(false); } ObjCImplementationDecl* IMPDecl = @@ -619,15 +659,15 @@ Sema::DeclPtrTy Sema::ActOnStartClassImplementation( return DeclPtrTy::make(IMPDecl); // Check that there is no duplicate implementation of this class. - if (IDecl->getImplementation()) { - // FIXME: Don't leak everything! + if (IDecl && IDecl->getImplementation()) { Diag(ClassLoc, diag::err_dup_implementation_class) << ClassName; Diag(IDecl->getImplementation()->getLocation(), diag::note_previous_definition); - } else { // add it to the list. + } else { IDecl->setImplementation(IMPDecl); PushOnScopeChains(IMPDecl, TUScope); } + return DeclPtrTy::make(IMPDecl); } @@ -1029,19 +1069,18 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, PrevDecl = OI->getInterface(); } } - ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); - if (!IDecl) { // Not already seen? Make a forward decl. - IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc, - IdentList[i], IdentLocs[i], true); - - // Push the ObjCInterfaceDecl on the scope chain but do *not* add it to - // the current DeclContext. This prevents clients that walk DeclContext - // from seeing the imaginary ObjCInterfaceDecl until it is actually - // declared later (if at all). We also take care to explicitly make - // sure this declaration is visible for name lookup. - PushOnScopeChains(IDecl, TUScope, false); - CurContext->makeDeclVisibleInContext(IDecl, true); - } + ObjCInterfaceDecl *ODecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); + ObjCInterfaceDecl *IDecl = + ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc, + IdentList[i], IdentLocs[i], ODecl, true); + + // Push the ObjCInterfaceDecl on the scope chain but do *not* add it to + // the current DeclContext. This prevents clients that walk DeclContext + // from seeing the imaginary ObjCInterfaceDecl until it is actually + // declared later (if at all). We also take care to explicitly make + // sure this declaration is visible for name lookup. + PushOnScopeChains(IDecl, TUScope, false); + CurContext->makeDeclVisibleInContext(IDecl, true); Interfaces.push_back(IDecl); } |