aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/SemaExpr.cpp7
-rw-r--r--lib/Sema/SemaExprCXX.cpp5
-rw-r--r--test/CodeGen/exprs.c18
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
+}