From bb53efb016d205d0aeed9cef69c2db51b3f351fc Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 16 May 2010 04:01:30 +0000 Subject: [PATCH] fix rdar://7985267 - Don't emit an error about a non-pod argument passed to va_start, it doesn't actually pass it. llvm-svn: 103899 --- clang/lib/Sema/Sema.h | 3 ++- clang/lib/Sema/SemaExpr.cpp | 20 +++++++++++++------- clang/lib/Sema/SemaExprObjC.cpp | 2 +- clang/lib/Sema/SemaOverload.cpp | 2 +- clang/test/SemaCXX/vararg-non-pod.cpp | 9 +++++++++ 5 files changed, 26 insertions(+), 10 deletions(-) diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 3e143bb3b00c..a7d242c559b5 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -4093,7 +4093,8 @@ public: // DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but // will warn if the resulting type is not a POD type. - bool DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT); + bool DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT, + FunctionDecl *FDecl); // UsualArithmeticConversions - performs the UsualUnaryConversions on it's // operands and then handles various conversions that are common to binary diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 60c716353a90..5a24a2c4c0a3 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -279,10 +279,9 @@ void Sema::DefaultArgumentPromotion(Expr *&Expr) { assert(!Ty.isNull() && "DefaultArgumentPromotion - missing type"); // If this is a 'float' (CVR qualified or typedef) promote to double. - if (const BuiltinType *BT = Ty->getAs()) - if (BT->getKind() == BuiltinType::Float) - return ImpCastExprToType(Expr, Context.DoubleTy, - CastExpr::CK_FloatingCast); + if (Ty->isSpecificBuiltinType(BuiltinType::Float)) + return ImpCastExprToType(Expr, Context.DoubleTy, + CastExpr::CK_FloatingCast); UsualUnaryConversions(Expr); } @@ -291,9 +290,16 @@ void Sema::DefaultArgumentPromotion(Expr *&Expr) { /// will warn if the resulting type is not a POD type, and rejects ObjC /// interfaces passed by value. This returns true if the argument type is /// completely illegal. -bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT) { +bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT, + FunctionDecl *FDecl) { DefaultArgumentPromotion(Expr); + // __builtin_va_start takes the second argument as a "varargs" argument, but + // it doesn't actually do anything with it. It doesn't need to be non-pod + // etc. + if (FDecl && FDecl->getBuiltinID() == Builtin::BI__builtin_va_start) + return false; + if (Expr->getType()->isObjCObjectType() && DiagRuntimeBehavior(Expr->getLocStart(), PDiag(diag::err_cannot_pass_objc_interface_to_vararg) @@ -3478,9 +3484,9 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, // If this is a variadic call, handle args passed through "...". if (CallType != VariadicDoesNotApply) { // Promote the arguments (C99 6.5.2.2p7). - for (unsigned i = ArgIx; i < NumArgs; i++) { + for (unsigned i = ArgIx; i != NumArgs; ++i) { Expr *Arg = Args[i]; - Invalid |= DefaultVariadicArgumentPromotion(Arg, CallType); + Invalid |= DefaultVariadicArgumentPromotion(Arg, CallType, FDecl); AllArgs.push_back(Arg); } } diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index fd4feedf9245..0b058be579a5 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -254,7 +254,7 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, if (Args[i]->isTypeDependent()) continue; - IsError |= DefaultVariadicArgumentPromotion(Args[i], VariadicMethod); + IsError |= DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, 0); } } else { // Check for extra arguments to non-variadic methods. diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index bf4e7f74ad9b..15f19723f896 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -7054,7 +7054,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, // Promote the arguments (C99 6.5.2.2p7). for (unsigned i = NumArgsInProto; i != NumArgs; i++) { Expr *Arg = Args[i]; - IsError |= DefaultVariadicArgumentPromotion(Arg, VariadicMethod); + IsError |= DefaultVariadicArgumentPromotion(Arg, VariadicMethod, 0); TheCall->setArg(i + 1, Arg); } } diff --git a/clang/test/SemaCXX/vararg-non-pod.cpp b/clang/test/SemaCXX/vararg-non-pod.cpp index d31f1f7196aa..f56d527c3773 100644 --- a/clang/test/SemaCXX/vararg-non-pod.cpp +++ b/clang/test/SemaCXX/vararg-non-pod.cpp @@ -88,3 +88,12 @@ void test_typeid(Base &base) { (void)typeid(get_base(base)); // expected-warning{{cannot pass object of non-POD type 'Base' through variadic function; call will abort at runtime}} (void)typeid(eat_base(base)); // okay } + + +// rdar://7985267 - Shouldn't warn, doesn't actually use __builtin_va_start is +// magic. + +void t6(Foo somearg, ... ) { + __builtin_va_start(0/*valist*/, somearg); +} +