[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