Skip to content

Commit

Permalink
[Clang] Fix dependent expression handling for assumptions (llvm#115646)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
zyn0217 authored Nov 12, 2024
1 parent 31dc2b9 commit de2fad3
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 2 deletions.
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,8 @@ Bug Fixes to C++ Support
an implicitly instantiated class template specialization. (#GH51051)
- Fixed an assertion failure caused by invalid enum forward declarations. (#GH112208)
- Name independent data members were not correctly initialized from default member initializers. (#GH114069)
- Fixed expression transformation for ``[[assume(...)]]``, allowing using pack indexing expressions within the
assumption if they also occur inside of a dependent lambda. (#GH114787)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
11 changes: 9 additions & 2 deletions clang/lib/Sema/SemaTemplateInstantiate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2196,11 +2196,18 @@ TemplateInstantiator::TransformCXXAssumeAttr(const CXXAssumeAttr *AA) {
if (!Res.isUsable())
return AA;

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

if (!(Res.get()->getDependence() & ExprDependence::TypeValueInstantiation)) {
Res = getSema().BuildCXXAssumeExpr(Res.get(), AA->getAttrName(),
AA->getRange());
if (!Res.isUsable())
return AA;
}

return CXXAssumeAttr::CreateImplicit(getSema().Context, Res.get(),
AA->getRange());
}
Expand Down
28 changes: 28 additions & 0 deletions clang/test/SemaCXX/cxx23-assume.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// RUN: %clang_cc1 -std=c++20 -pedantic -x c++ %s -verify=ext,expected
// RUN: %clang_cc1 -std=c++23 -x c++ %s -verify -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 -std=c++20 -pedantic -x c++ %s -verify=ext,expected -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 -std=c++26 -x c++ %s -verify
// RUN: %clang_cc1 -std=c++26 -x c++ %s -verify -fexperimental-new-constant-interpreter

struct A{};
struct B{ explicit operator bool() { return true; } };
Expand Down Expand Up @@ -167,3 +169,29 @@ int foo () {
__attribute__((assume (a < b)));
}
}

namespace GH114787 {

// FIXME: Correct the C++26 value
#if __cplusplus >= 202400L

constexpr int test(auto... xs) {
// FIXME: Investigate why addresses of PackIndexingExprs are printed for the next
// 'in call to' note.
return [&]<int I>() { // expected-note {{in call to}}
[[assume(
xs...[I] == 2
)]];
[[assume(
xs...[I + 1] == 0 // expected-note {{assumption evaluated to false}}
)]];
return xs...[I];
}.template operator()<1>();
}

static_assert(test(1, 2, 3, 5, 6) == 2); // expected-error {{not an integral constant expression}} \
// expected-note {{in call to}}

#endif

} // namespace GH114787

0 comments on commit de2fad3

Please sign in to comment.