aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2009-09-08 01:48:42 +0000
committerAnders Carlsson <andersca@mac.com>2009-09-08 01:48:42 +0000
commitd74d4149f759b8abec15fb8163a4206e8c7068c8 (patch)
tree9a3265135bd10d1d04c7f86b5b8b1750dd34fc8e
parentbcb11d01c034f967503bd98f28bdf458c1ab8001 (diff)
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
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--lib/Sema/Sema.h3
-rw-r--r--lib/Sema/SemaDeclCXX.cpp84
-rw-r--r--test/SemaCXX/vararg-non-pod.cpp14
4 files changed, 75 insertions, 28 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 4917598180..c9bfaaf55b 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1706,7 +1706,7 @@ def err_cannot_pass_objc_interface_to_vararg : Error<
def warn_cannot_pass_non_pod_arg_to_vararg : Warning<
"cannot pass object of non-POD type %0 through variadic "
- "%select{function|block|method}1; call will abort at runtime">;
+ "%select{function|block|method|constructor}1; call will abort at runtime">;
def err_typecheck_call_invalid_ordered_compare : Error<
"ordered compare requires two args of floating point type (%0 and %1)">;
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 12cafe83c5..a040a0f169 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -3287,7 +3287,8 @@ public:
enum VariadicCallType {
VariadicFunction,
VariadicBlock,
- VariadicMethod
+ VariadicMethod,
+ VariadicConstructor
};
// DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 8c5384b471..c37ff10941 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2834,6 +2834,60 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
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 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
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);
-
- OwningExprResult ArgExpr =
- BuildCXXDefaultArgExpr(ConstructLoc, FDecl, Param);
- if (ArgExpr.isInvalid())
- return ExprError();
+
+ if (CheckConstructArgumentTypes(*this, ConstructLoc, Temp.get()))
+ return ExprError();
- Temp->setArg(j, ArgExpr.takeAs<Expr>());
- }
return move(Temp);
}
@@ -2879,20 +2924,9 @@ Sema::BuildCXXTemporaryObjectExpr(CXXConstructorDecl *Constructor,
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);
-
- OwningExprResult ArgExpr = BuildCXXDefaultArgExpr(TyBeginLoc, FDecl, Param);
- if (ArgExpr.isInvalid())
- return ExprError();
-
- Temp->setArg(j, ArgExpr.takeAs<Expr>());
- }
+ if (CheckConstructArgumentTypes(*this, TyBeginLoc, Temp.get()))
+ return ExprError();
- Args.release();
return move(Temp);
}
diff --git a/test/SemaCXX/vararg-non-pod.cpp b/test/SemaCXX/vararg-non-pod.cpp
index 1c5fe74a15..390f58b1b7 100644
--- a/test/SemaCXX/vararg-non-pod.cpp
+++ b/test/SemaCXX/vararg-non-pod.cpp
@@ -51,6 +51,18 @@ void t4()
D d;
- d(10, c); // expected-warning{{Line 48: cannot pass object of non-POD type 'class C' through variadic method; call will abort at runtime}}
+ d(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic method; call will abort at runtime}}
d(10, version);
}
+
+class E {
+ E(int, ...);
+};
+
+void t5()
+{
+ C c(10);
+
+ E e(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic constructor; call will abort at runtime}}
+ (void)E(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic constructor; call will abort at runtime}}
+} \ No newline at end of file