aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST
diff options
context:
space:
mode:
authorTimm Baeder <tbaeder@redhat.com>2025-04-23 18:52:35 +0200
committerGitHub <noreply@github.com>2025-04-23 18:52:35 +0200
commit1b6cbaa7b64f54b127d139d653468e213bae007e (patch)
tree056125775fc6227d03bee4e84841b1e7fda2871e /clang/lib/AST
parent83c309b90550aa768ff9aa11b70898ee2c56b71e (diff)
downloadllvm-1b6cbaa7b64f54b127d139d653468e213bae007e.zip
llvm-1b6cbaa7b64f54b127d139d653468e213bae007e.tar.gz
llvm-1b6cbaa7b64f54b127d139d653468e213bae007e.tar.bz2
[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.
Diffstat (limited to 'clang/lib/AST')
-rw-r--r--clang/lib/AST/ByteCode/Compiler.cpp3
-rw-r--r--clang/lib/AST/ByteCode/Interp.cpp29
-rw-r--r--clang/lib/AST/ByteCode/Interp.h12
-rw-r--r--clang/lib/AST/ByteCode/PrimType.h7
4 files changed, 42 insertions, 9 deletions
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 7cba0e8..65d87cd 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -210,6 +210,9 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
switch (CE->getCastKind()) {
case CK_LValueToRValue: {
+ if (SubExpr->getType().isVolatileQualified())
+ return this->emitInvalidCast(CastKind::Volatile, /*Fatal=*/true, CE);
+
std::optional<PrimType> SubExprT = classify(SubExpr->getType());
// Prepare storage for the result.
if (!Initializing && !SubExprT) {
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index b755a07..6f277a7 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -641,11 +641,30 @@ static bool CheckVolatile(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
if (!PtrType.isVolatileQualified())
return true;
- const SourceInfo &Loc = S.Current->getSource(OpPC);
- if (S.getLangOpts().CPlusPlus)
- S.FFDiag(Loc, diag::note_constexpr_access_volatile_type) << AK << PtrType;
- else
- S.FFDiag(Loc);
+ if (!S.getLangOpts().CPlusPlus)
+ return Invalid(S, OpPC);
+
+ const NamedDecl *ND = nullptr;
+ int DiagKind;
+ SourceLocation Loc;
+ if (const auto *F = Ptr.getField()) {
+ DiagKind = 2;
+ Loc = F->getLocation();
+ ND = F;
+ } else if (auto *VD = Ptr.getFieldDesc()->asValueDecl()) {
+ DiagKind = 1;
+ Loc = VD->getLocation();
+ ND = VD;
+ } else {
+ DiagKind = 0;
+ if (const auto *E = Ptr.getFieldDesc()->asExpr())
+ Loc = E->getExprLoc();
+ }
+
+ S.FFDiag(S.Current->getLocation(OpPC),
+ diag::note_constexpr_access_volatile_obj, 1)
+ << AK << DiagKind << ND;
+ S.Note(Loc, diag::note_constexpr_volatile_here) << DiagKind;
return false;
}
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index e5300b7..588e0502 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -2885,12 +2885,22 @@ inline bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind,
bool Fatal) {
const SourceLocation &Loc = S.Current->getLocation(OpPC);
- // FIXME: Support diagnosing other invalid cast kinds.
if (Kind == CastKind::Reinterpret) {
S.CCEDiag(Loc, diag::note_constexpr_invalid_cast)
<< static_cast<unsigned>(Kind) << S.Current->getRange(OpPC);
return !Fatal;
+ } else if (Kind == CastKind::Volatile) {
+ // FIXME: Technically not a cast.
+ const auto *E = cast<CastExpr>(S.Current->getExpr(OpPC));
+ if (S.getLangOpts().CPlusPlus)
+ S.FFDiag(E, diag::note_constexpr_access_volatile_type)
+ << AK_Read << E->getSubExpr()->getType();
+ else
+ S.FFDiag(E);
+
+ return false;
}
+
return false;
}
diff --git a/clang/lib/AST/ByteCode/PrimType.h b/clang/lib/AST/ByteCode/PrimType.h
index a3c0b0f..c6145d4 100644
--- a/clang/lib/AST/ByteCode/PrimType.h
+++ b/clang/lib/AST/ByteCode/PrimType.h
@@ -55,16 +55,17 @@ inline constexpr bool isPtrType(PrimType T) {
enum class CastKind : uint8_t {
Reinterpret,
- Atomic,
+ Volatile,
};
+
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
interp::CastKind CK) {
switch (CK) {
case interp::CastKind::Reinterpret:
OS << "reinterpret_cast";
break;
- case interp::CastKind::Atomic:
- OS << "atomic";
+ case interp::CastKind::Volatile:
+ OS << "volatile";
break;
}
return OS;