aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-12-12 07:25:49 +0000
committerDouglas Gregor <dgregor@apple.com>2009-12-12 07:25:49 +0000
commit75b699a883ed02e9183cb5f4ad7086f4e3c6adf1 (patch)
tree57cd4da69e19f2ce662b942552917371d97750fe
parent9f61aa9e280adea9fbf3365f0e4f6ed568c9885a (diff)
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91210 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaExpr.cpp59
-rw-r--r--test/SemaCXX/offsetof.cpp2
-rw-r--r--test/SemaCXX/vararg-non-pod.cpp9
3 files changed, 59 insertions, 11 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index dbdaf59cba..1ca47a40aa 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/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<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;
+ }
}
}
diff --git a/test/SemaCXX/offsetof.cpp b/test/SemaCXX/offsetof.cpp
index e18987f11a..bc7a707ee5 100644
--- a/test/SemaCXX/offsetof.cpp
+++ b/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/test/SemaCXX/vararg-non-pod.cpp b/test/SemaCXX/vararg-non-pod.cpp
index c34f8d0b8f..db519d7161 100644
--- a/test/SemaCXX/vararg-non-pod.cpp
+++ b/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()));