Skip to content

Commit 1b6cbaa

Browse files
authored
[clang][bytecode] Refine diagnostics for volatile reads (#136857)
Differentiate between a volarile read via a lvalue-to-rvalue cast of a volatile qualified subexpression and a read from a pointer with a volatile base object.
1 parent 83c309b commit 1b6cbaa

File tree

5 files changed

+58
-9
lines changed

5 files changed

+58
-9
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,9 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
210210

211211
switch (CE->getCastKind()) {
212212
case CK_LValueToRValue: {
213+
if (SubExpr->getType().isVolatileQualified())
214+
returnthis->emitInvalidCast(CastKind::Volatile, /*Fatal=*/true, CE);
215+
213216
std::optional<PrimType> SubExprT = classify(SubExpr->getType());
214217
// Prepare storage for the result.
215218
if (!Initializing && !SubExprT) {

clang/lib/AST/ByteCode/Interp.cpp

+24-5
Original file line numberDiff line numberDiff line change
@@ -641,11 +641,30 @@ static bool CheckVolatile(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
641641
if (!PtrType.isVolatileQualified())
642642
returntrue;
643643

644-
const SourceInfo &Loc = S.Current->getSource(OpPC);
645-
if (S.getLangOpts().CPlusPlus)
646-
S.FFDiag(Loc, diag::note_constexpr_access_volatile_type) << AK << PtrType;
647-
else
648-
S.FFDiag(Loc);
644+
if (!S.getLangOpts().CPlusPlus)
645+
returnInvalid(S, OpPC);
646+
647+
const NamedDecl *ND = nullptr;
648+
int DiagKind;
649+
SourceLocation Loc;
650+
if (constauto *F = Ptr.getField()) {
651+
DiagKind = 2;
652+
Loc = F->getLocation();
653+
ND = F;
654+
} elseif (auto *VD = Ptr.getFieldDesc()->asValueDecl()) {
655+
DiagKind = 1;
656+
Loc = VD->getLocation();
657+
ND = VD;
658+
} else {
659+
DiagKind = 0;
660+
if (constauto *E = Ptr.getFieldDesc()->asExpr())
661+
Loc = E->getExprLoc();
662+
}
663+
664+
S.FFDiag(S.Current->getLocation(OpPC),
665+
diag::note_constexpr_access_volatile_obj, 1)
666+
<< AK << DiagKind << ND;
667+
S.Note(Loc, diag::note_constexpr_volatile_here) << DiagKind;
649668
returnfalse;
650669
}
651670

clang/lib/AST/ByteCode/Interp.h

+11-1
Original file line numberDiff line numberDiff line change
@@ -2885,12 +2885,22 @@ inline bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind,
28852885
bool Fatal) {
28862886
const SourceLocation &Loc = S.Current->getLocation(OpPC);
28872887

2888-
// FIXME: Support diagnosing other invalid cast kinds.
28892888
if (Kind == CastKind::Reinterpret) {
28902889
S.CCEDiag(Loc, diag::note_constexpr_invalid_cast)
28912890
<< static_cast<unsigned>(Kind) << S.Current->getRange(OpPC);
28922891
return !Fatal;
2892+
} elseif (Kind == CastKind::Volatile) {
2893+
// FIXME: Technically not a cast.
2894+
constauto *E = cast<CastExpr>(S.Current->getExpr(OpPC));
2895+
if (S.getLangOpts().CPlusPlus)
2896+
S.FFDiag(E, diag::note_constexpr_access_volatile_type)
2897+
<< AK_Read << E->getSubExpr()->getType();
2898+
else
2899+
S.FFDiag(E);
2900+
2901+
returnfalse;
28932902
}
2903+
28942904
returnfalse;
28952905
}
28962906

clang/lib/AST/ByteCode/PrimType.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,17 @@ inline constexpr bool isPtrType(PrimType T) {
5555

5656
enumclassCastKind : uint8_t {
5757
Reinterpret,
58-
Atomic,
58+
Volatile,
5959
};
60+
6061
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
6162
interp::CastKind CK) {
6263
switch (CK) {
6364
case interp::CastKind::Reinterpret:
6465
OS << "reinterpret_cast";
6566
break;
66-
case interp::CastKind::Atomic:
67-
OS << "atomic";
67+
case interp::CastKind::Volatile:
68+
OS << "volatile";
6869
break;
6970
}
7071
return OS;

clang/test/AST/ByteCode/literals.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -1357,6 +1357,22 @@ namespace VolatileReads {
13571357
constvolatileint b = 1;
13581358
static_assert(b, ""); // both-error {{not an integral constant expression}} \
13591359
// both-note {{read of volatile-qualified type 'const volatile int' is not allowed in a constant expression}}
1360+
1361+
1362+
constexprint a = 12;
1363+
constexprvolatileint c = (volatileint&)a; // both-error {{must be initialized by a constant expression}} \
1364+
// both-note {{read of volatile-qualified type 'volatile int'}}
1365+
1366+
volatileconstexprint n1 = 0; // both-note {{here}}
1367+
volatileconstint n2 = 0; // both-note {{here}}
1368+
constexprint m1 = n1; // both-error {{constant expression}} \
1369+
// both-note {{read of volatile-qualified type 'const volatile int'}}
1370+
constexprint m2 = n2; // both-error {{constant expression}} \
1371+
// both-note {{read of volatile-qualified type 'const volatile int'}}
1372+
constexprint m1b = const_cast<constint&>(n1); // both-error {{constant expression}} \
1373+
// both-note {{read of volatile object 'n1'}}
1374+
constexprint m2b = const_cast<constint&>(n2); // both-error {{constant expression}} \
1375+
// both-note {{read of volatile object 'n2'}}
13601376
}
13611377
#if __cplusplus >= 201703L
13621378
namespace {

0 commit comments

Comments
 (0)
close