-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[clang][bytecode] Diagnose volatile writes #160350
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) ChangesFull diff: https://github.com/llvm/llvm-project/pull/160350.diff 7 Files Affected:
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index b4da99957ee88..a81107289d91d 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -4452,6 +4452,9 @@ bool Compiler<Emitter>::visitAssignment(const Expr *LHS, const Expr *RHS,
if (!this->visit(LHS))
return false;
+ if (LHS->getType().isVolatileQualified())
+ return this->emitInvalidStore(LHS->getType().getTypePtr(), E);
+
// We don't support assignments in C.
if (!Ctx.getLangOpts().CPlusPlus && !this->emitInvalid(E))
return false;
@@ -4560,13 +4563,14 @@ bool Compiler<Emitter>::emitConst(const APSInt &Value, const Expr *E) {
template <class Emitter>
unsigned Compiler<Emitter>::allocateLocalPrimitive(
- DeclTy &&Src, PrimType Ty, bool IsConst, const ValueDecl *ExtendingDecl,
- ScopeKind SC, bool IsConstexprUnknown) {
+ DeclTy &&Src, PrimType Ty, bool IsConst, bool IsVolatile,
+ const ValueDecl *ExtendingDecl, ScopeKind SC, bool IsConstexprUnknown) {
// FIXME: There are cases where Src.is<Expr*>() is wrong, e.g.
// (int){12} in C. Consider using Expr::isTemporaryObject() instead
// or isa<MaterializeTemporaryExpr>().
Descriptor *D = P.createDescriptor(Src, Ty, nullptr, Descriptor::InlineDescMD,
- IsConst, isa<const Expr *>(Src));
+ IsConst, isa<const Expr *>(Src),
+ /*IsMutable=*/false, IsVolatile);
D->IsConstexprUnknown = IsConstexprUnknown;
Scope::Local Local = this->createLocal(D);
if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>()))
@@ -4874,7 +4878,8 @@ Compiler<Emitter>::visitVarDecl(const VarDecl *VD, const Expr *Init,
if (VarT) {
unsigned Offset = this->allocateLocalPrimitive(
- VD, *VarT, VD->getType().isConstQualified(), nullptr, ScopeKind::Block,
+ VD, *VarT, VD->getType().isConstQualified(),
+ VD->getType().isVolatileQualified(), nullptr, ScopeKind::Block,
IsConstexprUnknown);
if (Init) {
// If this is a toplevel declaration, create a scope for the
diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h
index 09599b3547888..5c46f75af4da3 100644
--- a/clang/lib/AST/ByteCode/Compiler.h
+++ b/clang/lib/AST/ByteCode/Compiler.h
@@ -327,6 +327,7 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
/// Creates a local primitive value.
unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsConst,
+ bool IsVolatile = false,
const ValueDecl *ExtendingDecl = nullptr,
ScopeKind SC = ScopeKind::Block,
bool IsConstexprUnknown = false);
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 0f322f6ed42ac..6a737c1c5e550 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -889,6 +889,8 @@ bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
return false;
if (!CheckConst(S, OpPC, Ptr))
return false;
+ if (!CheckVolatile(S, OpPC, Ptr, AK_Assign))
+ return false;
if (!S.inConstantContext() && isConstexprUnknown(Ptr))
return false;
return true;
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index b3b4b998439cc..d98ae8853147e 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -3344,6 +3344,19 @@ inline bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind,
return false;
}
+inline bool InvalidStore(InterpState &S, CodePtr OpPC, const Type *T) {
+
+ if (S.getLangOpts().CPlusPlus) {
+ QualType VolatileType = QualType(T, 0).withVolatile();
+ S.FFDiag(S.Current->getSource(OpPC),
+ diag::note_constexpr_access_volatile_type)
+ << AK_Assign << VolatileType;
+ } else {
+ S.FFDiag(S.Current->getSource(OpPC));
+ }
+ return false;
+}
+
inline bool InvalidDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR,
bool InitializerFailed) {
assert(DR);
diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td
index 7af2df5318106..532c4448e6f40 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -797,6 +797,7 @@ def SideEffect : Opcode {}
def InvalidCast : Opcode {
let Args = [ArgCastKind, ArgBool];
}
+def InvalidStore : Opcode { let Args = [ArgTypePtr]; }
def CheckPseudoDtor : Opcode {}
def InvalidDeclRef : Opcode {
diff --git a/clang/test/AST/ByteCode/cxx23.cpp b/clang/test/AST/ByteCode/cxx23.cpp
index 72c751d627a44..0cc6e3b25fcef 100644
--- a/clang/test/AST/ByteCode/cxx23.cpp
+++ b/clang/test/AST/ByteCode/cxx23.cpp
@@ -393,6 +393,48 @@ namespace UnionMemberCallDiags {
static_assert(g()); // all-error {{not an integral constant expression}} \
// all-note {{in call to}}
}
+#endif
+
+namespace VolatileWrites {
+ constexpr void test1() {// all20-error {{never produces a constant expression}}
+ int k;
+ volatile int &m = k;
+ m = 10; // all20-note {{assignment to volatile-qualified type 'volatile int'}}
+ }
+
+ constexpr void test2() { // all20-error {{never produces a constant expression}}
+ volatile int k = 12;
+
+ k = 13; // all20-note {{assignment to volatile-qualified type 'volatile int'}}
+ }
+
+ constexpr void test3() { // all20-error {{never produces a constant expression}}
+ volatile int k = 12; // all20-note {{volatile object declared here}}
+
+ *((int *)&k) = 13; // all20-note {{assignment to volatile object 'k' is not allowed in a constant expression}}
+ }
+
+
+ constexpr void test4() { // all20-error {{never produces a constant expression}}
+ int k = 12; // all20-note {{volatile object declared here}}
+
+ *((volatile int *)&k) = 13; // all20-note {{assignment to volatile-qualified type 'volatile int' is not allowed in a constant expression}}
+ }
+
+
+#if __cplusplus >= 202302L
+ struct S {
+ volatile int k;
+ };
+ constexpr int test5() {
+ S s;
+ s.k = 12; // all-note {{assignment to volatile-qualified type 'volatile int' is not}}
+
+ return 0;
+ }
+ static_assert(test5() == 0); // all-error{{not an integral constant expression}} \
+ // all-note {{in call to}}
#endif
+}
diff --git a/clang/test/AST/ByteCode/invalid.cpp b/clang/test/AST/ByteCode/invalid.cpp
index affb40eada870..00db27419e36b 100644
--- a/clang/test/AST/ByteCode/invalid.cpp
+++ b/clang/test/AST/ByteCode/invalid.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -fcxx-exceptions -std=c++20 -fexperimental-new-constant-interpreter -verify=expected,both %s
-// RUN: %clang_cc1 -fcxx-exceptions -std=c++20 -verify=ref,both %s
+// RUN: %clang_cc1 -fcxx-exceptions -std=c++20 -verify=ref,both %s
namespace Throw {
|
9b7c1aa to
1cd424c
Compare
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
ed58b80 to
c950c3d
Compare
c950c3d to
4eaebc3
Compare
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/141/builds/11859 Here is the relevant piece of the build log for the reference |
No description provided.