[clang] Add check in SemaChecking for multiple unsequenced volatile accesses (PR #180955)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Feb 11 06:51:06 PST 2026
https://github.com/Seraphimt created https://github.com/llvm/llvm-project/pull/180955
According to standards volatile accesses is sideeffects and multiple unsequenced volatile accesses same variable is UB.
>From 8411b532a145c3b5a39a3785a1ab6c3dbaf446e8 Mon Sep 17 00:00:00 2001
From: Seraphimt <svet58585 at mail.ru>
Date: Wed, 11 Feb 2026 12:18:06 +0300
Subject: [PATCH 1/2] Add warning to Sema for multi unseq use volatile.
---
clang/lib/Sema/SemaChecking.cpp | 42 ++++++++++++++++++-------
clang/test/SemaCXX/warn-unsequenced.cpp | 26 +++++++++++++++
2 files changed, 56 insertions(+), 12 deletions(-)
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 89171246d0bcb..b9d1ae9240923 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -14015,7 +14015,7 @@ class SequenceChecker : public ConstEvaluatedExprVisitor<SequenceChecker> {
};
/// An object for which we can track unsequenced uses.
- using Object = const NamedDecl *;
+ using Object = const ValueDecl *;
/// Different flavors of object usage which we track. We only track the
/// least-sequenced usage of each kind.
@@ -14034,6 +14034,12 @@ class SequenceChecker : public ConstEvaluatedExprVisitor<SequenceChecker> {
UK_Count = UK_ModAsSideEffect + 1
};
+ enum WarningKind {
+ WK_UseAndMod,
+ WK_ModAndMod,
+ WK_Volatile_UseAndUse
+ };
+
/// Bundle together a sequencing region and the expression corresponding
/// to a specific usage. One Usage is stored for each usage kind in UsageInfo.
struct Usage {
@@ -14179,7 +14185,7 @@ class SequenceChecker : public ConstEvaluatedExprVisitor<SequenceChecker> {
/// \p IsModMod is true when we are checking for a mod-mod unsequenced
/// usage and false we are checking for a mod-use unsequenced usage.
void checkUsage(Object O, UsageInfo &UI, const Expr *UsageExpr,
- UsageKind OtherKind, bool IsModMod) {
+ UsageKind OtherKind, WarningKind WarnKind) {
if (UI.Diagnosed)
return;
@@ -14192,11 +14198,22 @@ class SequenceChecker : public ConstEvaluatedExprVisitor<SequenceChecker> {
if (OtherKind == UK_Use)
std::swap(Mod, ModOrUse);
+ unsigned DiagID = 0;
+ switch (WarnKind) {
+ case WK_UseAndMod:
+ DiagID = diag::warn_unsequenced_mod_use;
+ break;
+ case WK_ModAndMod:
+ DiagID = diag::warn_unsequenced_mod_mod;
+ break;
+ case WK_Volatile_UseAndUse:
+ DiagID = diag::warn_unsequenced_use_use_volatile;
+ break;
+ }
+
SemaRef.DiagRuntimeBehavior(
Mod->getExprLoc(), {Mod, ModOrUse},
- SemaRef.PDiag(IsModMod ? diag::warn_unsequenced_mod_mod
- : diag::warn_unsequenced_mod_use)
- << O << SourceRange(ModOrUse->getExprLoc()));
+ SemaRef.PDiag(DiagID)<< O << SourceRange(ModOrUse->getExprLoc()));
UI.Diagnosed = true;
}
@@ -14229,27 +14246,28 @@ class SequenceChecker : public ConstEvaluatedExprVisitor<SequenceChecker> {
void notePreUse(Object O, const Expr *UseExpr) {
UsageInfo &UI = UsageMap[O];
// Uses conflict with other modifications.
- checkUsage(O, UI, UseExpr, /*OtherKind=*/UK_ModAsValue, /*IsModMod=*/false);
+ checkUsage(O, UI, UseExpr, /*OtherKind=*/UK_ModAsValue, WK_UseAndMod);
+ // Volatile uses conflict with other uses.
+ if (O->getType().isVolatileQualified())
+ checkUsage(O, UI, UseExpr, /*OtherKind=*/UK_Use, WK_Volatile_UseAndUse);
}
void notePostUse(Object O, const Expr *UseExpr) {
UsageInfo &UI = UsageMap[O];
- checkUsage(O, UI, UseExpr, /*OtherKind=*/UK_ModAsSideEffect,
- /*IsModMod=*/false);
+ checkUsage(O, UI, UseExpr, /*OtherKind=*/UK_ModAsSideEffect, WK_UseAndMod);
addUsage(O, UI, UseExpr, /*UsageKind=*/UK_Use);
}
void notePreMod(Object O, const Expr *ModExpr) {
UsageInfo &UI = UsageMap[O];
// Modifications conflict with other modifications and with uses.
- checkUsage(O, UI, ModExpr, /*OtherKind=*/UK_ModAsValue, /*IsModMod=*/true);
- checkUsage(O, UI, ModExpr, /*OtherKind=*/UK_Use, /*IsModMod=*/false);
+ checkUsage(O, UI, ModExpr, /*OtherKind=*/UK_ModAsValue, WK_ModAndMod);
+ checkUsage(O, UI, ModExpr, /*OtherKind=*/UK_Use, WK_UseAndMod);
}
void notePostMod(Object O, const Expr *ModExpr, UsageKind UK) {
UsageInfo &UI = UsageMap[O];
- checkUsage(O, UI, ModExpr, /*OtherKind=*/UK_ModAsSideEffect,
- /*IsModMod=*/true);
+ checkUsage(O, UI, ModExpr, /*OtherKind=*/UK_ModAsSideEffect, WK_ModAndMod);
addUsage(O, UI, ModExpr, /*UsageKind=*/UK);
}
diff --git a/clang/test/SemaCXX/warn-unsequenced.cpp b/clang/test/SemaCXX/warn-unsequenced.cpp
index 50dde8f3a5789..6019eb3929304 100644
--- a/clang/test/SemaCXX/warn-unsequenced.cpp
+++ b/clang/test/SemaCXX/warn-unsequenced.cpp
@@ -815,3 +815,29 @@ void test_var() {
}
} // namespace templates
+
+namespace muliple_read_volatile {
+ volatile int v1;
+
+ void PositiveTest(){
+ int x = 0;
+ int y = 0;
+ x = v1 + v1; // cxx11-warning {{unsequenced accesses to volatile qualified 'v1'}}
+ // cxx17-warning at -1 {{unsequenced accesses to volatile qualified 'v1'}}
+ v1 = v1 * v1; // cxx11-warning {{unsequenced accesses to volatile qualified 'v1'}}
+ // cxx17-warning at -1 {{unsequenced accesses to volatile qualified 'v1'}}
+ x = v1 + (y++, v1); // cxx11-warning {{unsequenced accesses to volatile qualified 'v1'}}
+ // cxx17-warning at -1 {{unsequenced accesses to volatile qualified 'v1'}}
+ x = v1 + y || y; // cxx11-warning {{unsequenced accesses to volatile qualified 'v1'}}
+ // cxx17-warning at -1 {{unsequenced accesses to volatile qualified 'v1'}}
+ }
+
+ void NegativeTest(){
+ int x = 0;
+ int y = 0;
+ x = v1 + y; // no-warning
+ v1 = v1 * y; // no-warning
+ x = (v1, v1); // no-warning
+ x = v1 || v1; // no-warning
+ }
+} // namespace volatiles
\ No newline at end of file
>From 4889b198e22806080f7b602b29526858135f4f02 Mon Sep 17 00:00:00 2001
From: Seraphimt <svet58585 at mail.ru>
Date: Wed, 11 Feb 2026 15:58:17 +0300
Subject: [PATCH 2/2] Minor fix.
---
clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 ++
clang/test/SemaCXX/warn-unsequenced.cpp | 4 ++--
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f12677ac11600..defd168b2c629 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2581,6 +2581,8 @@ def warn_unsequenced_mod_mod : Warning<
"multiple unsequenced modifications to %0">, InGroup<Unsequenced>;
def warn_unsequenced_mod_use : Warning<
"unsequenced modification and access to %0">, InGroup<Unsequenced>;
+def warn_unsequenced_use_use_volatile : Warning<
+ "unsequenced volatile accesses to %0">, InGroup<Unsequenced>;
def select_initialized_entity_kind : TextSubstitution<
"%select{copying variable|copying parameter|initializing template parameter|"
diff --git a/clang/test/SemaCXX/warn-unsequenced.cpp b/clang/test/SemaCXX/warn-unsequenced.cpp
index 6019eb3929304..3b4a8ec9380d0 100644
--- a/clang/test/SemaCXX/warn-unsequenced.cpp
+++ b/clang/test/SemaCXX/warn-unsequenced.cpp
@@ -828,7 +828,7 @@ namespace muliple_read_volatile {
// cxx17-warning at -1 {{unsequenced accesses to volatile qualified 'v1'}}
x = v1 + (y++, v1); // cxx11-warning {{unsequenced accesses to volatile qualified 'v1'}}
// cxx17-warning at -1 {{unsequenced accesses to volatile qualified 'v1'}}
- x = v1 + y || y; // cxx11-warning {{unsequenced accesses to volatile qualified 'v1'}}
+ x = v1 + v1 || y; // cxx11-warning {{unsequenced accesses to volatile qualified 'v1'}}
// cxx17-warning at -1 {{unsequenced accesses to volatile qualified 'v1'}}
}
@@ -840,4 +840,4 @@ namespace muliple_read_volatile {
x = (v1, v1); // no-warning
x = v1 || v1; // no-warning
}
-} // namespace volatiles
\ No newline at end of file
+} // namespace muliple_read_volatile
\ No newline at end of file
More information about the cfe-commits
mailing list