Skip to content

Commit 5b4d493

Browse files
tbaederrsivan-shani
authored andcommitted
[clang][bytecode] Fix const-ness of local primitive temporary (llvm#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.
1 parent f8d17de commit 5b4d493

File tree

2 files changed

+55
-1
lines changed

2 files changed

+55
-1
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2707,7 +2707,8 @@ bool Compiler<Emitter>::VisitMaterializeTemporaryExpr(
27072707

27082708
// For everyhing else, use local variables.
27092709
if (SubExprT) {
2710-
unsigned LocalIndex = allocateLocalPrimitive(E, *SubExprT, /*IsConst=*/true,
2710+
bool IsConst = SubExpr->getType().isConstQualified();
2711+
unsigned LocalIndex = allocateLocalPrimitive(E, *SubExprT, IsConst,
27112712
/*IsExtended=*/true);
27122713
if (!this->visit(SubExpr))
27132714
return false;
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// RUN: %clang_cc1 -std=c++2c -fexperimental-new-constant-interpreter -verify=expected,both %s
2+
// RUN: %clang_cc1 -std=c++2c -verify=ref,both %s
3+
4+
// both-no-diagnostics
5+
6+
namespace std {
7+
template <class, int __v> struct integral_constant {
8+
static const int value = __v;
9+
};
10+
using size_t = decltype(sizeof(int));
11+
template <class _Tp, class>
12+
concept __weakly_equality_comparable_with = requires(_Tp __t) { __t; };
13+
template <size_t, class> struct tuple_element;
14+
template <class> struct tuple_size;
15+
template <class _Ip>
16+
concept input_or_output_iterator = requires(_Ip __i) { __i; };
17+
template <class _Sp, class _Ip>
18+
concept sentinel_for = __weakly_equality_comparable_with<_Sp, _Ip>;
19+
namespace ranges {
20+
enum subrange_kind { unsized };
21+
template <input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent,
22+
subrange_kind = unsized>
23+
struct subrange {
24+
_Iter __begin_;
25+
_Sent __end_;
26+
constexpr _Sent end() { return __end_; }
27+
};
28+
template <int, class _Iter, class _Sent, subrange_kind _Kind>
29+
constexpr auto get(subrange<_Iter, _Sent, _Kind> __subrange) {
30+
return __subrange.end();
31+
}
32+
} // namespace ranges
33+
template <class _Ip, class _Sp, ranges::subrange_kind _Kp>
34+
struct tuple_size<ranges::subrange<_Ip, _Sp, _Kp>>
35+
: integral_constant<size_t, 2> {};
36+
template <class _Ip, class _Sp, ranges::subrange_kind _Kp>
37+
struct tuple_element<0, ranges::subrange<_Ip, _Sp, _Kp>> {
38+
using type = _Ip;
39+
};
40+
template <class _Ip, class _Sp, ranges::subrange_kind _Kp>
41+
struct tuple_element<1, ranges::subrange<_Ip, _Sp, _Kp>> {
42+
using type = _Sp;
43+
};
44+
} // namespace std
45+
constexpr bool test() {
46+
int a[1];
47+
auto r = std::ranges::subrange(a, a);
48+
auto [first, last] = r;
49+
last = a;
50+
return true;
51+
}
52+
static_assert(test());
53+

0 commit comments

Comments
 (0)