[clang] [clang][bytecode] Properly diagnose non-const reads (PR #106514)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 29 02:57:55 PDT 2024
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/106514
>From a8eaf58bcae529a3629dbd1b84df58e9557dde5d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Thu, 29 Aug 2024 10:21:54 +0200
Subject: [PATCH] [clang][bytecode] Properly diagnose non-const reads
If the global variable is constant (but not constexpr), we need to
diagnose, but keep evaluating.
---
clang/lib/AST/ByteCode/Interp.cpp | 62 ++++++++++++++--------
clang/test/AST/ByteCode/cxx11-pedantic.cpp | 13 +++++
2 files changed, 52 insertions(+), 23 deletions(-)
create mode 100644 clang/test/AST/ByteCode/cxx11-pedantic.cpp
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 09d3f4525138ed..0cd106b74d1504 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -323,36 +323,52 @@ bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {
assert(Desc);
- auto IsConstType = [&S](const VarDecl *VD) -> bool {
- QualType T = VD->getType();
-
- if (T.isConstant(S.getASTContext()))
- return true;
-
- if (S.getLangOpts().CPlusPlus && !S.getLangOpts().CPlusPlus11)
- return (T->isSignedIntegerOrEnumerationType() ||
- T->isUnsignedIntegerOrEnumerationType()) &&
- T.isConstQualified();
+ const auto *D = Desc->asVarDecl();
+ if (!D || !D->hasGlobalStorage())
+ return true;
- if (T.isConstQualified())
- return true;
+ if (D == S.EvaluatingDecl)
+ return true;
- if (const auto *RT = T->getAs<ReferenceType>())
- return RT->getPointeeType().isConstQualified();
+ if (D->isConstexpr())
+ return true;
- if (const auto *PT = T->getAs<PointerType>())
- return PT->getPointeeType().isConstQualified();
+ QualType T = D->getType();
+ bool IsConstant = T.isConstant(S.getASTContext());
+ if (T->isIntegralOrEnumerationType()) {
+ if (!IsConstant) {
+ diagnoseNonConstVariable(S, OpPC, D);
+ return false;
+ }
+ return true;
+ }
- return false;
- };
+ if (IsConstant) {
+ if (S.getLangOpts().CPlusPlus) {
+ S.CCEDiag(S.Current->getLocation(OpPC),
+ S.getLangOpts().CPlusPlus11
+ ? diag::note_constexpr_ltor_non_constexpr
+ : diag::note_constexpr_ltor_non_integral,
+ 1)
+ << D << T;
+ S.Note(D->getLocation(), diag::note_declared_at);
+ } else {
+ S.CCEDiag(S.Current->getLocation(OpPC));
+ }
+ return true;
+ }
- if (const auto *D = Desc->asVarDecl();
- D && D->hasGlobalStorage() && D != S.EvaluatingDecl && !IsConstType(D)) {
- diagnoseNonConstVariable(S, OpPC, D);
- return false;
+ if (T->isPointerOrReferenceType()) {
+ if (!T->getPointeeType().isConstant(S.getASTContext()) ||
+ !S.getLangOpts().CPlusPlus11) {
+ diagnoseNonConstVariable(S, OpPC, D);
+ return false;
+ }
+ return true;
}
- return true;
+ diagnoseNonConstVariable(S, OpPC, D);
+ return false;
}
static bool CheckConstant(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
diff --git a/clang/test/AST/ByteCode/cxx11-pedantic.cpp b/clang/test/AST/ByteCode/cxx11-pedantic.cpp
new file mode 100644
index 00000000000000..8779a2826c50db
--- /dev/null
+++ b/clang/test/AST/ByteCode/cxx11-pedantic.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=both,expected -std=c++11 -triple x86_64-linux -pedantic %s
+// RUN: %clang_cc1 -verify=both,ref -std=c++11 -triple x86_64-linux -pedantic %s
+
+struct T { int n; };
+const T t = { 42 }; // both-note 2{{declared here}}
+struct S {
+ int m : t.n; // both-warning {{width of bit-field 'm' (42 bits)}} \
+ // both-warning {{expression is not an integral constant expression}} \
+ // both-note {{read of non-constexpr variable 't' is not allowed}}
+};
+
+static_assert(t.n == 42, ""); // both-error {{expression is not an integral constant expression}} \
+ // both-note {{read of non-constexpr variable 't' is not allowed}}
More information about the cfe-commits
mailing list