Handle variadic constructors better. Share code between BuildCXXConstructExpr and BuildCXXTemporaryObjectExpr.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81181 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 8c5384b..c37ff10 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2834,6 +2834,60 @@
Elidable, move(ExprArgs));
}
+static bool
+CheckConstructArgumentTypes(Sema &SemaRef, SourceLocation ConstructLoc,
+ CXXConstructExpr *E) {
+ CXXConstructorDecl *Ctor = E->getConstructor();
+ const FunctionProtoType *Proto = Ctor->getType()->getAsFunctionProtoType();
+
+ unsigned NumArgs = E->getNumArgs();
+ unsigned NumArgsInProto = Proto->getNumArgs();
+ unsigned NumRequiredArgs = Ctor->getMinRequiredArguments();
+
+ for (unsigned i = 0; i != NumArgsInProto; ++i) {
+ QualType ProtoArgType = Proto->getArgType(i);
+
+ Expr *Arg;
+
+ if (i < NumRequiredArgs) {
+ Arg = E->getArg(i);
+
+ // Pass the argument.
+ // FIXME: Do this.
+ } else {
+ // Build a default argument.
+ ParmVarDecl *Param = Ctor->getParamDecl(i);
+
+ Sema::OwningExprResult ArgExpr =
+ SemaRef.BuildCXXDefaultArgExpr(ConstructLoc, Ctor, Param);
+ if (ArgExpr.isInvalid())
+ return true;
+
+ Arg = ArgExpr.takeAs<Expr>();
+ }
+
+ E->setArg(i, Arg);
+ }
+
+ // If this is a variadic call, handle args passed through "...".
+ if (Proto->isVariadic()) {
+ bool Invalid = false;
+
+ // Promote the arguments (C99 6.5.2.2p7).
+ for (unsigned i = NumArgsInProto; i != NumArgs; i++) {
+ Expr *Arg = E->getArg(i);
+ Invalid |=
+ SemaRef.DefaultVariadicArgumentPromotion(Arg,
+ Sema::VariadicConstructor);
+ E->setArg(i, Arg);
+ }
+
+ return Invalid;
+ }
+
+ return false;
+}
+
/// BuildCXXConstructExpr - Creates a complete call to a constructor,
/// including handling of its default argument expressions.
Sema::OwningExprResult
@@ -2850,19 +2904,10 @@
Elidable,
Exprs,
NumExprs));
- // Default arguments must be added to constructor call expression.
- FunctionDecl *FDecl = cast<FunctionDecl>(Constructor);
- unsigned NumArgsInProto = FDecl->param_size();
- for (unsigned j = NumExprs; j != NumArgsInProto; j++) {
- ParmVarDecl *Param = FDecl->getParamDecl(j);
+
+ if (CheckConstructArgumentTypes(*this, ConstructLoc, Temp.get()))
+ return ExprError();
- OwningExprResult ArgExpr =
- BuildCXXDefaultArgExpr(ConstructLoc, FDecl, Param);
- if (ArgExpr.isInvalid())
- return ExprError();
-
- Temp->setArg(j, ArgExpr.takeAs<Expr>());
- }
return move(Temp);
}
@@ -2879,20 +2924,9 @@
ExprOwningPtr<CXXTemporaryObjectExpr> Temp(this, E);
- // Default arguments must be added to constructor call expression.
- FunctionDecl *FDecl = cast<FunctionDecl>(Constructor);
- unsigned NumArgsInProto = FDecl->param_size();
- for (unsigned j = Args.size(); j != NumArgsInProto; j++) {
- ParmVarDecl *Param = FDecl->getParamDecl(j);
+ if (CheckConstructArgumentTypes(*this, TyBeginLoc, Temp.get()))
+ return ExprError();
- OwningExprResult ArgExpr = BuildCXXDefaultArgExpr(TyBeginLoc, FDecl, Param);
- if (ArgExpr.isInvalid())
- return ExprError();
-
- Temp->setArg(j, ArgExpr.takeAs<Expr>());
- }
-
- Args.release();
return move(Temp);
}