diff options
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 7 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 5 | ||||
-rw-r--r-- | test/CodeGen/exprs.c | 18 |
3 files changed, 26 insertions, 4 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index cf17566d41..3d6d59a406 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -269,6 +269,13 @@ void Sema::DefaultFunctionArrayLvalueConversion(Expr *&E) { T->isRecordType())) return; + // The C standard is actually really unclear on this point, and + // DR106 tells us what the result should be but not why. It's + // generally best to say that void just doesn't undergo + // lvalue-to-rvalue at all. + if (T->isVoidType()) + return; + // C++ [conv.lval]p1: // [...] If T is a non-class type, the type of the prvalue is the // cv-unqualified version of T. Otherwise, the type of the diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index fc396b992f..eec2fc88db 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -3549,8 +3549,9 @@ void Sema::IgnoredValueConversions(Expr *&E) { } DefaultFunctionArrayLvalueConversion(E); - RequireCompleteType(E->getExprLoc(), E->getType(), - diag::err_incomplete_type); + if (!E->getType()->isVoidType()) + RequireCompleteType(E->getExprLoc(), E->getType(), + diag::err_incomplete_type); } ExprResult Sema::ActOnFinishFullExpr(Expr *FullExpr) { diff --git a/test/CodeGen/exprs.c b/test/CodeGen/exprs.c index c9978b8516..452c823d15 100644 --- a/test/CodeGen/exprs.c +++ b/test/CodeGen/exprs.c @@ -147,8 +147,22 @@ double f13(double X) { } // Check operations on incomplete types. -struct s14; -void f14(struct s13 *a) { +void f14(struct s14 *a) { (void) &*a; } +// CHECK: define void @f15 +void f15(void *v, const void *cv, volatile void *vv) { + extern void f15_helper(void); + f15_helper(); + // CHECK: call void @f15_helper() + // FIXME: no loads from i8* should occur here at all! + *v; *v, *v; v ? *v : *v; + *cv; *cv, *cv; v ? *cv : *cv; + *vv; *vv, *vv; vv ? *vv : *vv; + // CHECK: volatile load i8* + // CHECK: volatile load i8* + // CHECK: volatile load i8* + // CHECK-NOT: load i8* % + // CHECK: ret void +} |