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?= <tbae...@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}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits