From dce5e2cabf07ff25eb4d9e1859c0a21c69f588d2 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Fri, 16 Jan 2009 16:48:51 +0000 Subject: [PATCH] Use a single function for doing vararg argument promotion. Also, make sure to do the promotion before checking the type - fixes PR3340. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62323 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/Sema.h | 11 ++++++++++ lib/Sema/SemaExpr.cpp | 34 ++++++++++++++++++++----------- lib/Sema/SemaExprObjC.cpp | 11 ++-------- lib/Sema/SemaOverload.cpp | 8 +------- test/SemaCXX/vararg-non-pod.cpp | 7 +++++++ test/SemaObjCXX/vararg-non-pod.mm | 3 +++ 6 files changed, 46 insertions(+), 28 deletions(-) diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 9bfa1ffefc..668cf5b7c4 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1523,6 +1523,17 @@ public: // do not have a prototype. Integer promotions are performed on each // argument, and arguments that have type float are promoted to double. void DefaultArgumentPromotion(Expr *&Expr); + + // Used for emitting the right warning by DefaultVariadicArgumentPromotion + enum VariadicCallType { + VariadicFunction, + VariadicBlock, + VariadicMethod + }; + + // DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but + // will warn if the resulting type is not a POD type. + void DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT); // UsualArithmeticConversions - performs the UsualUnaryConversions on it's // operands and then handles various conversions that are common to binary diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index bf2d7b1489..820326f77a 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -87,6 +87,21 @@ void Sema::DefaultArgumentPromotion(Expr *&Expr) { UsualUnaryConversions(Expr); } +// DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but +// will warn if the resulting type is not a POD type. +void Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT) + +{ + DefaultArgumentPromotion(Expr); + + if (!Expr->getType()->isPODType()) { + Diag(Expr->getLocStart(), + diag::warn_cannot_pass_non_pod_arg_to_vararg) << + Expr->getType() << CT; + } +} + + /// UsualArithmeticConversions - Performs various conversions that are common to /// binary operators (C99 6.3.1.8). If both operands aren't arithmetic, this /// routine returns the first non-arithmetic type found. The client is @@ -1703,21 +1718,16 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, // If this is a variadic call, handle args passed through "...". if (Proto->isVariadic()) { + VariadicCallType CallType = VariadicFunction; + if (Fn->getType()->isBlockPointerType()) + CallType = VariadicBlock; // Block + else if (isa(Fn)) + CallType = VariadicMethod; + // Promote the arguments (C99 6.5.2.2p7). for (unsigned i = NumArgsInProto; i != NumArgs; i++) { Expr *Arg = Args[i]; - if (!Arg->getType()->isPODType()) { - int CallType = 0; - if (Fn->getType()->isBlockPointerType()) - CallType = 1; // Block - else if (isa(Fn)) - CallType = 2; - - Diag(Arg->getLocStart(), - diag::warn_cannot_pass_non_pod_arg_to_vararg) << - Arg->getType() << CallType; - } - DefaultArgumentPromotion(Arg); + DefaultVariadicArgumentPromotion(Arg, CallType); Call->setArg(i, Arg); } } diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index a73f386dab..548389db37 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -156,15 +156,8 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, // Promote additional arguments to variadic methods. if (Method->isVariadic()) { - for (unsigned i = NumNamedArgs; i < NumArgs; ++i) { - if (!Args[i]->getType()->isPODType()) { - Diag(Args[i]->getLocStart(), - diag::warn_cannot_pass_non_pod_arg_to_vararg) << - Args[i]->getType() << 2; // Method - } - - DefaultArgumentPromotion(Args[i]); - } + for (unsigned i = NumNamedArgs; i < NumArgs; ++i) + DefaultVariadicArgumentPromotion(Args[i], VariadicMethod); } else { // Check for extra arguments to non-variadic methods. if (NumArgs != NumNamedArgs) { diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index fca1556028..170ef1b59c 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -3624,14 +3624,8 @@ 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]; - - if (!Arg->getType()->isPODType()) { - Diag(Arg->getLocStart(), - diag::warn_cannot_pass_non_pod_arg_to_vararg) << - Arg->getType() << 2; // Method - } - DefaultArgumentPromotion(Arg); + DefaultVariadicArgumentPromotion(Arg, VariadicMethod); TheCall->setArg(i + 1, Arg); } } diff --git a/test/SemaCXX/vararg-non-pod.cpp b/test/SemaCXX/vararg-non-pod.cpp index d413335243..ac108e6ad5 100644 --- a/test/SemaCXX/vararg-non-pod.cpp +++ b/test/SemaCXX/vararg-non-pod.cpp @@ -1,5 +1,7 @@ // RUN: clang -fsyntax-only -verify -fblocks %s +extern char version[]; + class C { public: C(int); @@ -14,6 +16,7 @@ void t1() C c(10); g(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic function; call will abort at runtime}} + g(10, version); } void t2() @@ -21,8 +24,10 @@ void t2() C c(10); c.g(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic method; call will abort at runtime}} + c.g(10, version); C::h(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic function; call will abort at runtime}} + C::h(10, version); } int (^block)(int, ...); @@ -32,6 +37,7 @@ void t3() C c(10); block(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic block; call will abort at runtime}} + block(10, version); } class D { @@ -46,4 +52,5 @@ 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, version); } diff --git a/test/SemaObjCXX/vararg-non-pod.mm b/test/SemaObjCXX/vararg-non-pod.mm index 3431dea9e5..83266381ae 100644 --- a/test/SemaObjCXX/vararg-non-pod.mm +++ b/test/SemaObjCXX/vararg-non-pod.mm @@ -1,5 +1,7 @@ // RUN: clang -fsyntax-only -verify %s +extern char version[]; + class C { public: C(int); @@ -14,5 +16,6 @@ void t1(D *d) C c(10); [d g:10, c]; // expected-warning{{cannot pass object of non-POD type 'class C' through variadic method; call will abort at runtime}} + [d g:10, version]; } -- 2.40.0