Template instantiation for the various kinds of AST nodes that occur
due to C++ type construction of the form T(a1, a2, ..., aN).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72183 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index f3c8244..df01e9b 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -431,8 +431,11 @@
void Destroy(ASTContext &C);
- const VarDecl* getVarDecl() const { return VD; }
- const CXXConstructorDecl* getConstructor() const { return Constructor; }
+ VarDecl* getVarDecl() const { return VD; }
+ CXXConstructorDecl* getConstructor() const { return Constructor; }
+
+ /// \brief Whether this construction is elidable.
+ bool isElidable() const { return Elidable; }
typedef ExprIterator arg_iterator;
typedef ConstExprIterator const_arg_iterator;
@@ -537,7 +540,7 @@
public:
CXXZeroInitValueExpr(QualType ty, SourceLocation tyBeginLoc,
SourceLocation rParenLoc ) :
- Expr(CXXZeroInitValueExprClass, ty),
+ Expr(CXXZeroInitValueExprClass, ty, false, false),
TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {}
SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
@@ -553,6 +556,8 @@
return SourceRange(TyBeginLoc, RParenLoc);
}
+ CXXZeroInitValueExpr* Clone(ASTContext &C) const;
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXZeroInitValueExprClass;
}
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index a73843c..cca391e 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -365,3 +365,7 @@
CXXNullPtrLiteralExpr* CXXNullPtrLiteralExpr::Clone(ASTContext &C) const {
return new (C) CXXNullPtrLiteralExpr(getType(), Loc);
}
+
+CXXZeroInitValueExpr* CXXZeroInitValueExpr::Clone(ASTContext &C) const {
+ return new (C) CXXZeroInitValueExpr(getType(), TyBeginLoc, RParenLoc);
+}
diff --git a/lib/Sema/SemaTemplateInstantiateExpr.cpp b/lib/Sema/SemaTemplateInstantiateExpr.cpp
index 1dad862..1b2fa46 100644
--- a/lib/Sema/SemaTemplateInstantiateExpr.cpp
+++ b/lib/Sema/SemaTemplateInstantiateExpr.cpp
@@ -85,9 +85,9 @@
// FIXME: CXXTypeIdExpr
// FIXME: CXXThrowExpr
// FIXME: CXXDefaultArgExpr
- // FIXME: CXXConstructExpr
- // FIXME: CXXFunctionalCastExpr
- // FIXME: CXXZeroInitValueExpr
+ OwningExprResult VisitCXXConstructExpr(CXXConstructExpr *E);
+ OwningExprResult VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E);
+ OwningExprResult VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E);
// FIXME: CXXNewExpr
// FIXME: CXXDeleteExpr
// FIXME: UnaryTypeTraitExpr
@@ -836,6 +836,87 @@
}
Sema::OwningExprResult
+TemplateExprInstantiator::VisitCXXConstructExpr(CXXConstructExpr *E) {
+ assert(!cast<CXXRecordDecl>(E->getConstructor()->getDeclContext())
+ ->isDependentType() && "Dependent constructor shouldn't be here");
+
+ QualType T = SemaRef.InstantiateType(E->getType(), TemplateArgs,
+ /*FIXME*/E->getSourceRange().getBegin(),
+ DeclarationName());
+ if (T.isNull())
+ return SemaRef.ExprError();
+
+ bool Invalid = false;
+ llvm::SmallVector<Expr *, 8> Args;
+ for (CXXConstructExpr::arg_iterator Arg = E->arg_begin(),
+ ArgEnd = E->arg_end();
+ Arg != ArgEnd; ++Arg) {
+ OwningExprResult ArgInst = Visit(*Arg);
+ if (ArgInst.isInvalid()) {
+ Invalid = true;
+ break;
+ }
+
+ Args.push_back(ArgInst.takeAs<Expr>());
+ }
+
+
+ VarDecl *Var = 0;
+ if (!Invalid) {
+ Var = cast_or_null<VarDecl>(SemaRef.InstantiateDecl(E->getVarDecl(),
+ SemaRef.CurContext,
+ TemplateArgs));
+ if (!Var)
+ Invalid = true;
+ }
+
+ if (Invalid) {
+ for (unsigned I = 0, N = Args.size(); I != N; ++I)
+ Args[I]->Destroy(SemaRef.Context);
+
+ return SemaRef.ExprError();
+ }
+
+ return SemaRef.Owned(CXXConstructExpr::Create(SemaRef.Context, Var, T,
+ E->getConstructor(),
+ E->isElidable(),
+ &Args.front(), Args.size()));
+}
+
+Sema::OwningExprResult
+TemplateExprInstantiator::VisitCXXFunctionalCastExpr(
+ CXXFunctionalCastExpr *E) {
+ // Instantiate the type that we're casting to.
+ QualType ExplicitTy = SemaRef.InstantiateType(E->getTypeAsWritten(),
+ TemplateArgs,
+ E->getTypeBeginLoc(),
+ DeclarationName());
+ if (ExplicitTy.isNull())
+ return SemaRef.ExprError();
+
+ // Instantiate the subexpression.
+ OwningExprResult SubExpr = Visit(E->getSubExpr());
+ if (SubExpr.isInvalid())
+ return SemaRef.ExprError();
+
+ // FIXME: The end of the type's source range is wrong
+ Expr *Sub = SubExpr.takeAs<Expr>();
+ return SemaRef.ActOnCXXTypeConstructExpr(SourceRange(E->getTypeBeginLoc()),
+ ExplicitTy.getAsOpaquePtr(),
+ /*FIXME:*/E->getTypeBeginLoc(),
+ Sema::MultiExprArg(SemaRef,
+ (void **)&Sub,
+ 1),
+ 0,
+ E->getRParenLoc());
+}
+
+Sema::OwningExprResult
+TemplateExprInstantiator::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) {
+ return SemaRef.Clone(E);
+}
+
+Sema::OwningExprResult
TemplateExprInstantiator::VisitCXXUnresolvedConstructExpr(
CXXUnresolvedConstructExpr *E) {
QualType T = SemaRef.InstantiateType(E->getTypeAsWritten(), TemplateArgs,
diff --git a/test/SemaTemplate/instantiate-expr-4.cpp b/test/SemaTemplate/instantiate-expr-4.cpp
new file mode 100644
index 0000000..a5b55b3
--- /dev/null
+++ b/test/SemaTemplate/instantiate-expr-4.cpp
@@ -0,0 +1,35 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// ---------------------------------------------------------------------
+// C++ Functional Casts
+// ---------------------------------------------------------------------
+template<int N>
+struct ValueInit0 {
+ int f() {
+ return int();
+ }
+};
+
+template struct ValueInit0<5>;
+
+template<int N>
+struct FunctionalCast0 {
+ int f() {
+ return int(N);
+ }
+};
+
+template struct FunctionalCast0<5>;
+
+struct X {
+ X(int, int);
+};
+
+template<int N, int M>
+struct BuildTemporary0 {
+ X f() {
+ return X(N, M);
+ }
+};
+
+template struct BuildTemporary0<5, 7>;