aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-07-02 17:43:08 +0000
committerDouglas Gregor <dgregor@apple.com>2010-07-02 17:43:08 +0000
commit23c94dbb6631fecdb55ba401aa93722803d980c6 (patch)
tree19240dbaae509d69e403e4962fd5a14b9c8d5c53 /lib/Sema
parentfe2dd6ceeeb31a7c681b2873a8459c5de5d1a3e9 (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.cpp25
-rw-r--r--lib/Sema/Sema.h23
-rw-r--r--lib/Sema/SemaDeclCXX.cpp43
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp2
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;