Unify initializer-instantiation code for variable declarations and

base/member initializers.

llvm-svn: 97560
This commit is contained in:
Douglas Gregor 2010-03-02 07:38:39 +00:00
parent 350bb062b2
commit b30f22b911
1 changed files with 93 additions and 85 deletions

View File

@ -202,6 +202,72 @@ static bool InstantiateInitializationArguments(Sema &SemaRef,
return false; return false;
} }
/// \brief Instantiate an initializer, breaking it into separate
/// initialization arguments.
///
/// \param S The semantic analysis object.
///
/// \param Init The initializer to instantiate.
///
/// \param TemplateArgs Template arguments to be substituted into the
/// initializer.
///
/// \param NewArgs Will be filled in with the instantiation arguments.
///
/// \returns true if an error occurred, false otherwise
static bool InstantiateInitializer(Sema &S, Expr *Init,
const MultiLevelTemplateArgumentList &TemplateArgs,
SourceLocation &LParenLoc,
llvm::SmallVector<SourceLocation, 4> &CommaLocs,
ASTOwningVector<&ActionBase::DeleteExpr> &NewArgs,
SourceLocation &RParenLoc) {
NewArgs.clear();
LParenLoc = SourceLocation();
RParenLoc = SourceLocation();
if (!Init)
return false;
if (CXXExprWithTemporaries *ExprTemp = dyn_cast<CXXExprWithTemporaries>(Init))
Init = ExprTemp->getSubExpr();
while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(Init))
Init = Binder->getSubExpr();
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Init))
Init = ICE->getSubExprAsWritten();
if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
LParenLoc = ParenList->getLParenLoc();
RParenLoc = ParenList->getRParenLoc();
return InstantiateInitializationArguments(S, ParenList->getExprs(),
ParenList->getNumExprs(),
TemplateArgs, CommaLocs,
NewArgs);
}
if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init)) {
if (InstantiateInitializationArguments(S,
Construct->getArgs(),
Construct->getNumArgs(),
TemplateArgs,
CommaLocs, NewArgs))
return true;
// FIXME: Fake locations!
LParenLoc = S.PP.getLocForEndOfToken(Init->getLocStart());
RParenLoc = CommaLocs.empty()? LParenLoc : CommaLocs.back();
return false;
}
Sema::OwningExprResult Result = S.SubstExpr(Init, TemplateArgs);
if (Result.isInvalid())
return true;
NewArgs.push_back(Result.takeAs<Expr>());
return false;
}
Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
// Do substitution on the type of the declaration // Do substitution on the type of the declaration
TypeSourceInfo *DI = SemaRef.SubstType(D->getTypeSourceInfo(), TypeSourceInfo *DI = SemaRef.SubstType(D->getTypeSourceInfo(),
@ -259,77 +325,33 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
else else
SemaRef.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated); SemaRef.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated);
// Extract the initializer, skipping through any temporary-binding // Instantiate the initializer.
// expressions and look at the subexpression as it was written. SourceLocation LParenLoc, RParenLoc;
Expr *DInit = D->getInit(); llvm::SmallVector<SourceLocation, 4> CommaLocs;
if (CXXExprWithTemporaries *ExprTemp ASTOwningVector<&ActionBase::DeleteExpr> InitArgs(SemaRef);
= dyn_cast<CXXExprWithTemporaries>(DInit)) if (!InstantiateInitializer(SemaRef, D->getInit(), TemplateArgs, LParenLoc,
DInit = ExprTemp->getSubExpr(); CommaLocs, InitArgs, RParenLoc)) {
while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(DInit)) // Attach the initializer to the declaration.
DInit = Binder->getSubExpr(); if (D->hasCXXDirectInitializer()) {
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(DInit))
DInit = ICE->getSubExprAsWritten();
if (ParenListExpr *PLE = dyn_cast<ParenListExpr>(DInit)) {
// The initializer is a parenthesized list of expressions that is
// type-dependent. Instantiate each of the expressions; we'll be
// performing direct initialization with them.
llvm::SmallVector<SourceLocation, 4> CommaLocs;
ASTOwningVector<&ActionBase::DeleteExpr> InitArgs(SemaRef);
if (!InstantiateInitializationArguments(SemaRef,
PLE->getExprs(),
PLE->getNumExprs(),
TemplateArgs,
CommaLocs, InitArgs)) {
// Add the direct initializer to the declaration. // Add the direct initializer to the declaration.
SemaRef.AddCXXDirectInitializerToDecl(Sema::DeclPtrTy::make(Var), SemaRef.AddCXXDirectInitializerToDecl(Sema::DeclPtrTy::make(Var),
PLE->getLParenLoc(), LParenLoc,
move_arg(InitArgs), move_arg(InitArgs),
CommaLocs.data(), CommaLocs.data(),
PLE->getRParenLoc()); RParenLoc);
} } else if (InitArgs.size() == 1) {
} else if (CXXConstructExpr *Construct =dyn_cast<CXXConstructExpr>(DInit)) { Expr *Init = (Expr*)(InitArgs.take()[0]);
// The initializer resolved to a constructor. Instantiate the constructor SemaRef.AddInitializerToDecl(Sema::DeclPtrTy::make(Var),
// arguments. SemaRef.Owned(Init),
llvm::SmallVector<SourceLocation, 4> CommaLocs; false);
ASTOwningVector<&ActionBase::DeleteExpr> InitArgs(SemaRef); } else {
assert(InitArgs.size() == 0);
if (!InstantiateInitializationArguments(SemaRef, SemaRef.ActOnUninitializedDecl(Sema::DeclPtrTy::make(Var), false);
Construct->getArgs(),
Construct->getNumArgs(),
TemplateArgs,
CommaLocs, InitArgs)) {
if (D->hasCXXDirectInitializer()) {
SourceLocation FakeLParenLoc =
SemaRef.PP.getLocForEndOfToken(D->getLocation());
SourceLocation FakeRParenLoc = CommaLocs.empty()? FakeLParenLoc
: CommaLocs.back();
SemaRef.AddCXXDirectInitializerToDecl(Sema::DeclPtrTy::make(Var),
FakeLParenLoc,
move_arg(InitArgs),
CommaLocs.data(),
FakeRParenLoc);
} else if (InitArgs.size() == 1) {
Expr *Init = (Expr*)(InitArgs.take()[0]);
SemaRef.AddInitializerToDecl(Sema::DeclPtrTy::make(Var),
SemaRef.Owned(Init),
false);
} else {
assert(InitArgs.size() == 0);
SemaRef.ActOnUninitializedDecl(Sema::DeclPtrTy::make(Var), false);
}
} }
} else { } else {
OwningExprResult Init // FIXME: Not too happy about invalidating the declaration
= SemaRef.SubstExpr(D->getInit(), TemplateArgs); // because of a bogus initializer.
Var->setInvalidDecl();
// FIXME: Not happy about invalidating decls just because of a bad
// initializer, unless it affects the type.
if (Init.isInvalid())
Var->setInvalidDecl();
else
SemaRef.AddInitializerToDecl(Sema::DeclPtrTy::make(Var), move(Init),
D->hasCXXDirectInitializer());
} }
SemaRef.PopExpressionEvaluationContext(); SemaRef.PopExpressionEvaluationContext();
@ -1888,29 +1910,15 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
Inits != InitsEnd; ++Inits) { Inits != InitsEnd; ++Inits) {
CXXBaseOrMemberInitializer *Init = *Inits; CXXBaseOrMemberInitializer *Init = *Inits;
SourceLocation LParenLoc, RParenLoc;
ASTOwningVector<&ActionBase::DeleteExpr> NewArgs(*this); ASTOwningVector<&ActionBase::DeleteExpr> NewArgs(*this);
llvm::SmallVector<SourceLocation, 4> CommaLocs; llvm::SmallVector<SourceLocation, 4> CommaLocs;
// Instantiate all the arguments. // Instantiate the initializer.
Expr *InitE = Init->getInit(); if (InstantiateInitializer(*this, Init->getInit(), TemplateArgs,
if (!InitE) { LParenLoc, CommaLocs, NewArgs, RParenLoc)) {
// Nothing to instantiate; AnyErrors = true;
} else if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(InitE)) { continue;
if (InstantiateInitializationArguments(*this, ParenList->getExprs(),
ParenList->getNumExprs(),
TemplateArgs, CommaLocs,
NewArgs)) {
AnyErrors = true;
continue;
}
} else {
OwningExprResult InitArg = SubstExpr(InitE, TemplateArgs);
if (InitArg.isInvalid()) {
AnyErrors = true;
continue;
}
NewArgs.push_back(InitArg.release());
} }
MemInitResult NewInit; MemInitResult NewInit;