From 7ca84af48ef9c079eedcabe7fe923fc842ea21ae Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Sat, 12 Dec 2009 07:25:49 +0000 Subject: [PATCH] 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 --- clang/lib/Sema/SemaExpr.cpp | 59 ++++++++++++++++++++++----- clang/test/SemaCXX/offsetof.cpp | 2 + clang/test/SemaCXX/vararg-non-pod.cpp | 9 ++++ 3 files changed, 59 insertions(+), 11 deletions(-) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index dbdaf59cbaa5..1ca47a40aa82 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -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(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; + } } } diff --git a/clang/test/SemaCXX/offsetof.cpp b/clang/test/SemaCXX/offsetof.cpp index e18987f11ad3..bc7a707ee546 100644 --- a/clang/test/SemaCXX/offsetof.cpp +++ b/clang/test/SemaCXX/offsetof.cpp @@ -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)); diff --git a/clang/test/SemaCXX/vararg-non-pod.cpp b/clang/test/SemaCXX/vararg-non-pod.cpp index c34f8d0b8f1d..db519d71611b 100644 --- a/clang/test/SemaCXX/vararg-non-pod.cpp +++ b/clang/test/SemaCXX/vararg-non-pod.cpp @@ -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()));