diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-01-01 20:30:41 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-01-01 20:30:41 +0000 |
commit | 27c6da284f90e32cda0ec8f52a2b6ba5a2613252 (patch) | |
tree | a753b051d413b266667ca50e5929e7cbbddf2d03 /lib/Sema | |
parent | 1d784b277cdfd4eba03680715d2a082b3f28d295 (diff) |
Wire up redeclaration chains for Objective-C protocols, so that both
forward declarations and definitions of an Objective-C protocol are
represented within a single chain of ObjCProtocolDecls.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147412 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 33 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 82 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 5 |
3 files changed, 65 insertions, 55 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index c8292b930e..a1ccf946d6 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1540,36 +1540,37 @@ DeclHasAttr(const Decl *D, const Attr *A) { } /// mergeDeclAttributes - Copy attributes from the Old decl to the New one. -static void mergeDeclAttributes(Decl *newDecl, const Decl *oldDecl, - ASTContext &C, bool mergeDeprecation = true) { - if (!oldDecl->hasAttrs()) +void Sema::mergeDeclAttributes(Decl *New, Decl *Old, + bool MergeDeprecation) { + if (!Old->hasAttrs()) return; - bool foundAny = newDecl->hasAttrs(); + bool foundAny = New->hasAttrs(); // Ensure that any moving of objects within the allocated map is done before // we process them. - if (!foundAny) newDecl->setAttrs(AttrVec()); + if (!foundAny) New->setAttrs(AttrVec()); for (specific_attr_iterator<InheritableAttr> - i = oldDecl->specific_attr_begin<InheritableAttr>(), - e = oldDecl->specific_attr_end<InheritableAttr>(); i != e; ++i) { + i = Old->specific_attr_begin<InheritableAttr>(), + e = Old->specific_attr_end<InheritableAttr>(); + i != e; ++i) { // Ignore deprecated/unavailable/availability attributes if requested. - if (!mergeDeprecation && + if (!MergeDeprecation && (isa<DeprecatedAttr>(*i) || isa<UnavailableAttr>(*i) || isa<AvailabilityAttr>(*i))) continue; - if (!DeclHasAttr(newDecl, *i)) { - InheritableAttr *newAttr = cast<InheritableAttr>((*i)->clone(C)); + if (!DeclHasAttr(New, *i)) { + InheritableAttr *newAttr = cast<InheritableAttr>((*i)->clone(Context)); newAttr->setInherited(true); - newDecl->addAttr(newAttr); + New->addAttr(newAttr); foundAny = true; } } - if (!foundAny) newDecl->dropAttrs(); + if (!foundAny) New->dropAttrs(); } /// mergeParamDeclAttributes - Copy attributes from the old parameter @@ -2035,7 +2036,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { /// \returns false bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) { // Merge the attributes - mergeDeclAttributes(New, Old, Context); + mergeDeclAttributes(New, Old); // Merge the storage class. if (Old->getStorageClass() != SC_Extern && @@ -2061,13 +2062,13 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) { void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod, - const ObjCMethodDecl *oldMethod) { + ObjCMethodDecl *oldMethod) { // We don't want to merge unavailable and deprecated attributes // except from interface to implementation. bool mergeDeprecation = isa<ObjCImplDecl>(newMethod->getDeclContext()); // Merge the attributes. - mergeDeclAttributes(newMethod, oldMethod, Context, mergeDeprecation); + mergeDeclAttributes(newMethod, oldMethod, mergeDeprecation); // Merge attributes from the parameters. ObjCMethodDecl::param_const_iterator oi = oldMethod->param_begin(); @@ -2174,7 +2175,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { New->setInvalidDecl(); } - mergeDeclAttributes(New, Old, Context); + mergeDeclAttributes(New, Old); // Warn if an already-declared variable is made a weak_import in a subsequent // declaration if (New->getAttr<WeakImportAttr>() && diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index eb178612c8..c4261ecbb8 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -569,46 +569,50 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, bool err = false; // FIXME: Deal with AttrList. assert(ProtocolName && "Missing protocol identifier"); - ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolName, ProtocolLoc); - if (PDecl) { - // Protocol already seen. Better be a forward protocol declaration - if (ObjCProtocolDecl *Def = PDecl->getDefinition()) { - Diag(ProtocolLoc, diag::warn_duplicate_protocol_def) << ProtocolName; - Diag(Def->getLocation(), diag::note_previous_definition); - - // Create a new protocol that is completely distinct from previous - // declarations, and do not make this protocol available for name lookup. - // That way, we'll end up completely ignoring the duplicate. - // FIXME: Can we turn this into an error? - PDecl = ObjCProtocolDecl::Create(Context, CurContext, ProtocolName, - ProtocolLoc, AtProtoInterfaceLoc, - /*isForwardDecl=*/false); - PDecl->startDefinition(); - } else { + ObjCProtocolDecl *PrevDecl = LookupProtocol(ProtocolName, ProtocolLoc, + ForRedeclaration); + ObjCProtocolDecl *PDecl = 0; + if (ObjCProtocolDecl *Def = PrevDecl? PrevDecl->getDefinition() : 0) { + // If we already have a definition, complain. + Diag(ProtocolLoc, diag::warn_duplicate_protocol_def) << ProtocolName; + Diag(Def->getLocation(), diag::note_previous_definition); + + // Create a new protocol that is completely distinct from previous + // declarations, and do not make this protocol available for name lookup. + // That way, we'll end up completely ignoring the duplicate. + // FIXME: Can we turn this into an error? + PDecl = ObjCProtocolDecl::Create(Context, CurContext, ProtocolName, + ProtocolLoc, AtProtoInterfaceLoc, + /*PrevDecl=*/0, + /*isForwardDecl=*/false); + PDecl->startDefinition(); + } else { + if (PrevDecl) { + // Check for circular dependencies among protocol declarations. This can + // only happen if this protocol was forward-declared. ObjCList<ObjCProtocolDecl> PList; PList.set((ObjCProtocolDecl *const*)ProtoRefs, NumProtoRefs, Context); err = CheckForwardProtocolDeclarationForCircularDependency( - ProtocolName, ProtocolLoc, PDecl->getLocation(), PList); - - // Make sure the cached decl gets a valid start location. - PDecl->setAtStartLoc(AtProtoInterfaceLoc); - PDecl->setLocation(ProtocolLoc); - // Since this ObjCProtocolDecl was created by a forward declaration, - // we now add it to the DeclContext since it wasn't added before - PDecl->setLexicalDeclContext(CurContext); - CurContext->addDecl(PDecl); - PDecl->completedForwardDecl(); + ProtocolName, ProtocolLoc, PrevDecl->getLocation(), PList); } - } else { + + // Create the new declaration. PDecl = ObjCProtocolDecl::Create(Context, CurContext, ProtocolName, ProtocolLoc, AtProtoInterfaceLoc, + /*PrevDecl=*/PrevDecl, /*isForwardDecl=*/false); + PushOnScopeChains(PDecl, TUScope); PDecl->startDefinition(); } if (AttrList) ProcessDeclAttributeList(TUScope, PDecl, AttrList); + + // Merge attributes from previous declarations. + if (PrevDecl) + mergeDeclAttributes(PDecl, PrevDecl); + if (!err && NumProtoRefs ) { /// Check then save referenced protocols. PDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs, @@ -700,22 +704,26 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, for (unsigned i = 0; i != NumElts; ++i) { IdentifierInfo *Ident = IdentList[i].first; - ObjCProtocolDecl *PDecl = LookupProtocol(Ident, IdentList[i].second); - bool isNew = false; - if (PDecl == 0) { // Not already seen? - PDecl = ObjCProtocolDecl::Create(Context, CurContext, Ident, - IdentList[i].second, AtProtocolLoc, - /*isForwardDecl=*/true); - PushOnScopeChains(PDecl, TUScope, false); - isNew = true; - } + ObjCProtocolDecl *PrevDecl = LookupProtocol(Ident, IdentList[i].second, + ForRedeclaration); + ObjCProtocolDecl *PDecl + = ObjCProtocolDecl::Create(Context, CurContext, Ident, + IdentList[i].second, AtProtocolLoc, + PrevDecl, /*isForwardDecl=*/true); + + PushOnScopeChains(PDecl, TUScope); + if (attrList) { ProcessDeclAttributeList(TUScope, PDecl, attrList); - if (!isNew) { + if (PrevDecl) { if (ASTMutationListener *L = Context.getASTMutationListener()) L->UpdatedAttributeList(PDecl); } } + + if (PrevDecl) + mergeDeclAttributes(PDecl, PrevDecl); + Protocols.push_back(PDecl); ProtoLocs.push_back(IdentList[i].second); } diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index f7dd69a78a..63d14f46c1 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -2180,9 +2180,10 @@ NamedDecl *Sema::LookupSingleName(Scope *S, DeclarationName Name, /// \brief Find the protocol with the given name, if any. ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II, - SourceLocation IdLoc) { + SourceLocation IdLoc, + RedeclarationKind Redecl) { Decl *D = LookupSingleName(TUScope, II, IdLoc, - LookupObjCProtocolName); + LookupObjCProtocolName, Redecl); return cast_or_null<ObjCProtocolDecl>(D); } |