Author: Timm Baeder
Date: 2025-02-17T06:24:30+01:00
New Revision: c3cae9d6fccc96297e832a09f5230346ef4c42f3

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

LOG: [clang][bytecode] Fix const-ness of local primitive temporary (#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.

Added: 
    clang/test/AST/ByteCode/non-const-local-temporary.cpp

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

Removed: 
    


################################################################################
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());
+


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to