diff options
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/Sema.h | 20 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 81 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 39 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 4 |
5 files changed, 83 insertions, 66 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index fc81781911c..e30f4b2b38f 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -32,6 +32,7 @@ namespace clang { class ASTConsumer; class Preprocessor; class Decl; + class NamedDecl; class ScopedDecl; class Expr; class InitListExpr; @@ -51,6 +52,7 @@ namespace clang { class OCUVectorType; class TypedefDecl; class ObjCInterfaceDecl; + class ObjCCompatibleAliasDecl; class ObjCProtocolDecl; class ObjCImplementationDecl; class ObjCCategoryImplDecl; @@ -93,6 +95,13 @@ class Sema : public Action { /// find the declarations when needed. llvm::DenseMap<IdentifierInfo*, ObjCProtocolDecl*> ObjCProtocols; + /// 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 + /// likely never be seen. Nevertheless, it is here for compatibility. + typedef llvm::DenseMap<IdentifierInfo*, ObjCCompatibleAliasDecl*> ObjCAliasTy; + ObjCAliasTy ObjCAliasDecls; + // Enum values used by KnownFunctionIDs (see below). enum { id_printf, @@ -232,16 +241,15 @@ private: /// Subroutines of ActOnDeclarator(). TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T, ScopedDecl *LastDecl); - TypedefDecl *MergeTypeDefDecl(TypedefDecl *New, ScopedDecl *Old); - FunctionDecl *MergeFunctionDecl(FunctionDecl *New, ScopedDecl *Old); - VarDecl *MergeVarDecl(VarDecl *New, ScopedDecl *Old); + TypedefDecl *MergeTypeDefDecl(TypedefDecl *New, Decl *Old); + FunctionDecl *MergeFunctionDecl(FunctionDecl *New, Decl *Old); + VarDecl *MergeVarDecl(VarDecl *New, Decl *Old); /// More parsing and symbol table subroutines... ParmVarDecl *ActOnParamDeclarator(struct DeclaratorChunk::ParamInfo &PI, Scope *FnBodyScope); - ScopedDecl *LookupScopedDecl(IdentifierInfo *II, unsigned NSI, - SourceLocation IdLoc, Scope *S); - ScopedDecl *LookupInterfaceDecl(IdentifierInfo *II); + Decl *LookupDecl(IdentifierInfo *II, unsigned NSI, + SourceLocation IdLoc, Scope *S); ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *Id); ScopedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, Scope *S); ScopedDecl *ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 9429d4b4130..0280ef2127b 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -35,15 +35,22 @@ using namespace clang; Sema::DeclTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S) const { Decl *IIDecl = II.getFETokenInfo<Decl>(); // Find first occurance of none-tagged declaration - while(IIDecl && IIDecl->getIdentifierNamespace() != Decl::IDNS_Ordinary) + while (IIDecl && IIDecl->getIdentifierNamespace() != Decl::IDNS_Ordinary) IIDecl = cast<ScopedDecl>(IIDecl)->getNext(); - if (!IIDecl) + + if (!IIDecl) { + if (getLangOptions().ObjC1) { + // @interface and @compatibility_alias result in new type references. + // Creating a class alias is *extremely* rare. + ObjCAliasTy::const_iterator I = ObjCAliasDecls.find((IdentifierInfo*)&II); + if (I != ObjCAliasDecls.end()) + return I->second->getClassInterface(); + } return 0; + } + // FIXME: remove ObjCInterfaceDecl check when we make it a named decl. if (isa<TypedefDecl>(IIDecl) || isa<ObjCInterfaceDecl>(IIDecl)) return IIDecl; - if (ObjCCompatibleAliasDecl *ADecl = - dyn_cast<ObjCCompatibleAliasDecl>(IIDecl)) - return ADecl->getClassInterface(); return 0; } @@ -91,15 +98,14 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { } } -/// LookupInterfaceDecl - Lookup interface declaration in the scope chain. -/// Return the first declaration found (which may or may not be a class -/// declaration. Caller is responsible for handling the none-class case. -/// Bypassing the alias of a class by returning the aliased class. -ScopedDecl *Sema::LookupInterfaceDecl(IdentifierInfo *ClassName) { +/// 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 = ClassName->getFETokenInfo<ScopedDecl>(); IDecl; + for (IDecl = Id->getFETokenInfo<ScopedDecl>(); IDecl; IDecl = IDecl->getNext()) if (IDecl->getIdentifierNamespace() == Decl::IDNS_Ordinary) break; @@ -107,20 +113,13 @@ ScopedDecl *Sema::LookupInterfaceDecl(IdentifierInfo *ClassName) { if (ObjCCompatibleAliasDecl *ADecl = dyn_cast_or_null<ObjCCompatibleAliasDecl>(IDecl)) return ADecl->getClassInterface(); - return IDecl; + return cast_or_null<ObjCInterfaceDecl>(IDecl); } -/// getObjCInterfaceDecl - Look up a for a class declaration in the scope. -/// return 0 if one not found. -ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *Id) { - ScopedDecl *IdDecl = LookupInterfaceDecl(Id); - return cast_or_null<ObjCInterfaceDecl>(IdDecl); -} - -/// LookupScopedDecl - Look up the inner-most declaration in the specified +/// LookupDecl - Look up the inner-most declaration in the specified /// namespace. -ScopedDecl *Sema::LookupScopedDecl(IdentifierInfo *II, unsigned NSI, - SourceLocation IdLoc, Scope *S) { +Decl *Sema::LookupDecl(IdentifierInfo *II, unsigned NSI, + SourceLocation IdLoc, Scope *S) { if (II == 0) return 0; Decl::IdentifierNamespace NS = (Decl::IdentifierNamespace)NSI; @@ -138,6 +137,16 @@ ScopedDecl *Sema::LookupScopedDecl(IdentifierInfo *II, unsigned NSI, // If this is a builtin on this (or all) targets, create the decl. if (unsigned BuiltinID = II->getBuiltinID()) return LazilyCreateBuiltin(II, BuiltinID, S); + + if (getLangOptions().ObjC1) { + // @interface and @compatibility_alias introduce typedef-like names. + // Unlike typedef's, they can only be introduced at file-scope (and are + // not therefore not scoped decls). They can, however, be shadowed by + // other names in IDNS_Ordinary. + ObjCAliasTy::iterator I = ObjCAliasDecls.find(II); + if (I != ObjCAliasDecls.end()) + return I->second->getClassInterface(); + } } return 0; } @@ -148,8 +157,8 @@ void Sema::InitBuiltinVaListType() return; IdentifierInfo *VaIdent = &Context.Idents.get("__builtin_va_list"); - ScopedDecl *VaDecl = LookupScopedDecl(VaIdent, Decl::IDNS_Ordinary, - SourceLocation(), TUScope); + Decl *VaDecl = LookupDecl(VaIdent, Decl::IDNS_Ordinary, + SourceLocation(), TUScope); TypedefDecl *VaTypedef = cast<TypedefDecl>(VaDecl); Context.setBuiltinVaListType(Context.getTypedefType(VaTypedef)); } @@ -193,7 +202,7 @@ ScopedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, /// and scope as a previous declaration 'Old'. Figure out how to resolve this /// situation, merging decls or emitting diagnostics as appropriate. /// -TypedefDecl *Sema::MergeTypeDefDecl(TypedefDecl *New, ScopedDecl *OldD) { +TypedefDecl *Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) { // Verify the old decl was also a typedef. TypedefDecl *Old = dyn_cast<TypedefDecl>(OldD); if (!Old) { @@ -265,7 +274,7 @@ static void MergeAttributes(Decl *New, Decl *Old) { /// and scope as a previous declaration 'Old'. Figure out how to resolve this /// situation, merging decls or emitting diagnostics as appropriate. /// -FunctionDecl *Sema::MergeFunctionDecl(FunctionDecl *New, ScopedDecl *OldD) { +FunctionDecl *Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { // Verify the old decl was also a function. FunctionDecl *Old = dyn_cast<FunctionDecl>(OldD); if (!Old) { @@ -337,7 +346,7 @@ static bool areEquivalentArrayTypes(QualType NewQType, QualType OldQType) { /// FIXME: Need to carefully consider tentative definition rules (C99 6.9.2p2). /// For example, we incorrectly complain about i1, i4 from C99 6.9.2p4. /// -VarDecl *Sema::MergeVarDecl(VarDecl *New, ScopedDecl *OldD) { +VarDecl *Sema::MergeVarDecl(VarDecl *New, Decl *OldD) { // Verify the old decl was also a variable. VarDecl *Old = dyn_cast<VarDecl>(OldD); if (!Old) { @@ -707,8 +716,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) { S = S->getParent(); // See if this is a redefinition of a variable in the same scope. - ScopedDecl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_Ordinary, - D.getIdentifierLoc(), S); + Decl *PrevDecl = LookupDecl(II, Decl::IDNS_Ordinary, D.getIdentifierLoc(), S); ScopedDecl *New; bool InvalidDecl = false; @@ -980,8 +988,8 @@ Sema::ActOnParamDeclarator(struct DeclaratorChunk::ParamInfo &PI, // TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope. // Can this happen for params? We already checked that they don't conflict // among each other. Here they can only shadow globals, which is ok. - if (/*Decl *PrevDecl = */LookupScopedDecl(II, Decl::IDNS_Ordinary, - PI.IdentLoc, FnScope)) { + if (/*Decl *PrevDecl = */LookupDecl(II, Decl::IDNS_Ordinary, + PI.IdentLoc, FnScope)) { } @@ -1061,8 +1069,8 @@ Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) { Scope *GlobalScope = FnBodyScope->getParent(); // See if this is a redefinition. - ScopedDecl *PrevDcl = LookupScopedDecl(D.getIdentifier(), Decl::IDNS_Ordinary, - D.getIdentifierLoc(), GlobalScope); + Decl *PrevDcl = LookupDecl(D.getIdentifier(), Decl::IDNS_Ordinary, + D.getIdentifierLoc(), GlobalScope); if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(PrevDcl)) { if (FD->getBody()) { Diag(D.getIdentifierLoc(), diag::err_redefinition, @@ -1216,8 +1224,8 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK, // If this is a named struct, check to see if there was a previous forward // declaration or definition. if (TagDecl *PrevDecl = - dyn_cast_or_null<TagDecl>(LookupScopedDecl(Name, Decl::IDNS_Tag, - NameLoc, S))) { + dyn_cast_or_null<TagDecl>(LookupDecl(Name, Decl::IDNS_Tag, + NameLoc, S))) { // If this is a use of a previous tag, or if the tag is already declared in // the same scope (so that the definition/declaration completes or @@ -1540,8 +1548,7 @@ Sema::DeclTy *Sema::ActOnEnumConstant(Scope *S, DeclTy *theEnumDecl, // Verify that there isn't already something declared with this name in this // scope. - if (ScopedDecl *PrevDecl = LookupScopedDecl(Id, Decl::IDNS_Ordinary, - IdLoc, S)) { + if (Decl *PrevDecl = LookupDecl(Id, Decl::IDNS_Ordinary, IdLoc, S)) { if (S->isDeclScope(PrevDecl)) { if (isa<EnumConstantDecl>(PrevDecl)) Diag(IdLoc, diag::err_redefinition_of_enumerator, Id->getName()); diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 12706534999..2385cd07bd8 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -79,7 +79,7 @@ Sema::DeclTy *Sema::ActOnStartClassInterface( assert(ClassName && "Missing class identifier"); // Check for another declaration kind with the same name. - ScopedDecl *PrevDecl = LookupInterfaceDecl(ClassName); + Decl *PrevDecl = LookupDecl(ClassName, Decl::IDNS_Ordinary, ClassLoc,TUScope); if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) { Diag(ClassLoc, diag::err_redefinition_different_kind, ClassName->getName()); @@ -112,7 +112,7 @@ Sema::DeclTy *Sema::ActOnStartClassInterface( if (SuperName) { ObjCInterfaceDecl* SuperClassEntry = 0; // Check if a different kind of symbol declared in this scope. - PrevDecl = LookupInterfaceDecl(SuperName); + PrevDecl = LookupDecl(SuperName, Decl::IDNS_Ordinary, SuperLoc, TUScope); if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) { Diag(SuperLoc, diag::err_redefinition_different_kind, SuperName->getName()); @@ -152,13 +152,14 @@ Sema::DeclTy *Sema::ActOnStartClassInterface( /// ActOnCompatiblityAlias - this action is called after complete parsing of /// @compaatibility_alias declaration. It sets up the alias relationships. -Sema::DeclTy *Sema::ActOnCompatiblityAlias( - SourceLocation AtCompatibilityAliasLoc, - IdentifierInfo *AliasName, SourceLocation AliasLocation, - IdentifierInfo *ClassName, SourceLocation ClassLocation) { +Sema::DeclTy *Sema::ActOnCompatiblityAlias(SourceLocation AtLoc, + IdentifierInfo *AliasName, + SourceLocation AliasLocation, + IdentifierInfo *ClassName, + SourceLocation ClassLocation) { // Look for previous declaration of alias name - ScopedDecl *ADecl = LookupScopedDecl(AliasName, Decl::IDNS_Ordinary, - AliasLocation, TUScope); + Decl *ADecl = LookupDecl(AliasName, Decl::IDNS_Ordinary, + AliasLocation, TUScope); if (ADecl) { if (isa<ObjCCompatibleAliasDecl>(ADecl)) { Diag(AliasLocation, diag::warn_previous_alias_decl); @@ -172,8 +173,8 @@ Sema::DeclTy *Sema::ActOnCompatiblityAlias( return 0; } // Check for class declaration - ScopedDecl *CDeclU = LookupScopedDecl(ClassName, Decl::IDNS_Ordinary, - ClassLocation, TUScope); + Decl *CDeclU = LookupDecl(ClassName, Decl::IDNS_Ordinary, + ClassLocation, TUScope); ObjCInterfaceDecl *CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDeclU); if (CDecl == 0) { Diag(ClassLocation, diag::warn_undef_interface, ClassName->getName()); @@ -184,12 +185,10 @@ Sema::DeclTy *Sema::ActOnCompatiblityAlias( // Everything checked out, instantiate a new alias declaration AST. ObjCCompatibleAliasDecl *AliasDecl = - ObjCCompatibleAliasDecl::Create(Context, AtCompatibilityAliasLoc, - AliasName, CDecl); - - // Chain & install the interface decl into the identifier. - AliasDecl->setNext(AliasName->getFETokenInfo<ScopedDecl>()); - AliasName->setFETokenInfo(AliasDecl); + ObjCCompatibleAliasDecl::Create(Context, AtLoc, AliasName, CDecl); + + ObjCAliasDecls[AliasName] = AliasDecl; + TUScope->AddDecl(AliasDecl); return AliasDecl; } @@ -348,7 +347,7 @@ Sema::DeclTy *Sema::ActOnStartClassImplementation( SourceLocation SuperClassLoc) { ObjCInterfaceDecl* IDecl = 0; // Check for another declaration kind with the same name. - ScopedDecl *PrevDecl = LookupInterfaceDecl(ClassName); + Decl *PrevDecl = LookupDecl(ClassName, Decl::IDNS_Ordinary, ClassLoc,TUScope); if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) { Diag(ClassLoc, diag::err_redefinition_different_kind, ClassName->getName()); @@ -365,7 +364,8 @@ Sema::DeclTy *Sema::ActOnStartClassImplementation( ObjCInterfaceDecl* SDecl = 0; if (SuperClassname) { // Check if a different kind of symbol declared in this scope. - PrevDecl = LookupInterfaceDecl(SuperClassname); + PrevDecl = LookupDecl(SuperClassname, Decl::IDNS_Ordinary, + SuperClassLoc, TUScope); if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) { Diag(SuperClassLoc, diag::err_redefinition_different_kind, SuperClassname->getName()); @@ -590,7 +590,8 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, for (unsigned i = 0; i != NumElts; ++i) { // Check for another declaration kind with the same name. - ScopedDecl *PrevDecl = LookupInterfaceDecl(IdentList[i]); + Decl *PrevDecl = LookupDecl(IdentList[i], Decl::IDNS_Ordinary, + AtClassLoc, TUScope); if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) { Diag(AtClassLoc, diag::err_redefinition_different_kind, IdentList[i]->getName()); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index c815b548689..94387da80f8 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -75,17 +75,18 @@ Sema::ExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc, IdentifierInfo &II, bool HasTrailingLParen) { // Could be enum-constant, value decl, instance variable, etc. - ScopedDecl *D = LookupScopedDecl(&II, Decl::IDNS_Ordinary, Loc, S); + Decl *D = LookupDecl(&II, Decl::IDNS_Ordinary, Loc, S); // If this reference is in an Objective-C method, then ivar lookup happens as // well. if (CurMethodDecl) { + ScopedDecl *SD = dyn_cast_or_null<ScopedDecl>(D); // There are two cases to handle here. 1) scoped lookup could have failed, // in which case we should look for an ivar. 2) scoped lookup could have // found a decl, but that decl is outside the current method (i.e. a global // variable). In these two cases, we do a lookup for an ivar with this // name, if the lookup suceeds, we replace it our current decl. - if (D == 0 || D->isDefinedOutsideFunctionOrMethod()) { + if (SD == 0 || SD->isDefinedOutsideFunctionOrMethod()) { ObjCInterfaceDecl *IFace = CurMethodDecl->getClassInterface(), *DeclClass; if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(&II, DeclClass)) { // FIXME: This should use a new expr for a direct reference, don't turn diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 1a274e126e0..00a13183769 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -52,8 +52,8 @@ Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, // Initialize the constant string interface lazily. This assumes // the NSConstantString interface is seen in this translation unit. IdentifierInfo *NSIdent = &Context.Idents.get("NSConstantString"); - ScopedDecl *IFace = LookupScopedDecl(NSIdent, Decl::IDNS_Ordinary, - SourceLocation(), TUScope); + Decl *IFace = LookupDecl(NSIdent, Decl::IDNS_Ordinary, + SourceLocation(), TUScope); ObjCInterfaceDecl *strIFace = dyn_cast_or_null<ObjCInterfaceDecl>(IFace); if (!strIFace) return Diag(S->getLocStart(), diag::err_undef_interface, |

