diff options
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 84 | ||||
-rw-r--r-- | test/SemaCXX/vararg-non-pod.cpp | 14 |
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 |