Introduce a new expression type, CXXUnresolvedConstructExpr, to
describe the construction of a value of a given type using function
syntax, e.g.,
T(a1, a2, ..., aN)
when the type or any of its arguments are type-dependent. In this
case, we don't know what kind of type-construction this will be: it
might construct a temporary of type 'T' (which might be a class or
non-class type) or might perform a conversion to type 'T'. Also,
implement printing of and template instantiation for this new
expression type. Due to the change in Sema::ActOnCXXTypeConstructExpr,
our existing tests cover template instantiation of this new expression
node.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72176 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index a138f01..a73843c 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -314,6 +314,45 @@
return &SubExpr + 1;
}
+CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(
+ SourceLocation TyBeginLoc,
+ QualType T,
+ SourceLocation LParenLoc,
+ Expr **Args,
+ unsigned NumArgs,
+ SourceLocation RParenLoc)
+ : Expr(CXXUnresolvedConstructExprClass, T.getNonReferenceType(),
+ T->isDependentType(), true),
+ TyBeginLoc(TyBeginLoc),
+ Type(T),
+ LParenLoc(LParenLoc),
+ RParenLoc(RParenLoc),
+ NumArgs(NumArgs) {
+ Stmt **StoredArgs = reinterpret_cast<Stmt **>(this + 1);
+ memcpy(StoredArgs, Args, sizeof(Expr *) * NumArgs);
+}
+
+CXXUnresolvedConstructExpr *
+CXXUnresolvedConstructExpr::Create(ASTContext &C,
+ SourceLocation TyBegin,
+ QualType T,
+ SourceLocation LParenLoc,
+ Expr **Args,
+ unsigned NumArgs,
+ SourceLocation RParenLoc) {
+ void *Mem = C.Allocate(sizeof(CXXUnresolvedConstructExpr) +
+ sizeof(Expr *) * NumArgs);
+ return new (Mem) CXXUnresolvedConstructExpr(TyBegin, T, LParenLoc,
+ Args, NumArgs, RParenLoc);
+}
+
+Stmt::child_iterator CXXUnresolvedConstructExpr::child_begin() {
+ return child_iterator(reinterpret_cast<Stmt **>(this + 1));
+}
+
+Stmt::child_iterator CXXUnresolvedConstructExpr::child_end() {
+ return child_iterator(reinterpret_cast<Stmt **>(this + 1) + NumArgs);
+}
//===----------------------------------------------------------------------===//
// Cloners
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 380634d..30de402 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -1110,6 +1110,21 @@
PrintExpr(E->getSubExpr());
}
+void
+StmtPrinter::VisitCXXUnresolvedConstructExpr(
+ CXXUnresolvedConstructExpr *Node) {
+ OS << Node->getTypeAsWritten().getAsString();
+ OS << "(";
+ for (CXXUnresolvedConstructExpr::arg_iterator Arg = Node->arg_begin(),
+ ArgEnd = Node->arg_end();
+ Arg != ArgEnd; ++Arg) {
+ if (Arg != Node->arg_begin())
+ OS << ", ";
+ PrintExpr(*Arg);
+ }
+ OS << ")";
+}
+
static const char *getTypeTraitName(UnaryTypeTrait UTT) {
switch (UTT) {
default: assert(false && "Unknown type trait");
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 30a7598..b957510 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -164,14 +164,11 @@
CallExpr::hasAnyTypeDependentArguments(Exprs, NumExprs)) {
exprs.release();
- // FIXME: Is this correct (I don't think so). Instead, we should have an
- // CXXUnresolvedTemporaryObjectExpr node for this.
- CXXTempVarDecl *Temp = CXXTempVarDecl::Create(Context, CurContext, Ty);
-
- return Owned(new (Context) CXXTemporaryObjectExpr(Context, Temp, 0, Ty,
- TyBeginLoc,
- Exprs, NumExprs,
- RParenLoc));
+ return Owned(CXXUnresolvedConstructExpr::Create(Context,
+ TypeRange.getBegin(), Ty,
+ LParenLoc,
+ Exprs, NumExprs,
+ RParenLoc));
}
diff --git a/lib/Sema/SemaTemplateInstantiateExpr.cpp b/lib/Sema/SemaTemplateInstantiateExpr.cpp
index a0e2941..1dad862 100644
--- a/lib/Sema/SemaTemplateInstantiateExpr.cpp
+++ b/lib/Sema/SemaTemplateInstantiateExpr.cpp
@@ -93,6 +93,8 @@
// FIXME: UnaryTypeTraitExpr
// FIXME: QualifiedDeclRefExpr
// FIXME: CXXExprWithTemporaries
+ OwningExprResult VisitCXXUnresolvedConstructExpr(
+ CXXUnresolvedConstructExpr *E);
OwningExprResult VisitGNUNullExpr(GNUNullExpr *E);
OwningExprResult VisitUnresolvedFunctionNameExpr(
UnresolvedFunctionNameExpr *E);
@@ -834,6 +836,45 @@
}
Sema::OwningExprResult
+TemplateExprInstantiator::VisitCXXUnresolvedConstructExpr(
+ CXXUnresolvedConstructExpr *E) {
+ QualType T = SemaRef.InstantiateType(E->getTypeAsWritten(), TemplateArgs,
+ E->getTypeBeginLoc(),
+ DeclarationName());
+ if (T.isNull())
+ return SemaRef.ExprError();
+
+ llvm::SmallVector<Expr *, 8> Args;
+ llvm::SmallVector<SourceLocation, 8> FakeCommaLocs;
+ for (CXXUnresolvedConstructExpr::arg_iterator Arg = E->arg_begin(),
+ ArgEnd = E->arg_end();
+ Arg != ArgEnd; ++Arg) {
+ OwningExprResult InstArg = Visit(*Arg);
+ if (InstArg.isInvalid()) {
+ for (unsigned I = 0; I != Args.size(); ++I)
+ Args[I]->Destroy(SemaRef.Context);
+ return SemaRef.ExprError();
+ }
+
+ FakeCommaLocs.push_back(
+ SemaRef.PP.getLocForEndOfToken((*Arg)->getSourceRange().getEnd()));
+ Args.push_back(InstArg.takeAs<Expr>());
+ }
+
+ // FIXME: The end of the type range isn't exactly correct.
+ // FIXME: we're faking the locations of the commas
+ return SemaRef.ActOnCXXTypeConstructExpr(SourceRange(E->getTypeBeginLoc(),
+ E->getLParenLoc()),
+ T.getAsOpaquePtr(),
+ E->getLParenLoc(),
+ Sema::MultiExprArg(SemaRef,
+ (void **)&Args.front(),
+ Args.size()),
+ &FakeCommaLocs.front(),
+ E->getRParenLoc());
+}
+
+Sema::OwningExprResult
Sema::InstantiateExpr(Expr *E, const TemplateArgumentList &TemplateArgs) {
if (!E)
return Owned((Expr *)0);