diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 5d45f4e2ed7b..ecabfd298474 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -12497,16 +12497,20 @@ class Sema final { class CXXFragmentScopeRAII { Sema &S; bool PreviouslyInFragment; + SmallVector OriginalDetachedCaptures; public: CXXFragmentScopeRAII(Sema &S) - : S(S), PreviouslyInFragment(S.FragmentScope) { + : S(S), PreviouslyInFragment(S.FragmentScope), + OriginalDetachedCaptures() { S.FragmentScope = true; + OriginalDetachedCaptures.swap(S.DetachedCaptures); } ~CXXFragmentScopeRAII() { S.FragmentScope = PreviouslyInFragment; assert(S.DetachedCaptures.empty() && "captures left unattached"); + OriginalDetachedCaptures.swap(S.DetachedCaptures); } }; diff --git a/clang/test/CXX/meta/nested_fragment_with_captures.cpp b/clang/test/CXX/meta/nested_fragment_with_captures.cpp new file mode 100644 index 000000000000..ad5317c4d7be --- /dev/null +++ b/clang/test/CXX/meta/nested_fragment_with_captures.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -freflection -std=c++2a %s + +#define assert(E) if (!(E)) __builtin_abort(); + +namespace meta { + using info = decltype(^void); +} + +struct Member { + const char* name; + meta::info type; +}; + +constexpr Member members[]{ + Member{"a", ^int}, + Member{"b", ^int} +}; + +consteval void generate_struct(const char* name) { + -> fragment namespace { + struct [# %{name} #] { + consteval { + for (auto member : %{members}) { + -> fragment struct { + typename [: %{member.type} :] [# %{member.name} #]; + }; + } + } + }; + }; +} + +consteval { + generate_struct("S"); +} + +int main() { + S s{1, 2}; + assert(s.a == 1); + assert(s.b == 2); + return 0; +} \ No newline at end of file