Index: clang/include/clang/AST/Expr.h =================================================================== --- clang/include/clang/AST/Expr.h +++ clang/include/clang/AST/Expr.h @@ -3546,6 +3546,21 @@ CastKind getCastKind() const { return (CastKind) CastExprBits.Kind; } void setCastKind(CastKind K) { CastExprBits.Kind = K; } + /// Return + // True : If the cast expr has the volatileness in the cast node path and + // DeclRefExprNode not has the volatile qualfiler like + // |-ImplicitCastExpr 'int' + // | `-CXXStaticCastExpr 'volatile int' lvalue static_cast + // | `-ImplicitCastExpr 'volatile int' lvalue part_of_explicit_cast + // | `-DeclRefExpr 'int' lvalue Var 'x' 'int' + // False : Otherwise. + bool isDeclRefExprNodeNotVolatile() { + return (this->isGLValue() && + (this->getType().isVolatileQualified() != + this->getSubExprAsWritten()->getType().isVolatileQualified())); + } + + static const char *getCastKindName(CastKind CK); const char *getCastKindName() const { return getCastKindName(getCastKind()); } Index: clang/lib/CodeGen/CGExpr.cpp =================================================================== --- clang/lib/CodeGen/CGExpr.cpp +++ clang/lib/CodeGen/CGExpr.cpp @@ -4805,6 +4805,9 @@ // bound and change the IR type. // FIXME: Once pointee types are removed from IR, remove this. LValue LV = EmitLValue(E->getSubExpr()); + // Propagate the volatile qualifer to LValue, if exist in E. + if (E->getType().isVolatileQualified()) + LV.getQuals().addVolatile(); if (LV.isSimple()) { Address V = LV.getAddress(*this); if (V.isValid()) { Index: clang/lib/CodeGen/CGExprComplex.cpp =================================================================== --- clang/lib/CodeGen/CGExprComplex.cpp +++ clang/lib/CodeGen/CGExprComplex.cpp @@ -182,6 +182,8 @@ ComplexPairTy VisitCastExpr(CastExpr *E) { if (const auto *ECE = dyn_cast(E)) CGF.CGM.EmitExplicitCastExprType(ECE, &CGF); + if (E->getCastKind() == CK_NoOp && E->isDeclRefExprNodeNotVolatile()) + return EmitLoadOfLValue(E); return EmitCast(E->getCastKind(), E->getSubExpr(), E->getType()); } ComplexPairTy VisitCallExpr(const CallExpr *E); Index: clang/lib/CodeGen/CGExprScalar.cpp =================================================================== --- clang/lib/CodeGen/CGExprScalar.cpp +++ clang/lib/CodeGen/CGExprScalar.cpp @@ -2225,7 +2225,9 @@ return Visit(const_cast(E)); case CK_NoOp: { - llvm::Value *V = Visit(const_cast(E)); + llvm::Value *V = CE->isDeclRefExprNodeNotVolatile() + ? EmitLoadOfLValue(CE) + : Visit(const_cast(E)) ; if (V) { // CK_NoOp can model a pointer qualification conversion, which can remove // an array bound and change the IR type. Index: clang/test/CodeGen/volatile.cpp =================================================================== --- /dev/null +++ clang/test/CodeGen/volatile.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -O2 -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK +struct agg +{ +int a ; +int b ; +} t; +struct agg a; +int vt; +_Complex float cf; + +void f0() { + const_cast(cf) = const_cast(cf) + 1; +// CHECK: %cf.real = load volatile float, ptr @cf +// CHECK: %cf.imag = load volatile float, ptr getelementptr +// CHECK: %add.r = fadd float %cf.real, 1.000000e+00 +// CHECK: %add.i = fadd float %cf.imag, 0.000000e+00 +// CHECK: store volatile float %add.r +// CHECK: store volatile float %add.i, ptr getelementptr + static_cast(cf) = static_cast(cf) + 1; +// CHECK: %cf.real1 = load volatile float, ptr @cf +// CHECK: %cf.imag2 = load volatile float, ptr getelementptr +// CHECK: %add.r3 = fadd float %cf.real1, 1.000000e+00 +// CHECK: %add.i4 = fadd float %cf.imag2, 0.000000e+00 +// CHECK: store volatile float %add.r3, ptr @cf +// CHECK: store volatile float %add.i4, ptr getelementptr + const_cast(a.a) = const_cast(t.a) ; +// CHECK: %0 = load volatile i32, ptr @t +// CHECK: store volatile i32 %0, ptr @a + static_cast(a.b) = static_cast(t.a) ; +// CHECK: %1 = load volatile i32, ptr @t +// CHECK: store volatile i32 %1, ptr getelementptr + const_cast(vt) = const_cast(vt) + 1; +// CHECK: %2 = load volatile i32, ptr @vt +// CHECK: %add = add nsw i32 %2, 1 +// CHECK: store volatile i32 %add, ptr @vt + static_cast(vt) = static_cast(vt) + 1; +// CHECK: %3 = load volatile i32, ptr @vt +// CHECK: %add5 = add nsw i32 %3, 1 +// CHECK: store volatile i32 %add5, ptr @vt +}