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
This commit is contained in:
Anders Carlsson 2009-01-16 16:48:51 +00:00
Родитель 636c5ef657
Коммит dce5e2cabf
6 изменённых файлов: 46 добавлений и 28 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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<MemberExpr>(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<MemberExpr>(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);
}
}

Просмотреть файл

@ -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) {

Просмотреть файл

@ -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);
}
}

Просмотреть файл

@ -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);
}

Просмотреть файл

@ -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];
}