Skip to content

Commit d223f36

Browse files
zyn0217Groverkss
authored andcommitted
[Clang] Fix dependent expression handling for assumptions (llvm#115646)
The function definition instantiation assumes any declarations used inside are already transformed before transforming the body, so we need to preserve the transformed expression of CXXAssumeAttr even if it is not a constant expression. Moreover, the full expression of the assumption should also entail a potential lambda capture transformation, hence the call to ActOnFinishFullExpr() after TransformExpr(). Fixes llvm#114787
1 parent 661aa52 commit d223f36

File tree

3 files changed

+39
-2
lines changed

3 files changed

+39
-2
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,8 @@ Bug Fixes to C++ Support
652652
an implicitly instantiated class template specialization. (#GH51051)
653653
- Fixed an assertion failure caused by invalid enum forward declarations. (#GH112208)
654654
- Name independent data members were not correctly initialized from default member initializers. (#GH114069)
655+
- Fixed expression transformation for ``[[assume(...)]]``, allowing using pack indexing expressions within the
656+
assumption if they also occur inside of a dependent lambda. (#GH114787)
655657

656658
Bug Fixes to AST Handling
657659
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2196,11 +2196,18 @@ TemplateInstantiator::TransformCXXAssumeAttr(const CXXAssumeAttr *AA) {
21962196
if (!Res.isUsable())
21972197
return AA;
21982198

2199-
Res = getSema().BuildCXXAssumeExpr(Res.get(), AA->getAttrName(),
2200-
AA->getRange());
2199+
Res = getSema().ActOnFinishFullExpr(Res.get(),
2200+
/*DiscardedValue=*/false);
22012201
if (!Res.isUsable())
22022202
return AA;
22032203

2204+
if (!(Res.get()->getDependence() & ExprDependence::TypeValueInstantiation)) {
2205+
Res = getSema().BuildCXXAssumeExpr(Res.get(), AA->getAttrName(),
2206+
AA->getRange());
2207+
if (!Res.isUsable())
2208+
return AA;
2209+
}
2210+
22042211
return CXXAssumeAttr::CreateImplicit(getSema().Context, Res.get(),
22052212
AA->getRange());
22062213
}

clang/test/SemaCXX/cxx23-assume.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// RUN: %clang_cc1 -std=c++20 -pedantic -x c++ %s -verify=ext,expected
33
// RUN: %clang_cc1 -std=c++23 -x c++ %s -verify -fexperimental-new-constant-interpreter
44
// RUN: %clang_cc1 -std=c++20 -pedantic -x c++ %s -verify=ext,expected -fexperimental-new-constant-interpreter
5+
// RUN: %clang_cc1 -std=c++26 -x c++ %s -verify
6+
// RUN: %clang_cc1 -std=c++26 -x c++ %s -verify -fexperimental-new-constant-interpreter
57

68
struct A{};
79
struct B{ explicit operator bool() { return true; } };
@@ -167,3 +169,29 @@ int foo () {
167169
__attribute__((assume (a < b)));
168170
}
169171
}
172+
173+
namespace GH114787 {
174+
175+
// FIXME: Correct the C++26 value
176+
#if __cplusplus >= 202400L
177+
178+
constexpr int test(auto... xs) {
179+
// FIXME: Investigate why addresses of PackIndexingExprs are printed for the next
180+
// 'in call to' note.
181+
return [&]<int I>() { // expected-note {{in call to}}
182+
[[assume(
183+
xs...[I] == 2
184+
)]];
185+
[[assume(
186+
xs...[I + 1] == 0 // expected-note {{assumption evaluated to false}}
187+
)]];
188+
return xs...[I];
189+
}.template operator()<1>();
190+
}
191+
192+
static_assert(test(1, 2, 3, 5, 6) == 2); // expected-error {{not an integral constant expression}} \
193+
// expected-note {{in call to}}
194+
195+
#endif
196+
197+
} // namespace GH114787

0 commit comments

Comments
 (0)