Un-templatetize this method. It's definition is out of line in the .cpp file,

so that's not a valid thing to do at all. Instead, switch to a ValueDecl
argument, the template isn't really necessary here.

When handling the types explicitly in the code, it becomes awkward to cerate
the CXXBaseOrMemberInitializer object in so many places. Re-flow the code to
calculate the Init expression first, and then create the initializer. If this
is too gross, we can factor the init expression logic into helper functions,
but it's not past my threshold yet.

llvm-svn: 120997
This commit is contained in:
Chandler Carruth 2010-12-06 09:23:57 +00:00
parent 5d41378146
commit d44c3105fb
2 changed files with 54 additions and 57 deletions

View File

@ -2530,8 +2530,7 @@ public:
Expr **Args, unsigned NumArgs, Expr **Args, unsigned NumArgs,
SourceLocation RParenLoc); SourceLocation RParenLoc);
template<typename T> MemInitResult BuildMemberInitializer(ValueDecl *Member, Expr **Args,
MemInitResult BuildMemberInitializer(T *Member, Expr **Args,
unsigned NumArgs, SourceLocation IdLoc, unsigned NumArgs, SourceLocation IdLoc,
SourceLocation LParenLoc, SourceLocation LParenLoc,
SourceLocation RParenLoc); SourceLocation RParenLoc);

View File

@ -1259,18 +1259,19 @@ static bool InitExprContainsUninitializedFields(const Stmt *S,
return false; return false;
} }
template <typename T>
MemInitResult MemInitResult
Sema::BuildMemberInitializer(T *Member, Expr **Args, Sema::BuildMemberInitializer(ValueDecl *Member, Expr **Args,
unsigned NumArgs, SourceLocation IdLoc, unsigned NumArgs, SourceLocation IdLoc,
SourceLocation LParenLoc, SourceLocation LParenLoc,
SourceLocation RParenLoc) { SourceLocation RParenLoc) {
assert((isa<FieldDecl>(Member) || isa<IndirectFieldDecl>(Member)) || FieldDecl *DirectMember = dyn_cast<FieldDecl>(Member);
IndirectFieldDecl *IndirectMember = dyn_cast<IndirectFieldDecl>(Member);
assert((DirectMember || IndirectMember) &&
"Member must be a FieldDecl or IndirectFieldDecl"); "Member must be a FieldDecl or IndirectFieldDecl");
if (Member->isInvalidDecl()) if (Member->isInvalidDecl())
return true; return true;
// Diagnose value-uses of fields to initialize themselves, e.g. // Diagnose value-uses of fields to initialize themselves, e.g.
// foo(foo) // foo(foo)
// where foo is not also a parameter to the constructor. // where foo is not also a parameter to the constructor.
@ -1292,12 +1293,12 @@ Sema::BuildMemberInitializer(T *Member, Expr **Args,
for (unsigned i = 0; i < NumArgs; i++) for (unsigned i = 0; i < NumArgs; i++)
HasDependentArg |= Args[i]->isTypeDependent(); HasDependentArg |= Args[i]->isTypeDependent();
Expr *Init;
if (Member->getType()->isDependentType() || HasDependentArg) { if (Member->getType()->isDependentType() || HasDependentArg) {
// Can't check initialization for a member of dependent type or when // Can't check initialization for a member of dependent type or when
// any of the arguments are type-dependent expressions. // any of the arguments are type-dependent expressions.
Expr *Init Init = new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
= new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs, RParenLoc);
RParenLoc);
// Erase any temporaries within this evaluation context; we're not // Erase any temporaries within this evaluation context; we're not
// going to track them in the AST, since we'll be rebuilding the // going to track them in the AST, since we'll be rebuilding the
@ -1305,57 +1306,54 @@ Sema::BuildMemberInitializer(T *Member, Expr **Args,
ExprTemporaries.erase( ExprTemporaries.erase(
ExprTemporaries.begin() + ExprEvalContexts.back().NumTemporaries, ExprTemporaries.begin() + ExprEvalContexts.back().NumTemporaries,
ExprTemporaries.end()); ExprTemporaries.end());
} else {
return new (Context) CXXBaseOrMemberInitializer(Context, Member, IdLoc, // Initialize the member.
LParenLoc, InitializedEntity MemberEntity =
Init, DirectMember ? InitializedEntity::InitializeMember(DirectMember, 0)
RParenLoc); : InitializedEntity::InitializeMember(IndirectMember, 0);
InitializationKind Kind =
} InitializationKind::CreateDirect(IdLoc, LParenLoc, RParenLoc);
// Initialize the member.
InitializedEntity MemberEntity =
InitializedEntity::InitializeMember(Member, 0);
InitializationKind Kind =
InitializationKind::CreateDirect(IdLoc, LParenLoc, RParenLoc);
InitializationSequence InitSeq(*this, MemberEntity, Kind, Args, NumArgs);
ExprResult MemberInit =
InitSeq.Perform(*this, MemberEntity, Kind,
MultiExprArg(*this, Args, NumArgs), 0);
if (MemberInit.isInvalid())
return true;
CheckImplicitConversions(MemberInit.get(), LParenLoc); InitializationSequence InitSeq(*this, MemberEntity, Kind, Args, NumArgs);
// C++0x [class.base.init]p7: ExprResult MemberInit =
// The initialization of each base and member constitutes a InitSeq.Perform(*this, MemberEntity, Kind,
// full-expression. MultiExprArg(*this, Args, NumArgs), 0);
MemberInit = MaybeCreateExprWithCleanups(MemberInit.get()); if (MemberInit.isInvalid())
if (MemberInit.isInvalid()) return true;
return true;
CheckImplicitConversions(MemberInit.get(), LParenLoc);
// If we are in a dependent context, template instantiation will
// perform this type-checking again. Just save the arguments that we // C++0x [class.base.init]p7:
// received in a ParenListExpr. // The initialization of each base and member constitutes a
// FIXME: This isn't quite ideal, since our ASTs don't capture all // full-expression.
// of the information that we have about the member MemberInit = MaybeCreateExprWithCleanups(MemberInit.get());
// initializer. However, deconstructing the ASTs is a dicey process, if (MemberInit.isInvalid())
// and this approach is far more likely to get the corner cases right. return true;
if (CurContext->isDependentContext()) {
Expr *Init = new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs, // If we are in a dependent context, template instantiation will
RParenLoc); // perform this type-checking again. Just save the arguments that we
return new (Context) CXXBaseOrMemberInitializer(Context, Member, IdLoc, // received in a ParenListExpr.
LParenLoc, // FIXME: This isn't quite ideal, since our ASTs don't capture all
Init, // of the information that we have about the member
RParenLoc); // initializer. However, deconstructing the ASTs is a dicey process,
// and this approach is far more likely to get the corner cases right.
if (CurContext->isDependentContext())
Init = new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
RParenLoc);
else
Init = MemberInit.get();
} }
return new (Context) CXXBaseOrMemberInitializer(Context, Member, IdLoc, if (DirectMember) {
LParenLoc, return new (Context) CXXBaseOrMemberInitializer(Context, DirectMember,
MemberInit.get(), IdLoc, LParenLoc, Init,
RParenLoc); RParenLoc);
} else {
return new (Context) CXXBaseOrMemberInitializer(Context, IndirectMember,
IdLoc, LParenLoc, Init,
RParenLoc);
}
} }
MemInitResult MemInitResult