diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-07-02 17:43:08 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-07-02 17:43:08 +0000 |
commit | 23c94dbb6631fecdb55ba401aa93722803d980c6 (patch) | |
tree | 19240dbaae509d69e403e4962fd5a14b9c8d5c53 /lib/Sema | |
parent | fe2dd6ceeeb31a7c681b2873a8459c5de5d1a3e9 (diff) |
Move the "current scope" state from the Parser into Action. This
allows Sema some limited access to the current scope, which we only
use in one way: when Sema is performing some kind of declaration that
is not directly driven by the parser (e.g., due to template
instantiatio or lazy declaration of a member), we can find the Scope
associated with a DeclContext, if that DeclContext is still in the
process of being parsed.
Use this to make the implicit declaration of special member functions
in a C++ class more "scope-less", rather than using the NULL Scope hack.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107491 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Sema.cpp | 25 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 23 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 43 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 2 |
4 files changed, 53 insertions, 40 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index d520a78abe..3e23ad3030 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -385,6 +385,31 @@ Sema::Diag(SourceLocation Loc, const PartialDiagnostic& PD) { return Builder; } +/// \brief Determines the active Scope associated with the given declaration +/// context. +/// +/// This routine maps a declaration context to the active Scope object that +/// represents that declaration context in the parser. It is typically used +/// from "scope-less" code (e.g., template instantiation, lazy creation of +/// declarations) that injects a name for name-lookup purposes and, therefore, +/// must update the Scope. +/// +/// \returns The scope corresponding to the given declaraion context, or NULL +/// if no such scope is open. +Scope *Sema::getScopeForContext(DeclContext *Ctx) { + + if (!Ctx) + return 0; + + Ctx = Ctx->getPrimaryContext(); + for (Scope *S = getCurScope(); S; S = S->getParent()) { + if (DeclContext *Entity = static_cast<DeclContext *> (S->getEntity())) + if (Ctx == Entity->getPrimaryContext()) + return S; + } + + return 0; +} /// \brief Enter a new function scope void Sema::PushFunctionScope() { diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index a1b2c2fab0..1cd7d739d2 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -674,6 +674,8 @@ public: virtual void ActOnEndOfTranslationUnit(); + Scope *getScopeForContext(DeclContext *Ctx); + void PushFunctionScope(); void PushBlockScope(Scope *BlockScope, BlockDecl *Block); void PopFunctionOrBlockScope(); @@ -2223,14 +2225,11 @@ public: /// \brief Declare the implicit default constructor for the given class. /// - /// \param S The scope of the class, which may be NULL if this is a - /// template instantiation. - /// /// \param ClassDecl The class declaration into which the implicit /// default constructor will be added. /// /// \returns The implicitly-declared default constructor. - CXXConstructorDecl *DeclareImplicitDefaultConstructor(Scope *S, + CXXConstructorDecl *DeclareImplicitDefaultConstructor( CXXRecordDecl *ClassDecl); /// DefineImplicitDefaultConstructor - Checks for feasibility of @@ -2240,15 +2239,11 @@ public: /// \brief Declare the implicit destructor for the given class. /// - /// \param S The scope of the class, which may be NULL if this is a - /// template instantiation. - /// /// \param ClassDecl The class declaration into which the implicit /// destructor will be added. /// /// \returns The implicitly-declared destructor. - CXXDestructorDecl *DeclareImplicitDestructor(Scope *S, - CXXRecordDecl *ClassDecl); + CXXDestructorDecl *DeclareImplicitDestructor(CXXRecordDecl *ClassDecl); /// DefineImplicitDestructor - Checks for feasibility of /// defining this destructor as the default destructor. @@ -2264,8 +2259,7 @@ public: /// copy constructor will be added. /// /// \returns The implicitly-declared copy constructor. - CXXConstructorDecl *DeclareImplicitCopyConstructor(Scope *S, - CXXRecordDecl *ClassDecl); + CXXConstructorDecl *DeclareImplicitCopyConstructor(CXXRecordDecl *ClassDecl); /// DefineImplicitCopyConstructor - Checks for feasibility of /// defining this constructor as the copy constructor. @@ -2282,8 +2276,7 @@ public: /// copy-assignment operator will be added. /// /// \returns The implicitly-declared copy assignment operator. - CXXMethodDecl *DeclareImplicitCopyAssignment(Scope *S, - CXXRecordDecl *ClassDecl); + CXXMethodDecl *DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl); /// \brief Defined an implicitly-declared copy assignment operator. void DefineImplicitCopyAssignment(SourceLocation CurrentLocation, @@ -2682,14 +2675,14 @@ public: /// \returns true if any work was done, false otherwise. bool DefineUsedVTables(); - void AddImplicitlyDeclaredMembersToClass(Scope *S, CXXRecordDecl *ClassDecl); + void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl); virtual void ActOnMemInitializers(DeclPtrTy ConstructorDecl, SourceLocation ColonLoc, MemInitTy **MemInits, unsigned NumMemInits, bool AnyErrors); - void CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record); + void CheckCompletedCXXClass(CXXRecordDecl *Record); virtual void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, DeclPtrTy TagDecl, SourceLocation LBrac, diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index fc52b3df10..7ba34a5fea 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2460,12 +2460,12 @@ namespace { /// \brief Perform semantic checks on a class definition that has been /// completing, introducing implicitly-declared members, checking for /// abstract types, etc. -void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { +void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { if (!Record || Record->isInvalidDecl()) return; if (!Record->isDependentType()) - AddImplicitlyDeclaredMembersToClass(S, Record); + AddImplicitlyDeclaredMembersToClass(Record); if (Record->isInvalidDecl()) return; @@ -2584,8 +2584,8 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, (DeclPtrTy*)FieldCollector->getCurFields(), FieldCollector->getCurNumFields(), LBrac, RBrac, AttrList); - CheckCompletedCXXClass(S, - dyn_cast_or_null<CXXRecordDecl>(TagDecl.getAs<Decl>())); + CheckCompletedCXXClass( + dyn_cast_or_null<CXXRecordDecl>(TagDecl.getAs<Decl>())); } namespace { @@ -2652,21 +2652,18 @@ namespace { /// constructor, or destructor, to the given C++ class (C++ /// [special]p1). This routine can only be executed just before the /// definition of the class is complete. -/// -/// The scope, if provided, is the class scope. -void Sema::AddImplicitlyDeclaredMembersToClass(Scope *S, - CXXRecordDecl *ClassDecl) { +void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { if (!ClassDecl->hasUserDeclaredConstructor()) - DeclareImplicitDefaultConstructor(S, ClassDecl); + DeclareImplicitDefaultConstructor(ClassDecl); if (!ClassDecl->hasUserDeclaredCopyConstructor()) - DeclareImplicitCopyConstructor(S, ClassDecl); + DeclareImplicitCopyConstructor(ClassDecl); if (!ClassDecl->hasUserDeclaredCopyAssignment()) - DeclareImplicitCopyAssignment(S, ClassDecl); + DeclareImplicitCopyAssignment(ClassDecl); if (!ClassDecl->hasUserDeclaredDestructor()) - DeclareImplicitDestructor(S, ClassDecl); + DeclareImplicitDestructor(ClassDecl); } void Sema::ActOnReenterTemplateScope(Scope *S, DeclPtrTy TemplateD) { @@ -4135,8 +4132,8 @@ namespace { }; } -CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(Scope *S, - CXXRecordDecl *ClassDecl) { +CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( + CXXRecordDecl *ClassDecl) { // C++ [class.ctor]p5: // A default constructor for a class X is a constructor of class X // that can be called without an argument. If there is no @@ -4206,7 +4203,7 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(Scope *S, DefaultCon->setAccess(AS_public); DefaultCon->setImplicit(); DefaultCon->setTrivial(ClassDecl->hasTrivialConstructor()); - if (S) + if (Scope *S = getScopeForContext(ClassDecl)) PushOnScopeChains(DefaultCon, S, true); else ClassDecl->addDecl(DefaultCon); @@ -4235,8 +4232,7 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, } } -CXXDestructorDecl *Sema::DeclareImplicitDestructor(Scope *S, - CXXRecordDecl *ClassDecl) { +CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { // C++ [class.dtor]p2: // If a class has no user-declared destructor, a destructor is // declared implicitly. An implicitly-declared destructor is an @@ -4298,7 +4294,7 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(Scope *S, Destructor->setAccess(AS_public); Destructor->setImplicit(); Destructor->setTrivial(ClassDecl->hasTrivialDestructor()); - if (S) + if (Scope *S = getScopeForContext(ClassDecl)) PushOnScopeChains(Destructor, S, true); else ClassDecl->addDecl(Destructor); @@ -4536,8 +4532,7 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, Loc, move(Copy)); } -CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(Scope *S, - CXXRecordDecl *ClassDecl) { +CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { // Note: The following rules are largely analoguous to the copy // constructor rules. Note that virtual bases are not taken into account // for determining the argument type of the operator. Note also that @@ -4655,7 +4650,7 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(Scope *S, // Don't call addedAssignmentOperator. The class does not need to know about // the implicitly-declared copy assignment operator. - if (S) + if (Scope *S = getScopeForContext(ClassDecl)) PushOnScopeChains(CopyAssignment, S, true); else ClassDecl->addDecl(CopyAssignment); @@ -4964,8 +4959,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, CopyAssignOperator->setBody(Body.takeAs<Stmt>()); } -CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(Scope *S, - CXXRecordDecl *ClassDecl) { +CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( + CXXRecordDecl *ClassDecl) { // C++ [class.copy]p4: // If the class definition does not explicitly declare a copy // constructor, one is declared implicitly. @@ -5108,7 +5103,7 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(Scope *S, VarDecl::None, VarDecl::None, 0); CopyConstructor->setParams(&FromParam, 1); - if (S) + if (Scope *S = getScopeForContext(ClassDecl)) PushOnScopeChains(CopyConstructor, S, true); else ClassDecl->addDecl(CopyConstructor); diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 1adf594c1e..cc9f600215 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -1216,7 +1216,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, ActOnFields(0, Instantiation->getLocation(), DeclPtrTy::make(Instantiation), Fields.data(), Fields.size(), SourceLocation(), SourceLocation(), 0); - CheckCompletedCXXClass(/*Scope=*/0, Instantiation); + CheckCompletedCXXClass(Instantiation); if (Instantiation->isInvalidDecl()) Invalid = true; |