зеркало из https://github.com/microsoft/clang-1.git
Added an RAII object that helps set up/tear down the Sema context
information required to implicitly define a C++ special member function. Use it rather than explicitly setting CurContext on entry and exit, which is fragile. Use this RAII object for the implicitly-defined default constructor, copy constructor, copy assignment operator, and destructor. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102840 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
63e742bed9
Коммит
39957dce3d
|
@ -2182,10 +2182,9 @@ public:
|
|||
CXXConstructorDecl *Constructor,
|
||||
unsigned TypeQuals);
|
||||
|
||||
/// DefineImplicitOverloadedAssign - Checks for feasibility of
|
||||
/// defining implicit this overloaded assignment operator.
|
||||
void DefineImplicitOverloadedAssign(SourceLocation CurrentLocation,
|
||||
CXXMethodDecl *MethodDecl);
|
||||
/// \brief Defined and implicitly-declared copy assignment operator.
|
||||
void DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
|
||||
CXXMethodDecl *MethodDecl);
|
||||
|
||||
/// getAssignOperatorMethod - Returns the default copy assignmment operator
|
||||
/// for the class.
|
||||
|
|
|
@ -4033,6 +4033,30 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S,
|
|||
return DeclPtrTy::make(AliasDecl);
|
||||
}
|
||||
|
||||
namespace {
|
||||
/// \brief Scoped object used to handle the state changes required in Sema
|
||||
/// to implicitly define the body of a C++ member function;
|
||||
class ImplicitlyDefinedFunctionScope {
|
||||
Sema &S;
|
||||
DeclContext *PreviousContext;
|
||||
|
||||
public:
|
||||
ImplicitlyDefinedFunctionScope(Sema &S, CXXMethodDecl *Method)
|
||||
: S(S), PreviousContext(S.CurContext)
|
||||
{
|
||||
S.CurContext = Method;
|
||||
S.PushFunctionScope();
|
||||
S.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated);
|
||||
}
|
||||
|
||||
~ImplicitlyDefinedFunctionScope() {
|
||||
S.PopExpressionEvaluationContext();
|
||||
S.PopFunctionOrBlockScope();
|
||||
S.CurContext = PreviousContext;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
|
||||
CXXConstructorDecl *Constructor) {
|
||||
assert((Constructor->isImplicit() && Constructor->isDefaultConstructor() &&
|
||||
|
@ -4042,8 +4066,7 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
|
|||
CXXRecordDecl *ClassDecl = Constructor->getParent();
|
||||
assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor");
|
||||
|
||||
DeclContext *PreviousContext = CurContext;
|
||||
CurContext = Constructor;
|
||||
ImplicitlyDefinedFunctionScope Scope(*this, Constructor);
|
||||
if (SetBaseOrMemberInitializers(Constructor, 0, 0, /*AnyErrors=*/false)) {
|
||||
Diag(CurrentLocation, diag::note_member_synthesized_at)
|
||||
<< CXXConstructor << Context.getTagDeclType(ClassDecl);
|
||||
|
@ -4051,7 +4074,6 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
|
|||
} else {
|
||||
Constructor->setUsed();
|
||||
}
|
||||
CurContext = PreviousContext;
|
||||
}
|
||||
|
||||
void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
|
||||
|
@ -4061,8 +4083,7 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
|
|||
CXXRecordDecl *ClassDecl = Destructor->getParent();
|
||||
assert(ClassDecl && "DefineImplicitDestructor - invalid destructor");
|
||||
|
||||
DeclContext *PreviousContext = CurContext;
|
||||
CurContext = Destructor;
|
||||
ImplicitlyDefinedFunctionScope Scope(*this, Destructor);
|
||||
|
||||
MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(),
|
||||
Destructor->getParent());
|
||||
|
@ -4074,27 +4095,23 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
|
|||
<< CXXDestructor << Context.getTagDeclType(ClassDecl);
|
||||
|
||||
Destructor->setInvalidDecl();
|
||||
CurContext = PreviousContext;
|
||||
|
||||
return;
|
||||
}
|
||||
CurContext = PreviousContext;
|
||||
|
||||
Destructor->setUsed();
|
||||
}
|
||||
|
||||
void Sema::DefineImplicitOverloadedAssign(SourceLocation CurrentLocation,
|
||||
CXXMethodDecl *MethodDecl) {
|
||||
void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
|
||||
CXXMethodDecl *MethodDecl) {
|
||||
assert((MethodDecl->isImplicit() && MethodDecl->isOverloadedOperator() &&
|
||||
MethodDecl->getOverloadedOperator() == OO_Equal &&
|
||||
!MethodDecl->isUsed()) &&
|
||||
"DefineImplicitOverloadedAssign - call it for implicit assignment op");
|
||||
"DefineImplicitCopyAssignment called for wrong function");
|
||||
|
||||
CXXRecordDecl *ClassDecl
|
||||
= cast<CXXRecordDecl>(MethodDecl->getDeclContext());
|
||||
|
||||
DeclContext *PreviousContext = CurContext;
|
||||
CurContext = MethodDecl;
|
||||
ImplicitlyDefinedFunctionScope Scope(*this, MethodDecl);
|
||||
|
||||
// C++[class.copy] p12
|
||||
// Before the implicitly-declared copy assignment operator for a class is
|
||||
|
@ -4151,8 +4168,6 @@ void Sema::DefineImplicitOverloadedAssign(SourceLocation CurrentLocation,
|
|||
}
|
||||
if (!err)
|
||||
MethodDecl->setUsed();
|
||||
|
||||
CurContext = PreviousContext;
|
||||
}
|
||||
|
||||
CXXMethodDecl *
|
||||
|
@ -4195,8 +4210,7 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
|
|||
CXXRecordDecl *ClassDecl = CopyConstructor->getParent();
|
||||
assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor");
|
||||
|
||||
DeclContext *PreviousContext = CurContext;
|
||||
CurContext = CopyConstructor;
|
||||
ImplicitlyDefinedFunctionScope Scope(*this, CopyConstructor);
|
||||
|
||||
// C++ [class.copy] p209
|
||||
// Before the implicitly-declared copy constructor for a class is
|
||||
|
@ -4238,8 +4252,6 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
|
|||
}
|
||||
}
|
||||
CopyConstructor->setUsed();
|
||||
|
||||
CurContext = PreviousContext;
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
|
|
|
@ -7507,7 +7507,7 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
|
|||
if (MethodDecl->isImplicit() && MethodDecl->isOverloadedOperator() &&
|
||||
MethodDecl->getOverloadedOperator() == OO_Equal) {
|
||||
if (!MethodDecl->isUsed())
|
||||
DefineImplicitOverloadedAssign(Loc, MethodDecl);
|
||||
DefineImplicitCopyAssignment(Loc, MethodDecl);
|
||||
}
|
||||
}
|
||||
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче