Suppress warnings and errors about certain uses of non-POD types (in

__builtin_offsetof, passing through an ellipsis) when we're in an
unevaluated context. This is the first part of the fix to PR5761,
which deals with the simple case of an unevaluated context.

llvm-svn: 91210
This commit is contained in:
Douglas Gregor 2009-12-12 07:25:49 +00:00
parent 9ad6ba3766
commit 7ca84af48e
3 changed files with 59 additions and 11 deletions

View File

@ -259,15 +259,39 @@ bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT) {
DefaultArgumentPromotion(Expr);
if (Expr->getType()->isObjCInterfaceType()) {
Diag(Expr->getLocStart(),
diag::err_cannot_pass_objc_interface_to_vararg)
<< Expr->getType() << CT;
return true;
switch (ExprEvalContexts.back().Context ) {
case Unevaluated:
// The argument will never be evaluated, so don't complain.
break;
case PotentiallyEvaluated:
Diag(Expr->getLocStart(),
diag::err_cannot_pass_objc_interface_to_vararg)
<< Expr->getType() << CT;
return true;
case PotentiallyPotentiallyEvaluated:
// FIXME: queue it!
break;
}
}
if (!Expr->getType()->isPODType())
Diag(Expr->getLocStart(), diag::warn_cannot_pass_non_pod_arg_to_vararg)
<< Expr->getType() << CT;
if (!Expr->getType()->isPODType()) {
switch (ExprEvalContexts.back().Context ) {
case Unevaluated:
// The argument will never be evaluated, so don't complain.
break;
case PotentiallyEvaluated:
Diag(Expr->getLocStart(), diag::warn_cannot_pass_non_pod_arg_to_vararg)
<< Expr->getType() << CT;
break;
case PotentiallyPotentiallyEvaluated:
// FIXME: queue it!
break;
}
}
return false;
}
@ -6451,10 +6475,23 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
RecordDecl *RD = RC->getDecl();
if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
if (!CRD->isPOD() && !DidWarnAboutNonPOD) {
ExprError(Diag(BuiltinLoc, diag::warn_offsetof_non_pod_type)
<< SourceRange(CompPtr[0].LocStart, OC.LocEnd)
<< Res->getType());
DidWarnAboutNonPOD = true;
switch (ExprEvalContexts.back().Context ) {
case Unevaluated:
// The argument will never be evaluated, so don't complain.
break;
case PotentiallyEvaluated:
ExprError(Diag(BuiltinLoc, diag::warn_offsetof_non_pod_type)
<< SourceRange(CompPtr[0].LocStart, OC.LocEnd)
<< Res->getType());
DidWarnAboutNonPOD = true;
break;
case PotentiallyPotentiallyEvaluated:
// FIXME: Queue it!
DidWarnAboutNonPOD = true;
break;
}
}
}

View File

@ -16,3 +16,5 @@ void f() {
struct Base { int x; };
struct Derived : Base { int y; };
int o = __builtin_offsetof(Derived, x); // expected-warning{{offset of on non-POD type}}
const int o2 = sizeof(__builtin_offsetof(Derived, x));

View File

@ -66,3 +66,12 @@ void t5()
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}}
}
// PR5761: unevaluated operands and the non-POD warning
class Foo {
public:
Foo() {}
};
int Helper(...);
const int size = sizeof(Helper(Foo()));