diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -7756,11 +7756,15 @@ // conversion. if (getLangOpts().CPlusPlus11 && E->isGLValue() && E->getType().isVolatileQualified()) { - if (IsSpecialDiscardedValue(E)) { - ExprResult Res = DefaultLvalueConversion(E); - if (Res.isInvalid()) - return E; - E = Res.get(); + if (IsSpecialDiscardedValue(E)) { + // Don't try to apply lvalue-to-rvalue conversion to expressions of + // array types. + if (!E->getType()->isArrayType()) { + ExprResult Res = DefaultLvalueConversion(E); + if (Res.isInvalid()) + return E; + E = Res.get(); + } } else { // Per C++2a [expr.ass]p5, a volatile assignment is not deprecated if // it occurs as a discarded-value expression. diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -370,7 +370,10 @@ } } - if (E->isGLValue() && E->getType().isVolatileQualified()) { + // Tell the user to assign it into a variable to force a volatile load if this + // isn't an array. + if (E->isGLValue() && E->getType().isVolatileQualified() && + !E->getType()->isArrayType()) { Diag(Loc, diag::warn_unused_volatile) << R1 << R2; return; } diff --git a/clang/test/CXX/expr/p10-0x.cpp b/clang/test/CXX/expr/p10-0x.cpp --- a/clang/test/CXX/expr/p10-0x.cpp +++ b/clang/test/CXX/expr/p10-0x.cpp @@ -44,3 +44,12 @@ refcall(); 1 ? refcall() : *x; } + +// CHECK: define void @_Z2f3v() +// CHECK-NOT: load +// CHECK-NOT: memcpy + +void f3(void) { + volatile char a[10]; + a; +} diff --git a/clang/test/SemaCXX/warn-unused-value-cxx11.cpp b/clang/test/SemaCXX/warn-unused-value-cxx11.cpp --- a/clang/test/SemaCXX/warn-unused-value-cxx11.cpp +++ b/clang/test/SemaCXX/warn-unused-value-cxx11.cpp @@ -41,4 +41,13 @@ (void)noexcept(s.g() = 5); // Ok } -} \ No newline at end of file +} + +namespace volatile_array { +void test() { + char a[10]; + volatile char b[10]; + a; // expected-warning-re {{expression result unused{{$}}}} + b; // expected-warning-re {{expression result unused{{$}}}} +} +}