[clang] [clang][bytecode] Fix const-ness of local primitive temporary (PR #127405)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Sun Feb 16 10:55:13 PST 2025
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/127405
This used to cause certain std::range tests in libc++ to be diagnosed as modifying a const-qualified field, because we set the IsConst flag to true unconditionally. Check the type instead.
>From 81d9f2d55463f1cb6980a9aa508ba8f3633c34d2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Sun, 16 Feb 2025 18:09:01 +0100
Subject: [PATCH] [clang][bytecode] Fix const-ness of local primitive temporary
This used to cause certain std::range tests in libc++ to be diagnosed
as modifying a const-qualified field, because we set the IsConst flag
to true unconditionally. Check the type instead.
---
clang/lib/AST/ByteCode/Compiler.cpp | 3 +-
.../ByteCode/non-const-local-temporary.cpp | 53 +++++++++++++++++++
2 files changed, 55 insertions(+), 1 deletion(-)
create mode 100644 clang/test/AST/ByteCode/non-const-local-temporary.cpp
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index cf39209819ade..c8ace39d56fd0 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -2707,7 +2707,8 @@ bool Compiler<Emitter>::VisitMaterializeTemporaryExpr(
// For everyhing else, use local variables.
if (SubExprT) {
- unsigned LocalIndex = allocateLocalPrimitive(E, *SubExprT, /*IsConst=*/true,
+ bool IsConst = SubExpr->getType().isConstQualified();
+ unsigned LocalIndex = allocateLocalPrimitive(E, *SubExprT, IsConst,
/*IsExtended=*/true);
if (!this->visit(SubExpr))
return false;
diff --git a/clang/test/AST/ByteCode/non-const-local-temporary.cpp b/clang/test/AST/ByteCode/non-const-local-temporary.cpp
new file mode 100644
index 0000000000000..11d4b5383dbf5
--- /dev/null
+++ b/clang/test/AST/ByteCode/non-const-local-temporary.cpp
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -std=c++2c -fexperimental-new-constant-interpreter -verify=expected,both %s
+// RUN: %clang_cc1 -std=c++2c -verify=ref,both %s
+
+// both-no-diagnostics
+
+namespace std {
+template <class, int __v> struct integral_constant {
+ static const int value = __v;
+};
+using size_t = decltype(sizeof(int));
+template <class _Tp, class>
+concept __weakly_equality_comparable_with = requires(_Tp __t) { __t; };
+template <size_t, class> struct tuple_element;
+template <class> struct tuple_size;
+template <class _Ip>
+concept input_or_output_iterator = requires(_Ip __i) { __i; };
+template <class _Sp, class _Ip>
+concept sentinel_for = __weakly_equality_comparable_with<_Sp, _Ip>;
+namespace ranges {
+enum subrange_kind { unsized };
+template <input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent,
+ subrange_kind = unsized>
+struct subrange {
+ _Iter __begin_;
+ _Sent __end_;
+ constexpr _Sent end() { return __end_; }
+};
+template <int, class _Iter, class _Sent, subrange_kind _Kind>
+constexpr auto get(subrange<_Iter, _Sent, _Kind> __subrange) {
+ return __subrange.end();
+}
+} // namespace ranges
+template <class _Ip, class _Sp, ranges::subrange_kind _Kp>
+struct tuple_size<ranges::subrange<_Ip, _Sp, _Kp>>
+ : integral_constant<size_t, 2> {};
+template <class _Ip, class _Sp, ranges::subrange_kind _Kp>
+struct tuple_element<0, ranges::subrange<_Ip, _Sp, _Kp>> {
+ using type = _Ip;
+};
+template <class _Ip, class _Sp, ranges::subrange_kind _Kp>
+struct tuple_element<1, ranges::subrange<_Ip, _Sp, _Kp>> {
+ using type = _Sp;
+};
+} // namespace std
+constexpr bool test() {
+ int a[1];
+ auto r = std::ranges::subrange(a, a);
+ auto [first, last] = r;
+ last = a;
+ return true;
+}
+static_assert(test());
+
More information about the cfe-commits
mailing list