forked from OSchip/llvm-project
Unify initializer-instantiation code for variable declarations and
base/member initializers. llvm-svn: 97560
This commit is contained in:
parent
350bb062b2
commit
b30f22b911
|
@ -202,6 +202,72 @@ static bool InstantiateInitializationArguments(Sema &SemaRef,
|
|||
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) {
|
||||
// Do substitution on the type of the declaration
|
||||
TypeSourceInfo *DI = SemaRef.SubstType(D->getTypeSourceInfo(),
|
||||
|
@ -259,56 +325,20 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
|
|||
else
|
||||
SemaRef.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated);
|
||||
|
||||
// Extract the initializer, skipping through any temporary-binding
|
||||
// expressions and look at the subexpression as it was written.
|
||||
Expr *DInit = D->getInit();
|
||||
if (CXXExprWithTemporaries *ExprTemp
|
||||
= dyn_cast<CXXExprWithTemporaries>(DInit))
|
||||
DInit = ExprTemp->getSubExpr();
|
||||
while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(DInit))
|
||||
DInit = Binder->getSubExpr();
|
||||
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.
|
||||
// Instantiate the initializer.
|
||||
SourceLocation LParenLoc, RParenLoc;
|
||||
llvm::SmallVector<SourceLocation, 4> CommaLocs;
|
||||
ASTOwningVector<&ActionBase::DeleteExpr> InitArgs(SemaRef);
|
||||
if (!InstantiateInitializationArguments(SemaRef,
|
||||
PLE->getExprs(),
|
||||
PLE->getNumExprs(),
|
||||
TemplateArgs,
|
||||
CommaLocs, InitArgs)) {
|
||||
if (!InstantiateInitializer(SemaRef, D->getInit(), TemplateArgs, LParenLoc,
|
||||
CommaLocs, InitArgs, RParenLoc)) {
|
||||
// Attach the initializer to the declaration.
|
||||
if (D->hasCXXDirectInitializer()) {
|
||||
// Add the direct initializer to the declaration.
|
||||
SemaRef.AddCXXDirectInitializerToDecl(Sema::DeclPtrTy::make(Var),
|
||||
PLE->getLParenLoc(),
|
||||
LParenLoc,
|
||||
move_arg(InitArgs),
|
||||
CommaLocs.data(),
|
||||
PLE->getRParenLoc());
|
||||
}
|
||||
} else if (CXXConstructExpr *Construct =dyn_cast<CXXConstructExpr>(DInit)) {
|
||||
// The initializer resolved to a constructor. Instantiate the constructor
|
||||
// arguments.
|
||||
llvm::SmallVector<SourceLocation, 4> CommaLocs;
|
||||
ASTOwningVector<&ActionBase::DeleteExpr> InitArgs(SemaRef);
|
||||
|
||||
if (!InstantiateInitializationArguments(SemaRef,
|
||||
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);
|
||||
RParenLoc);
|
||||
} else if (InitArgs.size() == 1) {
|
||||
Expr *Init = (Expr*)(InitArgs.take()[0]);
|
||||
SemaRef.AddInitializerToDecl(Sema::DeclPtrTy::make(Var),
|
||||
|
@ -318,18 +348,10 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
|
|||
assert(InitArgs.size() == 0);
|
||||
SemaRef.ActOnUninitializedDecl(Sema::DeclPtrTy::make(Var), false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
OwningExprResult Init
|
||||
= SemaRef.SubstExpr(D->getInit(), TemplateArgs);
|
||||
|
||||
// FIXME: Not happy about invalidating decls just because of a bad
|
||||
// initializer, unless it affects the type.
|
||||
if (Init.isInvalid())
|
||||
// FIXME: Not too happy about invalidating the declaration
|
||||
// because of a bogus initializer.
|
||||
Var->setInvalidDecl();
|
||||
else
|
||||
SemaRef.AddInitializerToDecl(Sema::DeclPtrTy::make(Var), move(Init),
|
||||
D->hasCXXDirectInitializer());
|
||||
}
|
||||
|
||||
SemaRef.PopExpressionEvaluationContext();
|
||||
|
@ -1888,30 +1910,16 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
|
|||
Inits != InitsEnd; ++Inits) {
|
||||
CXXBaseOrMemberInitializer *Init = *Inits;
|
||||
|
||||
SourceLocation LParenLoc, RParenLoc;
|
||||
ASTOwningVector<&ActionBase::DeleteExpr> NewArgs(*this);
|
||||
llvm::SmallVector<SourceLocation, 4> CommaLocs;
|
||||
|
||||
// Instantiate all the arguments.
|
||||
Expr *InitE = Init->getInit();
|
||||
if (!InitE) {
|
||||
// Nothing to instantiate;
|
||||
} else if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(InitE)) {
|
||||
if (InstantiateInitializationArguments(*this, ParenList->getExprs(),
|
||||
ParenList->getNumExprs(),
|
||||
TemplateArgs, CommaLocs,
|
||||
NewArgs)) {
|
||||
// Instantiate the initializer.
|
||||
if (InstantiateInitializer(*this, Init->getInit(), TemplateArgs,
|
||||
LParenLoc, CommaLocs, NewArgs, RParenLoc)) {
|
||||
AnyErrors = true;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
OwningExprResult InitArg = SubstExpr(InitE, TemplateArgs);
|
||||
if (InitArg.isInvalid()) {
|
||||
AnyErrors = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
NewArgs.push_back(InitArg.release());
|
||||
}
|
||||
|
||||
MemInitResult NewInit;
|
||||
if (Init->isBaseInitializer()) {
|
||||
|
|
Loading…
Reference in New Issue