[clang] cb608cc - [clang][bytecode] Properly diagnose non-const reads (#106514)

via cfe-commits cfe-commits at lists.llvm.org
Thu Aug 29 04:45:02 PDT 2024


Author: Timm Baeder
Date: 2024-08-29T13:44:59+02:00
New Revision: cb608cc5f62baa01fe106a14ef41971337c2c030

URL: https://github.com/llvm/llvm-project/commit/cb608cc5f62baa01fe106a14ef41971337c2c030
DIFF: https://github.com/llvm/llvm-project/commit/cb608cc5f62baa01fe106a14ef41971337c2c030.diff

LOG: [clang][bytecode] Properly diagnose non-const reads (#106514)

If the global variable is constant (but not constexpr), we need to
diagnose, but keep evaluating.

Added: 
    clang/test/AST/ByteCode/cxx11-pedantic.cpp

Modified: 
    clang/lib/AST/ByteCode/Interp.cpp

Removed: 
    


################################################################################
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