Magellan Linux

Annotation of /trunk/llvm/patches/clang-15.0.7-structured-bindings-r1.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3753 - (hide annotations) (download)
Fri Aug 4 08:32:09 2023 UTC (10 months ago) by niro
File size: 69760 byte(s)
-llcm/clang patches for 15.0.7
1 niro 3753 From 127bf44385424891eb04cff8e52d3f157fc2cb7c Mon Sep 17 00:00:00 2001
2     From: Corentin Jabot <corentinjabot@gmail.com>
3     Date: Wed, 30 Mar 2022 14:27:44 +0200
4     Subject: [PATCH] [Clang][C++20] Support capturing structured bindings in
5     lambdas
6    
7     This completes the implementation of P1091R3 and P1381R1.
8    
9     This patch allow the capture of structured bindings
10     both for C++20+ and C++17, with extension/compat warning.
11    
12     In addition, capturing an anonymous union member,
13     a bitfield, or a structured binding thereof now has a
14     better diagnostic.
15    
16     We only support structured bindings - as opposed to other kinds
17     of structured statements/blocks. We still emit an error for those.
18    
19     In addition, support for structured bindings capture is entirely disabled in
20     OpenMP mode as this needs more investigation - a specific diagnostic indicate the feature is not yet supported there.
21    
22     Note that the rest of P1091R3 (static/thread_local structured bindings) was already implemented.
23    
24     at the request of @shafik, i can confirm the correct behavior of lldb wit this change.
25    
26     Fixes https://github.com/llvm/llvm-project/issues/54300
27     Fixes https://github.com/llvm/llvm-project/issues/54300
28     Fixes https://github.com/llvm/llvm-project/issues/52720
29    
30     Reviewed By: aaron.ballman
31    
32     Differential Revision: https://reviews.llvm.org/D122768
33     ---
34     .../clang-tidy/modernize/LoopConvertUtils.cpp | 4 +-
35     clang/docs/ReleaseNotes.rst | 10 +
36     clang/include/clang/AST/Decl.h | 5 +
37     clang/include/clang/AST/DeclCXX.h | 5 +-
38     clang/include/clang/AST/LambdaCapture.h | 8 +-
39     clang/include/clang/AST/Stmt.h | 1 +
40     clang/include/clang/ASTMatchers/ASTMatchers.h | 2 +-
41     .../clang/Basic/DiagnosticSemaKinds.td | 10 +
42     clang/include/clang/Sema/ScopeInfo.h | 27 ++-
43     clang/include/clang/Sema/Sema.h | 12 +-
44     clang/lib/AST/ASTImporter.cpp | 2 +-
45     clang/lib/AST/Decl.cpp | 6 +
46     clang/lib/AST/DeclCXX.cpp | 4 +-
47     clang/lib/AST/ExprCXX.cpp | 6 +-
48     clang/lib/AST/ExprConstant.cpp | 2 +-
49     clang/lib/AST/StmtPrinter.cpp | 3 +-
50     clang/lib/Analysis/AnalysisDeclContext.cpp | 6 +-
51     clang/lib/CodeGen/CGDebugInfo.cpp | 2 +-
52     clang/lib/CodeGen/CGExpr.cpp | 7 +-
53     clang/lib/CodeGen/CGOpenMPRuntime.cpp | 6 +-
54     clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp | 15 +-
55     clang/lib/CodeGen/CodeGenFunction.h | 2 +-
56     clang/lib/Sema/SemaDecl.cpp | 2 +-
57     clang/lib/Sema/SemaExpr.cpp | 200 ++++++++++++------
58     clang/lib/Sema/SemaInit.cpp | 2 +-
59     clang/lib/Sema/SemaLambda.cpp | 31 ++-
60     clang/lib/Sema/SemaOpenMP.cpp | 4 +-
61     clang/lib/Sema/SemaStmt.cpp | 10 +-
62     clang/lib/Sema/TreeTransform.h | 9 +-
63     clang/lib/Serialization/ASTWriter.cpp | 2 +-
64     .../Checkers/DeadStoresChecker.cpp | 8 +-
65     .../WebKit/UncountedLambdaCapturesChecker.cpp | 4 +-
66     clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 2 +-
67     .../lib/StaticAnalyzer/Core/LoopUnrolling.cpp | 2 +-
68     clang/test/CodeGenCXX/cxx20-decomposition.cpp | 48 +++++
69     clang/test/SemaCXX/cxx1z-decomposition.cpp | 54 ++++-
70     clang/test/SemaCXX/cxx20-decomposition.cpp | 141 ++++++++++++
71     clang/test/SemaCXX/decomposition-blocks.cpp | 14 ++
72     clang/test/SemaCXX/decomposition-openmp.cpp | 13 ++
73     clang/tools/libclang/CIndex.cpp | 8 +-
74     clang/www/cxx_status.html | 2 +-
75     41 files changed, 539 insertions(+), 162 deletions(-)
76     create mode 100644 clang/test/CodeGenCXX/cxx20-decomposition.cpp
77     create mode 100644 clang/test/SemaCXX/cxx20-decomposition.cpp
78     create mode 100644 clang/test/SemaCXX/decomposition-blocks.cpp
79     create mode 100644 clang/test/SemaCXX/decomposition-openmp.cpp
80    
81     diff --git a/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp b/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp
82     index 5d4f3b82492499..fc3dfbdeac785f 100644
83     --- a/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp
84     +++ b/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp
85     @@ -785,8 +785,8 @@ bool ForLoopIndexUseVisitor::TraverseLambdaCapture(LambdaExpr *LE,
86     const LambdaCapture *C,
87     Expr *Init) {
88     if (C->capturesVariable()) {
89     - const VarDecl *VDecl = C->getCapturedVar();
90     - if (areSameVariable(IndexVar, cast<ValueDecl>(VDecl))) {
91     + const ValueDecl *VDecl = C->getCapturedVar();
92     + if (areSameVariable(IndexVar, VDecl)) {
93     // FIXME: if the index is captured, it will count as an usage and the
94     // alias (if any) won't work, because it is only used in case of having
95     // exactly one usage.
96     diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
97     index 7d90b08814baa3..878effe08294cb 100644
98     --- a/clang/docs/ReleaseNotes.rst
99     +++ b/clang/docs/ReleaseNotes.rst
100     @@ -108,6 +108,16 @@ C++ Language Changes in Clang
101     C++20 Feature Support
102     ^^^^^^^^^^^^^^^^^^^^^
103    
104     +- Support capturing structured bindings in lambdas
105     + (`P1091R3 <https://wg21.link/p1091r3>`_ and `P1381R1 <https://wg21.link/P1381R1>`).
106     + This fixes issues `GH52720 <https://github.com/llvm/llvm-project/issues/52720>`_,
107     + `GH54300 <https://github.com/llvm/llvm-project/issues/54300>`_,
108     + `GH54301 <https://github.com/llvm/llvm-project/issues/54301>`_,
109     + and `GH49430 <https://github.com/llvm/llvm-project/issues/49430>`_.
110     +
111     +
112     +
113     +
114     C++2b Feature Support
115     ^^^^^^^^^^^^^^^^^^^^^
116    
117     diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
118     index 6441cd339d917a..1b414b5c0c194a 100644
119     --- a/clang/include/clang/AST/Decl.h
120     +++ b/clang/include/clang/AST/Decl.h
121     @@ -689,6 +689,11 @@ class ValueDecl : public NamedDecl {
122     /// or declared with the weak or weak-ref attr.
123     bool isWeak() const;
124    
125     + /// Whether this variable is the implicit variable for a lambda init-capture.
126     + /// Only VarDecl can be init captures, but both VarDecl and BindingDecl
127     + /// can be captured.
128     + bool isInitCapture() const;
129     +
130     // Implement isa/cast/dyncast/etc.
131     static bool classof(const Decl *D) { return classofKind(D->getKind()); }
132     static bool classofKind(Kind K) { return K >= firstValue && K <= lastValue; }
133     diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
134     index 9e4fc3fc1254fd..c97301957cb609 100644
135     --- a/clang/include/clang/AST/DeclCXX.h
136     +++ b/clang/include/clang/AST/DeclCXX.h
137     @@ -1057,8 +1057,9 @@ class CXXRecordDecl : public RecordDecl {
138     ///
139     /// \note No entries will be added for init-captures, as they do not capture
140     /// variables.
141     - void getCaptureFields(llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures,
142     - FieldDecl *&ThisCapture) const;
143     + void
144     + getCaptureFields(llvm::DenseMap<const ValueDecl *, FieldDecl *> &Captures,
145     + FieldDecl *&ThisCapture) const;
146    
147     using capture_const_iterator = const LambdaCapture *;
148     using capture_const_range = llvm::iterator_range<capture_const_iterator>;
149     diff --git a/clang/include/clang/AST/LambdaCapture.h b/clang/include/clang/AST/LambdaCapture.h
150     index 7ad1e2361e4273..62e7716ed3699d 100644
151     --- a/clang/include/clang/AST/LambdaCapture.h
152     +++ b/clang/include/clang/AST/LambdaCapture.h
153     @@ -71,7 +71,7 @@ class LambdaCapture {
154     /// capture that is a pack expansion, or an invalid source
155     /// location to indicate that this is not a pack expansion.
156     LambdaCapture(SourceLocation Loc, bool Implicit, LambdaCaptureKind Kind,
157     - VarDecl *Var = nullptr,
158     + ValueDecl *Var = nullptr,
159     SourceLocation EllipsisLoc = SourceLocation());
160    
161     /// Determine the kind of capture.
162     @@ -86,7 +86,7 @@ class LambdaCapture {
163    
164     /// Determine whether this capture handles a variable.
165     bool capturesVariable() const {
166     - return isa_and_nonnull<VarDecl>(DeclAndBits.getPointer());
167     + return isa_and_nonnull<ValueDecl>(DeclAndBits.getPointer());
168     }
169    
170     /// Determine whether this captures a variable length array bound
171     @@ -101,9 +101,9 @@ class LambdaCapture {
172     ///
173     /// This operation is only valid if this capture is a variable capture
174     /// (other than a capture of \c this).
175     - VarDecl *getCapturedVar() const {
176     + ValueDecl *getCapturedVar() const {
177     assert(capturesVariable() && "No variable available for capture");
178     - return static_cast<VarDecl *>(DeclAndBits.getPointer());
179     + return static_cast<ValueDecl *>(DeclAndBits.getPointer());
180     }
181    
182     /// Determine whether this was an implicit capture (not
183     diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
184     index 49a66a1ea5b86a..52c0ca51ea8669 100644
185     --- a/clang/include/clang/AST/Stmt.h
186     +++ b/clang/include/clang/AST/Stmt.h
187     @@ -59,6 +59,7 @@ class RecordDecl;
188     class SourceManager;
189     class StringLiteral;
190     class Token;
191     +class ValueDecl;
192     class VarDecl;
193    
194     //===----------------------------------------------------------------------===//
195     diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
196     index 9f4d807c232dcd..5bcf1d3896e89b 100644
197     --- a/clang/include/clang/ASTMatchers/ASTMatchers.h
198     +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
199     @@ -4722,7 +4722,7 @@ AST_MATCHER_P(LambdaExpr, hasAnyCapture, internal::Matcher<LambdaCapture>,
200     /// In the matcher
201     /// lambdaExpr(hasAnyCapture(lambdaCapture(capturesVar(hasName("x")))),
202     /// capturesVar(hasName("x")) matches `x` and `x = 1`.
203     -AST_MATCHER_P(LambdaCapture, capturesVar, internal::Matcher<VarDecl>,
204     +AST_MATCHER_P(LambdaCapture, capturesVar, internal::Matcher<ValueDecl>,
205     InnerMatcher) {
206     auto *capturedVar = Node.getCapturedVar();
207     return capturedVar && InnerMatcher.matches(*capturedVar, Finder, Builder);
208     diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
209     index 6ff5b8de57fd02..550ad5ab73c642 100644
210     --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
211     +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
212     @@ -9013,6 +9013,16 @@ def ext_ms_anonymous_record : ExtWarn<
213     def err_reference_to_local_in_enclosing_context : Error<
214     "reference to local %select{variable|binding}1 %0 declared in enclosing "
215     "%select{%3|block literal|lambda expression|context}2">;
216     +def err_bitfield_capture_by_ref : Error<
217     + "cannot capture a bit-field by reference">;
218     +def err_capture_binding_openmp : Error<
219     + "capturing a structured binding is not yet supported in OpenMP">;
220     +def ext_capture_binding : ExtWarn<
221     + "captured structured bindings are a C++20 extension">, InGroup<CXX20>;
222     +def warn_cxx17_compat_capture_binding : Warning<
223     + "captured structured bindings are incompatible with "
224     + "C++ standards before C++20">,
225     + InGroup<CXXPre20Compat>, DefaultIgnore;
226    
227     def err_static_data_member_not_allowed_in_local_class : Error<
228     "static data member %0 not allowed in local %sub{select_tag_type_kind}2 %1">;
229     diff --git a/clang/include/clang/Sema/ScopeInfo.h b/clang/include/clang/Sema/ScopeInfo.h
230     index 18848c8d8a4564..c0dfcb89e86ffc 100644
231     --- a/clang/include/clang/Sema/ScopeInfo.h
232     +++ b/clang/include/clang/Sema/ScopeInfo.h
233     @@ -553,7 +553,7 @@ class Capture {
234     const VariableArrayType *CapturedVLA;
235    
236     /// Otherwise, the captured variable (if any).
237     - VarDecl *CapturedVar;
238     + ValueDecl *CapturedVar;
239     };
240    
241     /// The source location at which the first capture occurred.
242     @@ -589,12 +589,13 @@ class Capture {
243     unsigned Invalid : 1;
244    
245     public:
246     - Capture(VarDecl *Var, bool Block, bool ByRef, bool IsNested,
247     + Capture(ValueDecl *Var, bool Block, bool ByRef, bool IsNested,
248     SourceLocation Loc, SourceLocation EllipsisLoc, QualType CaptureType,
249     bool Invalid)
250     : CapturedVar(Var), Loc(Loc), EllipsisLoc(EllipsisLoc),
251     - CaptureType(CaptureType),
252     - Kind(Block ? Cap_Block : ByRef ? Cap_ByRef : Cap_ByCopy),
253     + CaptureType(CaptureType), Kind(Block ? Cap_Block
254     + : ByRef ? Cap_ByRef
255     + : Cap_ByCopy),
256     Nested(IsNested), CapturesThis(false), ODRUsed(false),
257     NonODRUsed(false), Invalid(Invalid) {}
258    
259     @@ -639,7 +640,7 @@ class Capture {
260     NonODRUsed = true;
261     }
262    
263     - VarDecl *getVariable() const {
264     + ValueDecl *getVariable() const {
265     assert(isVariableCapture());
266     return CapturedVar;
267     }
268     @@ -678,7 +679,7 @@ class CapturingScopeInfo : public FunctionScopeInfo {
269     : FunctionScopeInfo(Diag), ImpCaptureStyle(Style) {}
270    
271     /// CaptureMap - A map of captured variables to (index+1) into Captures.
272     - llvm::DenseMap<VarDecl*, unsigned> CaptureMap;
273     + llvm::DenseMap<ValueDecl *, unsigned> CaptureMap;
274    
275     /// CXXThisCaptureIndex - The (index+1) of the capture of 'this';
276     /// zero if 'this' is not captured.
277     @@ -695,7 +696,7 @@ class CapturingScopeInfo : public FunctionScopeInfo {
278     /// or null if unknown.
279     QualType ReturnType;
280    
281     - void addCapture(VarDecl *Var, bool isBlock, bool isByref, bool isNested,
282     + void addCapture(ValueDecl *Var, bool isBlock, bool isByref, bool isNested,
283     SourceLocation Loc, SourceLocation EllipsisLoc,
284     QualType CaptureType, bool Invalid) {
285     Captures.push_back(Capture(Var, isBlock, isByref, isNested, Loc,
286     @@ -722,23 +723,21 @@ class CapturingScopeInfo : public FunctionScopeInfo {
287     }
288    
289     /// Determine whether the given variable has been captured.
290     - bool isCaptured(VarDecl *Var) const {
291     - return CaptureMap.count(Var);
292     - }
293     + bool isCaptured(ValueDecl *Var) const { return CaptureMap.count(Var); }
294    
295     /// Determine whether the given variable-array type has been captured.
296     bool isVLATypeCaptured(const VariableArrayType *VAT) const;
297    
298     /// Retrieve the capture of the given variable, if it has been
299     /// captured already.
300     - Capture &getCapture(VarDecl *Var) {
301     + Capture &getCapture(ValueDecl *Var) {
302     assert(isCaptured(Var) && "Variable has not been captured");
303     return Captures[CaptureMap[Var] - 1];
304     }
305    
306     - const Capture &getCapture(VarDecl *Var) const {
307     - llvm::DenseMap<VarDecl*, unsigned>::const_iterator Known
308     - = CaptureMap.find(Var);
309     + const Capture &getCapture(ValueDecl *Var) const {
310     + llvm::DenseMap<ValueDecl *, unsigned>::const_iterator Known =
311     + CaptureMap.find(Var);
312     assert(Known != CaptureMap.end() && "Variable has not been captured");
313     return Captures[Known->second - 1];
314     }
315     diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
316     index ed50b9ef42ef49..706383e8943fcf 100644
317     --- a/clang/include/clang/Sema/Sema.h
318     +++ b/clang/include/clang/Sema/Sema.h
319     @@ -5325,23 +5325,23 @@ class Sema final {
320     ///
321     /// \returns true if an error occurred (i.e., the variable cannot be
322     /// captured) and false if the capture succeeded.
323     - bool tryCaptureVariable(VarDecl *Var, SourceLocation Loc, TryCaptureKind Kind,
324     - SourceLocation EllipsisLoc, bool BuildAndDiagnose,
325     - QualType &CaptureType,
326     + bool tryCaptureVariable(ValueDecl *Var, SourceLocation Loc,
327     + TryCaptureKind Kind, SourceLocation EllipsisLoc,
328     + bool BuildAndDiagnose, QualType &CaptureType,
329     QualType &DeclRefType,
330     const unsigned *const FunctionScopeIndexToStopAt);
331    
332     /// Try to capture the given variable.
333     - bool tryCaptureVariable(VarDecl *Var, SourceLocation Loc,
334     + bool tryCaptureVariable(ValueDecl *Var, SourceLocation Loc,
335     TryCaptureKind Kind = TryCapture_Implicit,
336     SourceLocation EllipsisLoc = SourceLocation());
337    
338     /// Checks if the variable must be captured.
339     - bool NeedToCaptureVariable(VarDecl *Var, SourceLocation Loc);
340     + bool NeedToCaptureVariable(ValueDecl *Var, SourceLocation Loc);
341    
342     /// Given a variable, determine the type that a reference to that
343     /// variable will have in the given scope.
344     - QualType getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc);
345     + QualType getCapturedDeclRefType(ValueDecl *Var, SourceLocation Loc);
346    
347     /// Mark all of the declarations referenced within a particular AST node as
348     /// referenced. Used when template instantiation instantiates a non-dependent
349     diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
350     index 159010713f4343..2e230921b938f7 100644
351     --- a/clang/lib/AST/ASTImporter.cpp
352     +++ b/clang/lib/AST/ASTImporter.cpp
353     @@ -1006,7 +1006,7 @@ ASTNodeImporter::import(const Designator &D) {
354    
355     template <>
356     Expected<LambdaCapture> ASTNodeImporter::import(const LambdaCapture &From) {
357     - VarDecl *Var = nullptr;
358     + ValueDecl *Var = nullptr;
359     if (From.capturesVariable()) {
360     if (auto VarOrErr = import(From.getCapturedVar()))
361     Var = *VarOrErr;
362     diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
363     index 030792bfc7ca3b..61688688b0a73b 100644
364     --- a/clang/lib/AST/Decl.cpp
365     +++ b/clang/lib/AST/Decl.cpp
366     @@ -4983,6 +4983,12 @@ bool ValueDecl::isWeak() const {
367     MostRecent->hasAttr<WeakRefAttr>() || isWeakImported();
368     }
369    
370     +bool ValueDecl::isInitCapture() const {
371     + if (auto *Var = llvm::dyn_cast<VarDecl>(this))
372     + return Var->isInitCapture();
373     + return false;
374     +}
375     +
376     void ImplicitParamDecl::anchor() {}
377    
378     ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC,
379     diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
380     index a955b4f3aba00f..38c46b112b8030 100644
381     --- a/clang/lib/AST/DeclCXX.cpp
382     +++ b/clang/lib/AST/DeclCXX.cpp
383     @@ -1570,8 +1570,8 @@ CXXMethodDecl *CXXRecordDecl::getLambdaStaticInvoker(CallingConv CC) const {
384     }
385    
386     void CXXRecordDecl::getCaptureFields(
387     - llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures,
388     - FieldDecl *&ThisCapture) const {
389     + llvm::DenseMap<const ValueDecl *, FieldDecl *> &Captures,
390     + FieldDecl *&ThisCapture) const {
391     Captures.clear();
392     ThisCapture = nullptr;
393    
394     diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
395     index 6328fa4a7dd512..1f860a351866f2 100644
396     --- a/clang/lib/AST/ExprCXX.cpp
397     +++ b/clang/lib/AST/ExprCXX.cpp
398     @@ -1087,7 +1087,7 @@ CXXConstructExpr::CXXConstructExpr(StmtClass SC, EmptyShell Empty,
399     : Expr(SC, Empty), NumArgs(NumArgs) {}
400    
401     LambdaCapture::LambdaCapture(SourceLocation Loc, bool Implicit,
402     - LambdaCaptureKind Kind, VarDecl *Var,
403     + LambdaCaptureKind Kind, ValueDecl *Var,
404     SourceLocation EllipsisLoc)
405     : DeclAndBits(Var, 0), Loc(Loc), EllipsisLoc(EllipsisLoc) {
406     unsigned Bits = 0;
407     @@ -1211,8 +1211,8 @@ const CompoundStmt *LambdaExpr::getCompoundStmtBody() const {
408     }
409    
410     bool LambdaExpr::isInitCapture(const LambdaCapture *C) const {
411     - return (C->capturesVariable() && C->getCapturedVar()->isInitCapture() &&
412     - (getCallOperator() == C->getCapturedVar()->getDeclContext()));
413     + return C->capturesVariable() && C->getCapturedVar()->isInitCapture() &&
414     + getCallOperator() == C->getCapturedVar()->getDeclContext();
415     }
416    
417     LambdaExpr::capture_iterator LambdaExpr::capture_begin() const {
418     diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
419     index efaccf52132b34..6f3539a4b2c177 100644
420     --- a/clang/lib/AST/ExprConstant.cpp
421     +++ b/clang/lib/AST/ExprConstant.cpp
422     @@ -578,7 +578,7 @@ namespace {
423    
424     /// LambdaCaptureFields - Mapping from captured variables/this to
425     /// corresponding data members in the closure class.
426     - llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
427     + llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
428     FieldDecl *LambdaThisCaptureField;
429    
430     CallStackFrame(EvalInfo &Info, SourceLocation CallLoc,
431     diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
432     index 8d778500d10336..9cb72ee6b1964c 100644
433     --- a/clang/lib/AST/StmtPrinter.cpp
434     +++ b/clang/lib/AST/StmtPrinter.cpp
435     @@ -2164,7 +2164,8 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) {
436     OS << "...";
437    
438     if (Node->isInitCapture(C)) {
439     - VarDecl *D = C->getCapturedVar();
440     + // Init captures are always VarDecl.
441     + auto *D = cast<VarDecl>(C->getCapturedVar());
442    
443     llvm::StringRef Pre;
444     llvm::StringRef Post;
445     diff --git a/clang/lib/Analysis/AnalysisDeclContext.cpp b/clang/lib/Analysis/AnalysisDeclContext.cpp
446     index f20924604f6491..f72c75a12fec99 100644
447     --- a/clang/lib/Analysis/AnalysisDeclContext.cpp
448     +++ b/clang/lib/Analysis/AnalysisDeclContext.cpp
449     @@ -142,7 +142,7 @@ bool AnalysisDeclContext::isBodyAutosynthesizedFromModelFile() const {
450    
451     /// Returns true if \param VD is an Objective-C implicit 'self' parameter.
452     static bool isSelfDecl(const VarDecl *VD) {
453     - return isa<ImplicitParamDecl>(VD) && VD->getName() == "self";
454     + return isa_and_nonnull<ImplicitParamDecl>(VD) && VD->getName() == "self";
455     }
456    
457     const ImplicitParamDecl *AnalysisDeclContext::getSelfDecl() const {
458     @@ -169,8 +169,8 @@ const ImplicitParamDecl *AnalysisDeclContext::getSelfDecl() const {
459     if (!LC.capturesVariable())
460     continue;
461    
462     - VarDecl *VD = LC.getCapturedVar();
463     - if (isSelfDecl(VD))
464     + ValueDecl *VD = LC.getCapturedVar();
465     + if (isSelfDecl(dyn_cast<VarDecl>(VD)))
466     return dyn_cast<ImplicitParamDecl>(VD);
467     }
468    
469     diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
470     index 522ed7ae8b144f..6527d87399bef7 100644
471     --- a/clang/lib/CodeGen/CGDebugInfo.cpp
472     +++ b/clang/lib/CodeGen/CGDebugInfo.cpp
473     @@ -1497,7 +1497,7 @@ void CGDebugInfo::CollectRecordLambdaFields(
474     if (C.capturesVariable()) {
475     SourceLocation Loc = C.getLocation();
476     assert(!Field->isBitField() && "lambdas don't have bitfield members!");
477     - VarDecl *V = C.getCapturedVar();
478     + ValueDecl *V = C.getCapturedVar();
479     StringRef VName = V->getName();
480     llvm::DIFile *VUnit = getOrCreateFile(Loc);
481     auto Align = getDeclAlignIfRequired(V, CGM.getContext());
482     diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
483     index 91a6b4e5284728..e26822eaa601e6 100644
484     --- a/clang/lib/CodeGen/CGExpr.cpp
485     +++ b/clang/lib/CodeGen/CGExpr.cpp
486     @@ -2942,8 +2942,13 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
487     // FIXME: While we're emitting a binding from an enclosing scope, all other
488     // DeclRefExprs we see should be implicitly treated as if they also refer to
489     // an enclosing scope.
490     - if (const auto *BD = dyn_cast<BindingDecl>(ND))
491     + if (const auto *BD = dyn_cast<BindingDecl>(ND)) {
492     + if (E->refersToEnclosingVariableOrCapture()) {
493     + auto *FD = LambdaCaptureFields.lookup(BD);
494     + return EmitCapturedFieldLValue(*this, FD, CXXABIThisValue);
495     + }
496     return EmitLValue(BD->getBinding());
497     + }
498    
499     // We can form DeclRefExprs naming GUID declarations when reconstituting
500     // non-type template parameters into expressions.
501     diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
502     index 3a1ed38d491fc6..9fc7360e924723 100644
503     --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
504     +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
505     @@ -409,7 +409,7 @@ class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo {
506     /// RAII for emitting code of OpenMP constructs.
507     class InlinedOpenMPRegionRAII {
508     CodeGenFunction &CGF;
509     - llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
510     + llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
511     FieldDecl *LambdaThisCaptureField = nullptr;
512     const CodeGen::CGBlockInfo *BlockInfo = nullptr;
513     bool NoInheritance = false;
514     @@ -8948,7 +8948,7 @@ class MappableExprsHandler {
515     Address VDAddr(Arg, CGF.ConvertTypeForMem(VDType),
516     CGF.getContext().getDeclAlign(VD));
517     LValue VDLVal = CGF.MakeAddrLValue(VDAddr, VDType);
518     - llvm::DenseMap<const VarDecl *, FieldDecl *> Captures;
519     + llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
520     FieldDecl *ThisCapture = nullptr;
521     RD->getCaptureFields(Captures, ThisCapture);
522     if (ThisCapture) {
523     @@ -8970,7 +8970,7 @@ class MappableExprsHandler {
524     for (const LambdaCapture &LC : RD->captures()) {
525     if (!LC.capturesVariable())
526     continue;
527     - const VarDecl *VD = LC.getCapturedVar();
528     + const VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
529     if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType())
530     continue;
531     auto It = Captures.find(VD);
532     diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
533     index 058b312c0ce68f..e8affaaecc980e 100644
534     --- a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
535     +++ b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
536     @@ -444,9 +444,8 @@ class CheckVarsEscapingDeclContext final
537     markAsEscaped(VD);
538     if (isa<OMPCapturedExprDecl>(VD))
539     VisitValueDecl(VD);
540     - else if (const auto *VarD = dyn_cast<VarDecl>(VD))
541     - if (VarD->isInitCapture())
542     - VisitValueDecl(VD);
543     + else if (VD->isInitCapture())
544     + VisitValueDecl(VD);
545     }
546     void VisitUnaryOperator(const UnaryOperator *E) {
547     if (!E)
548     @@ -3810,7 +3809,7 @@ void CGOpenMPRuntimeGPU::adjustTargetSpecificDataForLambdas(
549     else
550     VDLVal = CGF.MakeAddrLValue(
551     VDAddr, VD->getType().getCanonicalType().getNonReferenceType());
552     - llvm::DenseMap<const VarDecl *, FieldDecl *> Captures;
553     + llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
554     FieldDecl *ThisCapture = nullptr;
555     RD->getCaptureFields(Captures, ThisCapture);
556     if (ThisCapture && CGF.CapturedStmtInfo->isCXXThisExprCaptured()) {
557     @@ -3822,13 +3821,15 @@ void CGOpenMPRuntimeGPU::adjustTargetSpecificDataForLambdas(
558     for (const LambdaCapture &LC : RD->captures()) {
559     if (LC.getCaptureKind() != LCK_ByRef)
560     continue;
561     - const VarDecl *VD = LC.getCapturedVar();
562     - if (!CS->capturesVariable(VD))
563     + const ValueDecl *VD = LC.getCapturedVar();
564     + // FIXME: For now VD is always a VarDecl because OpenMP does not support
565     + // capturing structured bindings in lambdas yet.
566     + if (!CS->capturesVariable(cast<VarDecl>(VD)))
567     continue;
568     auto It = Captures.find(VD);
569     assert(It != Captures.end() && "Found lambda capture without field.");
570     LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second);
571     - Address VDAddr = CGF.GetAddrOfLocalVar(VD);
572     + Address VDAddr = CGF.GetAddrOfLocalVar(cast<VarDecl>(VD));
573     if (VD->getType().getCanonicalType()->isReferenceType())
574     VDAddr = CGF.EmitLoadOfReferenceLValue(VDAddr,
575     VD->getType().getCanonicalType())
576     diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
577     index fe0890f433e8c9..b61a2a68687d9f 100644
578     --- a/clang/lib/CodeGen/CodeGenFunction.h
579     +++ b/clang/lib/CodeGen/CodeGenFunction.h
580     @@ -609,7 +609,7 @@ class CodeGenFunction : public CodeGenTypeCache {
581     const CodeGen::CGBlockInfo *BlockInfo = nullptr;
582     llvm::Value *BlockPointer = nullptr;
583    
584     - llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
585     + llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
586     FieldDecl *LambdaThisCaptureField = nullptr;
587    
588     /// A mapping from NRVO variables to the flags used to indicate
589     diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
590     index eca20002b30dab..b110a07f4fcbad 100644
591     --- a/clang/lib/Sema/SemaDecl.cpp
592     +++ b/clang/lib/Sema/SemaDecl.cpp
593     @@ -14681,7 +14681,7 @@ static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator,
594     auto I = LambdaClass->field_begin();
595     for (const auto &C : LambdaClass->captures()) {
596     if (C.capturesVariable()) {
597     - VarDecl *VD = C.getCapturedVar();
598     + ValueDecl *VD = C.getCapturedVar();
599     if (VD->isInitCapture())
600     S.CurrentInstantiationScope->InstantiatedLocal(VD, VD);
601     const bool ByRef = C.getCaptureKind() == LCK_ByRef;
602     diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
603     index 6f758e437a9059..9497c4b5d53004 100644
604     --- a/clang/lib/Sema/SemaExpr.cpp
605     +++ b/clang/lib/Sema/SemaExpr.cpp
606     @@ -2082,9 +2082,8 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
607     NestedNameSpecifierLoc NNS, NamedDecl *FoundD,
608     SourceLocation TemplateKWLoc,
609     const TemplateArgumentListInfo *TemplateArgs) {
610     - bool RefersToCapturedVariable =
611     - isa<VarDecl>(D) &&
612     - NeedToCaptureVariable(cast<VarDecl>(D), NameInfo.getLoc());
613     + bool RefersToCapturedVariable = isa<VarDecl, BindingDecl>(D) &&
614     + NeedToCaptureVariable(D, NameInfo.getLoc());
615    
616     DeclRefExpr *E = DeclRefExpr::Create(
617     Context, NNS, TemplateKWLoc, D, RefersToCapturedVariable, NameInfo, Ty,
618     @@ -3252,8 +3251,9 @@ ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
619     return ULE;
620     }
621    
622     -static void diagnoseUncapturableValueReference(Sema &S, SourceLocation loc,
623     - ValueDecl *var);
624     +static void diagnoseUncapturableValueReferenceOrBinding(Sema &S,
625     + SourceLocation loc,
626     + ValueDecl *var);
627    
628     /// Complete semantic analysis for a reference to the given declaration.
629     ExprResult Sema::BuildDeclarationNameExpr(
630     @@ -3411,20 +3411,11 @@ ExprResult Sema::BuildDeclarationNameExpr(
631     break;
632     }
633    
634     - case Decl::Binding: {
635     + case Decl::Binding:
636     // These are always lvalues.
637     valueKind = VK_LValue;
638     type = type.getNonReferenceType();
639     - // FIXME: Support lambda-capture of BindingDecls, once CWG actually
640     - // decides how that's supposed to work.
641     - auto *BD = cast<BindingDecl>(VD);
642     - if (BD->getDeclContext() != CurContext) {
643     - auto *DD = dyn_cast_or_null<VarDecl>(BD->getDecomposedDecl());
644     - if (DD && DD->hasLocalStorage())
645     - diagnoseUncapturableValueReference(*this, Loc, BD);
646     - }
647     break;
648     - }
649    
650     case Decl::Function: {
651     if (unsigned BID = cast<FunctionDecl>(VD)->getBuiltinID()) {
652     @@ -16411,8 +16402,9 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
653     for (Capture &Cap : BSI->Captures) {
654     if (Cap.isInvalid() || Cap.isThisCapture())
655     continue;
656     -
657     - VarDecl *Var = Cap.getVariable();
658     + // Cap.getVariable() is always a VarDecl because
659     + // blocks cannot capture structured bindings or other ValueDecl kinds.
660     + auto *Var = cast<VarDecl>(Cap.getVariable());
661     Expr *CopyExpr = nullptr;
662     if (getLangOpts().CPlusPlus && Cap.isCopyCapture()) {
663     if (const RecordType *Record =
664     @@ -18243,8 +18235,8 @@ void Sema::MarkCaptureUsedInEnclosingContext(VarDecl *Capture,
665     MarkVarDeclODRUsed(Capture, Loc, *this, &CapturingScopeIndex);
666     }
667    
668     -static void diagnoseUncapturableValueReference(Sema &S, SourceLocation loc,
669     - ValueDecl *var) {
670     +void diagnoseUncapturableValueReferenceOrBinding(Sema &S, SourceLocation loc,
671     + ValueDecl *var) {
672     DeclContext *VarDC = var->getDeclContext();
673    
674     // If the parameter still belongs to the translation unit, then
675     @@ -18284,12 +18276,12 @@ static void diagnoseUncapturableValueReference(Sema &S, SourceLocation loc,
676     // capture.
677     }
678    
679     -
680     -static bool isVariableAlreadyCapturedInScopeInfo(CapturingScopeInfo *CSI, VarDecl *Var,
681     - bool &SubCapturesAreNested,
682     - QualType &CaptureType,
683     - QualType &DeclRefType) {
684     - // Check whether we've already captured it.
685     +static bool isVariableAlreadyCapturedInScopeInfo(CapturingScopeInfo *CSI,
686     + ValueDecl *Var,
687     + bool &SubCapturesAreNested,
688     + QualType &CaptureType,
689     + QualType &DeclRefType) {
690     + // Check whether we've already captured it.
691     if (CSI->CaptureMap.count(Var)) {
692     // If we found a capture, any subcaptures are nested.
693     SubCapturesAreNested = true;
694     @@ -18316,14 +18308,22 @@ static bool isVariableAlreadyCapturedInScopeInfo(CapturingScopeInfo *CSI, VarDec
695    
696     // Only block literals, captured statements, and lambda expressions can
697     // capture; other scopes don't work.
698     -static DeclContext *getParentOfCapturingContextOrNull(DeclContext *DC, VarDecl *Var,
699     - SourceLocation Loc,
700     - const bool Diagnose, Sema &S) {
701     +static DeclContext *getParentOfCapturingContextOrNull(DeclContext *DC,
702     + ValueDecl *Var,
703     + SourceLocation Loc,
704     + const bool Diagnose,
705     + Sema &S) {
706     if (isa<BlockDecl>(DC) || isa<CapturedDecl>(DC) || isLambdaCallOperator(DC))
707     return getLambdaAwareParentOfDeclContext(DC);
708     - else if (Var->hasLocalStorage()) {
709     - if (Diagnose)
710     - diagnoseUncapturableValueReference(S, Loc, Var);
711     +
712     + ValueDecl *Underlying = Var;
713     + auto *BD = dyn_cast_or_null<BindingDecl>(Var);
714     + if (BD)
715     + Underlying = BD->getDecomposedDecl();
716     +
717     + if (auto *VD = dyn_cast<VarDecl>(Underlying)) {
718     + if (VD->hasLocalStorage() && Diagnose)
719     + diagnoseUncapturableValueReferenceOrBinding(S, Loc, Var);
720     }
721     return nullptr;
722     }
723     @@ -18331,9 +18331,12 @@ static DeclContext *getParentOfCapturingContextOrNull(DeclContext *DC, VarDecl *
724     // Certain capturing entities (lambdas, blocks etc.) are not allowed to capture
725     // certain types of variables (unnamed, variably modified types etc.)
726     // so check for eligibility.
727     -static bool isVariableCapturable(CapturingScopeInfo *CSI, VarDecl *Var,
728     - SourceLocation Loc,
729     - const bool Diagnose, Sema &S) {
730     +static bool isVariableCapturable(CapturingScopeInfo *CSI, ValueDecl *Var,
731     + SourceLocation Loc, const bool Diagnose,
732     + Sema &S) {
733     +
734     + assert((isa<VarDecl, BindingDecl>(Var)) &&
735     + "Only variables and structured bindings can be captured");
736    
737     bool IsBlock = isa<BlockScopeInfo>(CSI);
738     bool IsLambda = isa<LambdaScopeInfo>(CSI);
739     @@ -18390,17 +18393,28 @@ static bool isVariableCapturable(CapturingScopeInfo *CSI, VarDecl *Var,
740     return false;
741     }
742    
743     + if (isa<BindingDecl>(Var)) {
744     + if (!IsLambda || !S.getLangOpts().CPlusPlus) {
745     + if (Diagnose)
746     + diagnoseUncapturableValueReferenceOrBinding(S, Loc, Var);
747     + return false;
748     + } else if (Diagnose && S.getLangOpts().CPlusPlus) {
749     + S.Diag(Loc, S.LangOpts.CPlusPlus20
750     + ? diag::warn_cxx17_compat_capture_binding
751     + : diag::ext_capture_binding)
752     + << Var;
753     + S.Diag(Var->getLocation(), diag::note_entity_declared_at) << Var;
754     + }
755     + }
756     +
757     return true;
758     }
759    
760     // Returns true if the capture by block was successful.
761     -static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
762     - SourceLocation Loc,
763     - const bool BuildAndDiagnose,
764     - QualType &CaptureType,
765     - QualType &DeclRefType,
766     - const bool Nested,
767     - Sema &S, bool Invalid) {
768     +static bool captureInBlock(BlockScopeInfo *BSI, ValueDecl *Var,
769     + SourceLocation Loc, const bool BuildAndDiagnose,
770     + QualType &CaptureType, QualType &DeclRefType,
771     + const bool Nested, Sema &S, bool Invalid) {
772     bool ByRef = false;
773    
774     // Blocks are not allowed to capture arrays, excepting OpenCL.
775     @@ -18464,10 +18478,9 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
776     return !Invalid;
777     }
778    
779     -
780     /// Capture the given variable in the captured region.
781     static bool captureInCapturedRegion(
782     - CapturedRegionScopeInfo *RSI, VarDecl *Var, SourceLocation Loc,
783     + CapturedRegionScopeInfo *RSI, ValueDecl *Var, SourceLocation Loc,
784     const bool BuildAndDiagnose, QualType &CaptureType, QualType &DeclRefType,
785     const bool RefersToCapturedVariable, Sema::TryCaptureKind Kind,
786     bool IsTopScope, Sema &S, bool Invalid) {
787     @@ -18506,16 +18519,12 @@ static bool captureInCapturedRegion(
788     }
789    
790     /// Capture the given variable in the lambda.
791     -static bool captureInLambda(LambdaScopeInfo *LSI,
792     - VarDecl *Var,
793     - SourceLocation Loc,
794     - const bool BuildAndDiagnose,
795     - QualType &CaptureType,
796     - QualType &DeclRefType,
797     +static bool captureInLambda(LambdaScopeInfo *LSI, ValueDecl *Var,
798     + SourceLocation Loc, const bool BuildAndDiagnose,
799     + QualType &CaptureType, QualType &DeclRefType,
800     const bool RefersToCapturedVariable,
801     const Sema::TryCaptureKind Kind,
802     - SourceLocation EllipsisLoc,
803     - const bool IsTopScope,
804     + SourceLocation EllipsisLoc, const bool IsTopScope,
805     Sema &S, bool Invalid) {
806     // Determine whether we are capturing by reference or by value.
807     bool ByRef = false;
808     @@ -18524,6 +18533,40 @@ static bool captureInLambda(LambdaScopeInfo *LSI,
809     } else {
810     ByRef = (LSI->ImpCaptureStyle == LambdaScopeInfo::ImpCap_LambdaByref);
811     }
812     + // C++20 : [expr.prim.lambda.capture]p12
813     + // A bit-field or a member of an anonymous union shall
814     + // not be captured by reference.
815     + MemberExpr *ME = nullptr;
816     + BindingDecl *BD = nullptr;
817     + if (auto *V = dyn_cast<VarDecl>(Var)) {
818     + if (V->getInit())
819     + ME = dyn_cast<MemberExpr>(V->getInit()->IgnoreImplicit());
820     + } else if ((BD = dyn_cast<BindingDecl>(Var))) {
821     + ME = dyn_cast_or_null<MemberExpr>(BD->getBinding());
822     + }
823     +
824     + // Capturing a bitfield by reference is not allowed except in OpenMP.
825     + if (ByRef && ME &&
826     + (isa<BindingDecl>(Var) || !S.LangOpts.OpenMP ||
827     + !S.isOpenMPCapturedDecl(Var))) {
828     + const auto *FD = dyn_cast_or_null<FieldDecl>(ME->getMemberDecl());
829     + if (FD && FD->isBitField()) {
830     + if (BuildAndDiagnose) {
831     + S.Diag(Loc, diag::err_bitfield_capture_by_ref) << Var;
832     + S.Diag(Var->getLocation(), diag::note_entity_declared_at) << Var;
833     + S.Diag(FD->getLocation(), diag::note_bitfield_decl) << FD;
834     + }
835     + Invalid = true;
836     + }
837     + }
838     + // FIXME: We should support capturing structured bindings in OpenMP.
839     + if (!Invalid && BD && S.LangOpts.OpenMP) {
840     + if (BuildAndDiagnose) {
841     + S.Diag(Loc, diag::err_capture_binding_openmp) << Var;
842     + S.Diag(Var->getLocation(), diag::note_entity_declared_at) << Var;
843     + }
844     + Invalid = true;
845     + }
846    
847     // Compute the type of the field that will capture this variable.
848     if (ByRef) {
849     @@ -18605,7 +18648,8 @@ static bool captureInLambda(LambdaScopeInfo *LSI,
850     return !Invalid;
851     }
852    
853     -static bool canCaptureVariableByCopy(VarDecl *Var, const ASTContext &Context) {
854     +static bool canCaptureVariableByCopy(ValueDecl *Var,
855     + const ASTContext &Context) {
856     // Offer a Copy fix even if the type is dependent.
857     if (Var->getType()->isDependentType())
858     return true;
859     @@ -18631,7 +18675,7 @@ static bool canCaptureVariableByCopy(VarDecl *Var, const ASTContext &Context) {
860     /// standard, for example we can't emit a default copy capture fix-it if we
861     /// already explicitly copy capture capture another variable.
862     static void buildLambdaCaptureFixit(Sema &Sema, LambdaScopeInfo *LSI,
863     - VarDecl *Var) {
864     + ValueDecl *Var) {
865     assert(LSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None);
866     // Don't offer Capture by copy of default capture by copy fixes if Var is
867     // known not to be copy constructible.
868     @@ -18707,14 +18751,21 @@ static void buildLambdaCaptureFixit(Sema &Sema, LambdaScopeInfo *LSI,
869     }
870    
871     bool Sema::tryCaptureVariable(
872     - VarDecl *Var, SourceLocation ExprLoc, TryCaptureKind Kind,
873     + ValueDecl *Var, SourceLocation ExprLoc, TryCaptureKind Kind,
874     SourceLocation EllipsisLoc, bool BuildAndDiagnose, QualType &CaptureType,
875     QualType &DeclRefType, const unsigned *const FunctionScopeIndexToStopAt) {
876     // An init-capture is notionally from the context surrounding its
877     // declaration, but its parent DC is the lambda class.
878     DeclContext *VarDC = Var->getDeclContext();
879     - if (Var->isInitCapture())
880     - VarDC = VarDC->getParent();
881     + const auto *VD = dyn_cast<VarDecl>(Var);
882     + if (VD) {
883     + if (VD->isInitCapture())
884     + VarDC = VarDC->getParent();
885     + } else {
886     + VD = dyn_cast<DecompositionDecl>(
887     + cast<BindingDecl>(Var)->getDecomposedDecl());
888     + }
889     + assert(VD && "Cannot capture a null variable");
890    
891     DeclContext *DC = CurContext;
892     const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt
893     @@ -18736,12 +18787,14 @@ bool Sema::tryCaptureVariable(
894    
895     // Capture global variables if it is required to use private copy of this
896     // variable.
897     - bool IsGlobal = !Var->hasLocalStorage();
898     + bool IsGlobal = !VD->hasLocalStorage();
899     if (IsGlobal &&
900     !(LangOpts.OpenMP && isOpenMPCapturedDecl(Var, /*CheckScopeInfo=*/true,
901     MaxFunctionScopesIndex)))
902     return true;
903     - Var = Var->getCanonicalDecl();
904     +
905     + if (isa<VarDecl>(Var))
906     + Var = cast<VarDecl>(Var->getCanonicalDecl());
907    
908     // Walk up the stack to determine whether we can capture the variable,
909     // performing the "simple" checks that don't depend on type. We stop when
910     @@ -18797,7 +18850,7 @@ bool Sema::tryCaptureVariable(
911     Diag(LSI->Lambda->getBeginLoc(), diag::note_lambda_decl);
912     buildLambdaCaptureFixit(*this, LSI, Var);
913     } else
914     - diagnoseUncapturableValueReference(*this, ExprLoc, Var);
915     + diagnoseUncapturableValueReferenceOrBinding(*this, ExprLoc, Var);
916     }
917     return true;
918     }
919     @@ -18945,7 +18998,7 @@ bool Sema::tryCaptureVariable(
920     return Invalid;
921     }
922    
923     -bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc,
924     +bool Sema::tryCaptureVariable(ValueDecl *Var, SourceLocation Loc,
925     TryCaptureKind Kind, SourceLocation EllipsisLoc) {
926     QualType CaptureType;
927     QualType DeclRefType;
928     @@ -18954,7 +19007,7 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc,
929     DeclRefType, nullptr);
930     }
931    
932     -bool Sema::NeedToCaptureVariable(VarDecl *Var, SourceLocation Loc) {
933     +bool Sema::NeedToCaptureVariable(ValueDecl *Var, SourceLocation Loc) {
934     QualType CaptureType;
935     QualType DeclRefType;
936     return !tryCaptureVariable(Var, Loc, TryCapture_Implicit, SourceLocation(),
937     @@ -18962,7 +19015,7 @@ bool Sema::NeedToCaptureVariable(VarDecl *Var, SourceLocation Loc) {
938     DeclRefType, nullptr);
939     }
940    
941     -QualType Sema::getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc) {
942     +QualType Sema::getCapturedDeclRefType(ValueDecl *Var, SourceLocation Loc) {
943     QualType CaptureType;
944     QualType DeclRefType;
945    
946     @@ -19558,6 +19611,24 @@ static void DoMarkVarDeclReferenced(
947     }
948     }
949    
950     +static void DoMarkBindingDeclReferenced(Sema &SemaRef, SourceLocation Loc,
951     + BindingDecl *BD) {
952     + BD->setReferenced();
953     +
954     + if (BD->isInvalidDecl())
955     + return;
956     +
957     + OdrUseContext OdrUse = isOdrUseContext(SemaRef);
958     + if (OdrUse == OdrUseContext::Used) {
959     + QualType CaptureType, DeclRefType;
960     + SemaRef.tryCaptureVariable(BD, Loc, Sema::TryCapture_Implicit,
961     + /*EllipsisLoc*/ SourceLocation(),
962     + /*BuildAndDiagnose*/ true, CaptureType,
963     + DeclRefType,
964     + /*FunctionScopeIndexToStopAt*/ nullptr);
965     + }
966     +}
967     +
968     /// Mark a variable referenced, and check whether it is odr-used
969     /// (C++ [basic.def.odr]p2, C99 6.9p3). Note that this should not be
970     /// used directly for normal expressions referring to VarDecl.
971     @@ -19577,6 +19648,11 @@ MarkExprReferenced(Sema &SemaRef, SourceLocation Loc, Decl *D, Expr *E,
972     return;
973     }
974    
975     + if (BindingDecl *Decl = dyn_cast<BindingDecl>(D)) {
976     + DoMarkBindingDeclReferenced(SemaRef, Loc, Decl);
977     + return;
978     + }
979     +
980     SemaRef.MarkAnyDeclReferenced(Loc, D, MightBeOdrUse);
981    
982     // If this is a call to a method via a cast, also mark the method in the
983     diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
984     index d3b454843234b3..737952bdfe8106 100644
985     --- a/clang/lib/Sema/SemaInit.cpp
986     +++ b/clang/lib/Sema/SemaInit.cpp
987     @@ -7846,7 +7846,7 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity,
988     break;
989     // FIXME: We can't easily tell apart an init-capture from a nested
990     // capture of an init-capture.
991     - const VarDecl *VD = Elem.Capture->getCapturedVar();
992     + const ValueDecl *VD = Elem.Capture->getCapturedVar();
993     Diag(Elem.Capture->getLocation(), diag::note_lambda_capture_initializer)
994     << VD << VD->isInitCapture() << Elem.Capture->isExplicit()
995     << (Elem.Capture->getCaptureKind() == LCK_ByRef) << VD
996     diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
997     index afc2f3ef4d76e6..3f271d6c53f17b 100644
998     --- a/clang/lib/Sema/SemaLambda.cpp
999     +++ b/clang/lib/Sema/SemaLambda.cpp
1000     @@ -1088,7 +1088,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
1001     if (C->Init.isInvalid())
1002     continue;
1003    
1004     - VarDecl *Var = nullptr;
1005     + ValueDecl *Var = nullptr;
1006     if (C->Init.isUsable()) {
1007     Diag(C->Loc, getLangOpts().CPlusPlus14
1008     ? diag::warn_cxx11_compat_init_capture
1009     @@ -1166,7 +1166,10 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
1010     continue;
1011     }
1012    
1013     - Var = R.getAsSingle<VarDecl>();
1014     + if (auto *BD = R.getAsSingle<BindingDecl>())
1015     + Var = BD;
1016     + else
1017     + Var = R.getAsSingle<VarDecl>();
1018     if (Var && DiagnoseUseOfDecl(Var, C->Loc))
1019     continue;
1020     }
1021     @@ -1200,7 +1203,13 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
1022     if (Var->isInvalidDecl())
1023     continue;
1024    
1025     - if (!Var->hasLocalStorage()) {
1026     + VarDecl *Underlying;
1027     + if (auto *BD = dyn_cast<BindingDecl>(Var))
1028     + Underlying = dyn_cast<VarDecl>(BD->getDecomposedDecl());
1029     + else
1030     + Underlying = cast<VarDecl>(Var);
1031     +
1032     + if (!Underlying->hasLocalStorage()) {
1033     Diag(C->Loc, diag::err_capture_non_automatic_variable) << C->Id;
1034     Diag(Var->getLocation(), diag::note_previous_decl) << C->Id;
1035     continue;
1036     @@ -1224,7 +1233,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
1037     }
1038    
1039     if (C->Init.isUsable()) {
1040     - addInitCapture(LSI, Var);
1041     + addInitCapture(LSI, cast<VarDecl>(Var));
1042     } else {
1043     TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef :
1044     TryCapture_ExplicitByVal;
1045     @@ -1574,7 +1583,7 @@ ExprResult Sema::BuildCaptureInit(const Capture &Cap,
1046    
1047     // An init-capture is initialized directly from its stored initializer.
1048     if (Cap.isInitCapture())
1049     - return Cap.getVariable()->getInit();
1050     + return cast<VarDecl>(Cap.getVariable())->getInit();
1051    
1052     // For anything else, build an initialization expression. For an implicit
1053     // capture, the capture notionally happens at the capture-default, so use
1054     @@ -1605,7 +1614,7 @@ ExprResult Sema::BuildCaptureInit(const Capture &Cap,
1055     Init = This;
1056     } else {
1057     assert(Cap.isVariableCapture() && "unknown kind of capture");
1058     - VarDecl *Var = Cap.getVariable();
1059     + ValueDecl *Var = Cap.getVariable();
1060     Name = Var->getIdentifier();
1061     Init = BuildDeclarationNameExpr(
1062     CXXScopeSpec(), DeclarationNameInfo(Var->getDeclName(), Loc), Var);
1063     @@ -1654,7 +1663,7 @@ mapImplicitCaptureStyle(CapturingScopeInfo::ImplicitCaptureStyle ICS) {
1064    
1065     bool Sema::CaptureHasSideEffects(const Capture &From) {
1066     if (From.isInitCapture()) {
1067     - Expr *Init = From.getVariable()->getInit();
1068     + Expr *Init = cast<VarDecl>(From.getVariable())->getInit();
1069     if (Init && Init->HasSideEffects(Context))
1070     return true;
1071     }
1072     @@ -1704,9 +1713,9 @@ FieldDecl *Sema::BuildCaptureField(RecordDecl *RD,
1073    
1074     TypeSourceInfo *TSI = nullptr;
1075     if (Capture.isVariableCapture()) {
1076     - auto *Var = Capture.getVariable();
1077     - if (Var->isInitCapture())
1078     - TSI = Capture.getVariable()->getTypeSourceInfo();
1079     + const auto *Var = dyn_cast_or_null<VarDecl>(Capture.getVariable());
1080     + if (Var && Var->isInitCapture())
1081     + TSI = Var->getTypeSourceInfo();
1082     }
1083    
1084     // FIXME: Should we really be doing this? A null TypeSourceInfo seems more
1085     @@ -1854,7 +1863,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
1086     return LambdaCapture(From.getLocation(), IsImplicit, LCK_VLAType);
1087     } else {
1088     assert(From.isVariableCapture() && "unknown kind of capture");
1089     - VarDecl *Var = From.getVariable();
1090     + ValueDecl *Var = From.getVariable();
1091     LambdaCaptureKind Kind =
1092     From.isCopyCapture() ? LCK_ByCopy : LCK_ByRef;
1093     return LambdaCapture(From.getLocation(), IsImplicit, Kind, Var,
1094     diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
1095     index a92fec6a02323f..4279a152db907d 100644
1096     --- a/clang/lib/Sema/SemaOpenMP.cpp
1097     +++ b/clang/lib/Sema/SemaOpenMP.cpp
1098     @@ -4677,12 +4677,12 @@ void Sema::tryCaptureOpenMPLambdas(ValueDecl *V) {
1099     DSAStack->setForceCaptureByReferenceInTargetExecutable(
1100     /*V=*/true);
1101     if (RD->isLambda()) {
1102     - llvm::DenseMap<const VarDecl *, FieldDecl *> Captures;
1103     + llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
1104     FieldDecl *ThisCapture;
1105     RD->getCaptureFields(Captures, ThisCapture);
1106     for (const LambdaCapture &LC : RD->captures()) {
1107     if (LC.getCaptureKind() == LCK_ByRef) {
1108     - VarDecl *VD = LC.getCapturedVar();
1109     + VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
1110     DeclContext *VDC = VD->getDeclContext();
1111     if (!VDC->Encloses(CurContext))
1112     continue;
1113     diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
1114     index c6ca10c0342c57..73d243cda974e0 100644
1115     --- a/clang/lib/Sema/SemaStmt.cpp
1116     +++ b/clang/lib/Sema/SemaStmt.cpp
1117     @@ -4695,11 +4695,11 @@ buildCapturedStmtCaptureList(Sema &S, CapturedRegionScopeInfo *RSI,
1118     if (S.getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP)
1119     S.setOpenMPCaptureKind(Field, Cap.getVariable(), RSI->OpenMPLevel);
1120    
1121     - Captures.push_back(CapturedStmt::Capture(Cap.getLocation(),
1122     - Cap.isReferenceCapture()
1123     - ? CapturedStmt::VCK_ByRef
1124     - : CapturedStmt::VCK_ByCopy,
1125     - Cap.getVariable()));
1126     + Captures.push_back(CapturedStmt::Capture(
1127     + Cap.getLocation(),
1128     + Cap.isReferenceCapture() ? CapturedStmt::VCK_ByRef
1129     + : CapturedStmt::VCK_ByCopy,
1130     + cast<VarDecl>(Cap.getVariable())));
1131     }
1132     CaptureInits.push_back(Init.get());
1133     }
1134     diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
1135     index 86d92158da8df6..14f652614730db 100644
1136     --- a/clang/lib/Sema/TreeTransform.h
1137     +++ b/clang/lib/Sema/TreeTransform.h
1138     @@ -12986,7 +12986,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
1139     continue;
1140    
1141     TransformedInitCapture &Result = InitCaptures[C - E->capture_begin()];
1142     - VarDecl *OldVD = C->getCapturedVar();
1143     + auto *OldVD = cast<VarDecl>(C->getCapturedVar());
1144    
1145     auto SubstInitCapture = [&](SourceLocation EllipsisLoc,
1146     Optional<unsigned> NumExpansions) {
1147     @@ -13003,7 +13003,8 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
1148     getSema().buildLambdaInitCaptureInitialization(
1149     C->getLocation(), OldVD->getType()->isReferenceType(),
1150     EllipsisLoc, NumExpansions, OldVD->getIdentifier(),
1151     - C->getCapturedVar()->getInitStyle() != VarDecl::CInit,
1152     + cast<VarDecl>(C->getCapturedVar())->getInitStyle() !=
1153     + VarDecl::CInit,
1154     NewExprInit);
1155     Result.Expansions.push_back(
1156     InitCaptureInfoTy(NewExprInit, NewInitCaptureType));
1157     @@ -13170,7 +13171,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
1158     if (E->isInitCapture(C)) {
1159     TransformedInitCapture &NewC = InitCaptures[C - E->capture_begin()];
1160    
1161     - VarDecl *OldVD = C->getCapturedVar();
1162     + auto *OldVD = cast<VarDecl>(C->getCapturedVar());
1163     llvm::SmallVector<Decl*, 4> NewVDs;
1164    
1165     for (InitCaptureInfoTy &Info : NewC.Expansions) {
1166     @@ -13225,7 +13226,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
1167     // The transform has determined that we should perform an expansion;
1168     // transform and capture each of the arguments.
1169     // expansion of the pattern. Do so.
1170     - VarDecl *Pack = C->getCapturedVar();
1171     + auto *Pack = cast<VarDecl>(C->getCapturedVar());
1172     for (unsigned I = 0; I != *NumExpansions; ++I) {
1173     Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
1174     VarDecl *CapturedVar
1175     diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
1176     index 34af5d6600126c..7e0496fcf34d22 100644
1177     --- a/clang/lib/Serialization/ASTWriter.cpp
1178     +++ b/clang/lib/Serialization/ASTWriter.cpp
1179     @@ -5786,7 +5786,7 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) {
1180     break;
1181     case LCK_ByCopy:
1182     case LCK_ByRef:
1183     - VarDecl *Var =
1184     + ValueDecl *Var =
1185     Capture.capturesVariable() ? Capture.getCapturedVar() : nullptr;
1186     AddDeclRef(Var);
1187     AddSourceLocation(Capture.isPackExpansion() ? Capture.getEllipsisLoc()
1188     diff --git a/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
1189     index 2102f9233bc109..8b6304f65dce5b 100644
1190     --- a/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
1191     +++ b/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
1192     @@ -504,7 +504,7 @@ class FindEscaped {
1193     // Treat local variables captured by reference in C++ lambdas as escaped.
1194     void findLambdaReferenceCaptures(const LambdaExpr *LE) {
1195     const CXXRecordDecl *LambdaClass = LE->getLambdaClass();
1196     - llvm::DenseMap<const VarDecl *, FieldDecl *> CaptureFields;
1197     + llvm::DenseMap<const ValueDecl *, FieldDecl *> CaptureFields;
1198     FieldDecl *ThisCaptureField;
1199     LambdaClass->getCaptureFields(CaptureFields, ThisCaptureField);
1200    
1201     @@ -512,14 +512,14 @@ class FindEscaped {
1202     if (!C.capturesVariable())
1203     continue;
1204    
1205     - VarDecl *VD = C.getCapturedVar();
1206     + ValueDecl *VD = C.getCapturedVar();
1207     const FieldDecl *FD = CaptureFields[VD];
1208     - if (!FD)
1209     + if (!FD || !isa<VarDecl>(VD))
1210     continue;
1211    
1212     // If the capture field is a reference type, it is capture-by-reference.
1213     if (FD->getType()->isReferenceType())
1214     - Escaped.insert(VD);
1215     + Escaped.insert(cast<VarDecl>(VD));
1216     }
1217     }
1218     };
1219     diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp
1220     index deebbd603b2c1c..0c952b5ab9a546 100644
1221     --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp
1222     +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp
1223     @@ -57,7 +57,7 @@ class UncountedLambdaCapturesChecker
1224     void visitLambdaExpr(LambdaExpr *L) const {
1225     for (const LambdaCapture &C : L->captures()) {
1226     if (C.capturesVariable()) {
1227     - VarDecl *CapturedVar = C.getCapturedVar();
1228     + ValueDecl *CapturedVar = C.getCapturedVar();
1229     if (auto *CapturedVarType = CapturedVar->getType().getTypePtrOrNull()) {
1230     Optional<bool> IsUncountedPtr = isUncountedPtr(CapturedVarType);
1231     if (IsUncountedPtr && *IsUncountedPtr) {
1232     @@ -68,7 +68,7 @@ class UncountedLambdaCapturesChecker
1233     }
1234     }
1235    
1236     - void reportBug(const LambdaCapture &Capture, VarDecl *CapturedVar,
1237     + void reportBug(const LambdaCapture &Capture, ValueDecl *CapturedVar,
1238     const Type *T) const {
1239     assert(CapturedVar);
1240    
1241     diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
1242     index cdd566029ae0ca..049b7d4724353c 100644
1243     --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
1244     +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
1245     @@ -2732,7 +2732,7 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
1246     MD->getParent()->isLambda()) {
1247     // Lookup the field of the lambda.
1248     const CXXRecordDecl *CXXRec = MD->getParent();
1249     - llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
1250     + llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
1251     FieldDecl *LambdaThisCaptureField;
1252     CXXRec->getCaptureFields(LambdaCaptureFields, LambdaThisCaptureField);
1253    
1254     diff --git a/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp b/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
1255     index 506d61d94d5fe6..f6efde8c90d136 100644
1256     --- a/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
1257     +++ b/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
1258     @@ -175,7 +175,7 @@ static bool isCapturedByReference(ExplodedNode *N, const DeclRefExpr *DR) {
1259     const CXXRecordDecl *LambdaCXXRec = MD->getParent();
1260    
1261     // Lookup the fields of the lambda
1262     - llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
1263     + llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
1264     FieldDecl *LambdaThisCaptureField;
1265     LambdaCXXRec->getCaptureFields(LambdaCaptureFields, LambdaThisCaptureField);
1266    
1267     diff --git a/clang/test/CodeGenCXX/cxx20-decomposition.cpp b/clang/test/CodeGenCXX/cxx20-decomposition.cpp
1268     new file mode 100644
1269     index 00000000000000..165450318a80ab
1270     --- /dev/null
1271     +++ b/clang/test/CodeGenCXX/cxx20-decomposition.cpp
1272     @@ -0,0 +1,48 @@
1273     +// RUN: %clang_cc1 -std=c++20 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
1274     +
1275     +struct S {
1276     + int i;
1277     + int j;
1278     +};
1279     +
1280     +int f() {
1281     + auto [i, j] = S{1, 42};
1282     + return [&i, j] {
1283     + return i + j;
1284     + }();
1285     +}
1286     +
1287     +// Ensures the representation of the lambda, the order of the
1288     +// 1st 2nd don't matter except for ABI-esque things, but make sure
1289     +// that the ref-capture is a ptr, and 'j' is captured by value.
1290     +// CHECK: %[[LAMBDA_TY:.+]] = type <{ ptr, i32, [4 x i8] }>
1291     +
1292     +// Check the captures themselves.
1293     +// CHECK: define{{.*}} i32 @_Z1fv()
1294     +// CHECK: %[[BINDING:.+]] = alloca %struct.S
1295     +// CHECK: %[[LAMBDA:.+]] = alloca %[[LAMBDA_TY]]
1296     +
1297     +// Copy a pointer to the binding, for reference capture.
1298     +// CHECK: %[[LAMBDA_CAP_PTR:.+]] = getelementptr inbounds %[[LAMBDA_TY]], ptr %[[LAMBDA]], i32 0, i32 0
1299     +// CHECK: %[[BINDING_PTR:.+]] = getelementptr inbounds %struct.S, ptr %[[BINDING]], i32 0, i32 0
1300     +// CHECK: store ptr %[[BINDING_PTR]], ptr %[[LAMBDA_CAP_PTR]]
1301     +
1302     +// Copy the integer from the binding, for copy capture.
1303     +// CHECK: %[[LAMBDA_CAP_INT:.+]] = getelementptr inbounds %[[LAMBDA_TY]], ptr %[[LAMBDA]], i32 0, i32 1
1304     +// CHECK: %[[PTR_TO_J:.+]] = getelementptr inbounds %struct.S, ptr %[[BINDING]], i32 0, i32 1
1305     +// CHECK: %[[J_COPY:.+]] = load i32, ptr %[[PTR_TO_J]]
1306     +// CHECK: store i32 %[[J_COPY]], ptr %[[LAMBDA_CAP_INT]]
1307     +
1308     +// Ensure the captures are properly extracted in operator().
1309     +// CHECK: define{{.*}} i32 @"_ZZ1fvENK3$_0clEv"
1310     +// CHECK: %[[THIS_ADDR:.+]] = alloca ptr
1311     +// CHECK: %[[THIS_PTR:.+]] = load ptr, ptr %[[THIS_ADDR]]
1312     +
1313     +// Load 'i', passed by reference.
1314     +// CHECK: %[[LAMBDA_GEP_TO_PTR:.+]] = getelementptr inbounds %[[LAMBDA_TY]], ptr %[[THIS_PTR]], i32 0, i32 0
1315     +// CHECK: %[[I_PTR:.+]] = load ptr, ptr %[[LAMBDA_GEP_TO_PTR]]
1316     +// CHECK: %[[I_VALUE:.+]] = load i32, ptr %[[I_PTR]]
1317     +
1318     +// Load the 'j', passed by value.
1319     +// CHECK: %[[LAMBDA_GEP_TO_INT:.+]] = getelementptr inbounds %[[LAMBDA_TY]], ptr %[[THIS_PTR]], i32 0, i32 1
1320     +// CHECK: %[[J_VALUE:.+]] = load i32, ptr %[[LAMBDA_GEP_TO_INT]]
1321     diff --git a/clang/test/SemaCXX/cxx1z-decomposition.cpp b/clang/test/SemaCXX/cxx1z-decomposition.cpp
1322     index 4c8c64177ed133..7165f30dc07030 100644
1323     --- a/clang/test/SemaCXX/cxx1z-decomposition.cpp
1324     +++ b/clang/test/SemaCXX/cxx1z-decomposition.cpp
1325     @@ -1,4 +1,5 @@
1326     -// RUN: %clang_cc1 -std=c++17 -verify %s
1327     +// RUN: %clang_cc1 -std=c++17 -Wc++20-extensions -verify=expected %s
1328     +// RUN: %clang_cc1 -std=c++20 -Wpre-c++20-compat -verify=expected %s
1329    
1330     void use_from_own_init() {
1331     auto [a] = a; // expected-error {{binding 'a' cannot appear in the initializer of its own decomposition declaration}}
1332     @@ -46,25 +47,58 @@ constexpr int f(S s) {
1333     }
1334     static_assert(f({1, 2}) == 12);
1335    
1336     -constexpr bool g(S &&s) {
1337     +constexpr bool g(S &&s) {
1338     auto &[a, b] = s;
1339     return &a == &s.a && &b == &s.b && &a != &b;
1340     }
1341     static_assert(g({1, 2}));
1342    
1343     -auto [outer1, outer2] = S{1, 2};
1344     +struct S1 {
1345     + int a, b;
1346     +};
1347     +struct S2 {
1348     + int a : 1; // expected-note 2{{bit-field is declared here}}
1349     + int b;
1350     +};
1351     +
1352     +auto [outer1, outer2] = S1{1, 2};
1353     +auto [outerbit1, outerbit2] = S1{1, 2}; // expected-note {{declared here}}
1354     +
1355     void enclosing() {
1356     struct S { int a = outer1; };
1357     - auto [n] = S(); // expected-note 2{{'n' declared here}}
1358     + auto [n] = S(); // expected-note 3{{'n' declared here}}
1359     +
1360     + struct Q {
1361     + int f() { return n; } // expected-error {{reference to local binding 'n' declared in enclosing function 'enclosing'}}
1362     + };
1363     +
1364     + (void)[&] { return n; }; // expected-warning {{C++20}}
1365     + (void)[n] { return n; }; // expected-warning {{C++20}}
1366    
1367     - struct Q { int f() { return n; } }; // expected-error {{reference to local binding 'n' declared in enclosing function}}
1368     - (void) [&] { return n; }; // expected-error {{reference to local binding 'n' declared in enclosing function}}
1369     - (void) [n] {}; // expected-error {{'n' in capture list does not name a variable}}
1370     + static auto [m] = S(); // expected-note {{'m' declared here}} \
1371     + // expected-warning {{C++20}}
1372    
1373     - static auto [m] = S(); // expected-warning {{extension}}
1374     struct R { int f() { return m; } };
1375     (void) [&] { return m; };
1376     - (void) [m] {}; // expected-error {{'m' in capture list does not name a variable}}
1377     + (void)[m]{}; // expected-error {{'m' cannot be captured because it does not have automatic storage duration}}
1378     +
1379     + (void)[outerbit1]{}; // expected-error {{'outerbit1' cannot be captured because it does not have automatic storage duration}}
1380     +
1381     + auto [bit, var] = S2{1, 1}; // expected-note 4{{'bit' declared here}}
1382     +
1383     + (void)[&bit] { // expected-error {{cannot capture a bit-field by reference}} \
1384     + // expected-warning {{C++20}}
1385     + return bit;
1386     + };
1387     +
1388     + union { // expected-note {{declared here}}
1389     + int u;
1390     + };
1391     +
1392     + (void)[&] { return bit + u; } // expected-error {{unnamed variable cannot be implicitly captured in a lambda expression}} \
1393     + // expected-error {{cannot capture a bit-field by reference}} \
1394     + // expected-warning {{C++20}}
1395     + ();
1396     }
1397    
1398     void bitfield() {
1399     @@ -98,7 +132,7 @@ template <class T> void dependent_foreach(T t) {
1400    
1401     struct PR37352 {
1402     int n;
1403     - void f() { static auto [a] = *this; } // expected-warning {{C++20 extension}}
1404     + void f() { static auto [a] = *this; } // expected-warning {{C++20}}
1405     };
1406    
1407     namespace instantiate_template {
1408     diff --git a/clang/test/SemaCXX/cxx20-decomposition.cpp b/clang/test/SemaCXX/cxx20-decomposition.cpp
1409     new file mode 100644
1410     index 00000000000000..a99766f5775b22
1411     --- /dev/null
1412     +++ b/clang/test/SemaCXX/cxx20-decomposition.cpp
1413     @@ -0,0 +1,141 @@
1414     +// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
1415     +// expected-no-diagnostics
1416     +
1417     +template <typename, typename>
1418     +constexpr bool is_same = false;
1419     +template <typename T>
1420     +constexpr bool is_same<T, T> = true;
1421     +
1422     +struct S {
1423     + int i;
1424     + int &j;
1425     +};
1426     +
1427     +void check_category() {
1428     + int a = 42;
1429     + {
1430     + auto [v, r] = S{1, a};
1431     + (void)[ v, r ] {
1432     + static_assert(is_same<decltype(v), int>);
1433     + static_assert(is_same<decltype(r), int &>);
1434     + };
1435     + }
1436     + {
1437     + auto [v, r] = S{1, a};
1438     + (void)[&v, &r ] {
1439     + static_assert(is_same<decltype(v), int>);
1440     + static_assert(is_same<decltype(r), int &>);
1441     + };
1442     + }
1443     + {
1444     + S s{1, a};
1445     + const auto &[v, r] = s;
1446     + (void)[ v, r ] {
1447     + static_assert(is_same<decltype(v), const int>);
1448     + static_assert(is_same<decltype(r), int &>);
1449     + };
1450     + }
1451     + {
1452     + S s{1, a};
1453     + const auto &[v, r] = s;
1454     + (void)[&v, &r ] {
1455     + static_assert(is_same<decltype(v), const int>);
1456     + static_assert(is_same<decltype(r), int &>);
1457     + };
1458     + }
1459     +}
1460     +
1461     +void check_array() {
1462     + int arr[2] = {42, 42};
1463     + auto &[a, b] = arr;
1464     + (void)[ a, &b ] {
1465     + static_assert(is_same<decltype(a), int>);
1466     + static_assert(is_same<decltype(b), int>);
1467     + };
1468     +}
1469     +
1470     +struct tuple {
1471     + template <unsigned long I>
1472     + decltype(auto) get() {
1473     + if constexpr (I == 0) {
1474     + return a;
1475     + } else {
1476     + return b;
1477     + }
1478     + }
1479     +
1480     + template <unsigned long I>
1481     + decltype(auto) get() const {
1482     + if constexpr (I == 0) {
1483     + return a;
1484     + } else {
1485     + return b;
1486     + }
1487     + }
1488     +
1489     + int a = 0;
1490     + int &b = a;
1491     +};
1492     +
1493     +namespace std {
1494     +
1495     +template <typename T>
1496     +struct tuple_size {
1497     + static constexpr unsigned long value = 2;
1498     +};
1499     +
1500     +template <unsigned long, typename T>
1501     +struct tuple_element;
1502     +
1503     +template <>
1504     +struct tuple_element<0, tuple> {
1505     + using type = int;
1506     +};
1507     +
1508     +template <>
1509     +struct tuple_element<1, tuple> {
1510     + using type = int &;
1511     +};
1512     +
1513     +template <>
1514     +struct tuple_element<0, const tuple> {
1515     + using type = int;
1516     +};
1517     +
1518     +template <>
1519     +struct tuple_element<1, const tuple> {
1520     + using type = const int &;
1521     +};
1522     +} // namespace std
1523     +
1524     +void check_tuple_like() {
1525     + tuple t;
1526     + {
1527     + auto [v, r] = t;
1528     + (void)[ v, r ] {
1529     + static_assert(is_same<decltype(v), int>);
1530     + static_assert(is_same<decltype(r), int &>);
1531     + };
1532     + }
1533     + {
1534     + auto &[v, r] = t;
1535     + (void)[&v, &r ] {
1536     + static_assert(is_same<decltype(v), int>);
1537     + static_assert(is_same<decltype(r), int &>);
1538     + };
1539     + }
1540     + {
1541     + const auto &[v, r] = t;
1542     + (void)[ v, r ] {
1543     + static_assert(is_same<decltype(v), int>);
1544     + static_assert(is_same<decltype(r), const int &>);
1545     + };
1546     + }
1547     + {
1548     + const auto &[v, r] = t;
1549     + (void)[&v, &r ] {
1550     + static_assert(is_same<decltype(v), int>);
1551     + static_assert(is_same<decltype(r), const int &>);
1552     + };
1553     + }
1554     +}
1555     diff --git a/clang/test/SemaCXX/decomposition-blocks.cpp b/clang/test/SemaCXX/decomposition-blocks.cpp
1556     new file mode 100644
1557     index 00000000000000..21f66f8c7c1b83
1558     --- /dev/null
1559     +++ b/clang/test/SemaCXX/decomposition-blocks.cpp
1560     @@ -0,0 +1,14 @@
1561     +// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s -fblocks
1562     +
1563     +struct S {
1564     + int i : 1;
1565     + int j;
1566     +};
1567     +
1568     +void run(void (^)());
1569     +void test() {
1570     + auto [i, j] = S{1, 42}; // expected-note {{'i' declared here}}
1571     + run(^{
1572     + (void)i; // expected-error {{reference to local binding 'i' declared in enclosing function 'test'}}
1573     + });
1574     +}
1575     diff --git a/clang/test/SemaCXX/decomposition-openmp.cpp b/clang/test/SemaCXX/decomposition-openmp.cpp
1576     new file mode 100644
1577     index 00000000000000..28afc398003995
1578     --- /dev/null
1579     +++ b/clang/test/SemaCXX/decomposition-openmp.cpp
1580     @@ -0,0 +1,13 @@
1581     +
1582     +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 -fopenmp %s
1583     +
1584     +// FIXME: OpenMP should support capturing structured bindings
1585     +auto f() {
1586     + int i[2] = {};
1587     + auto [a, b] = i; // expected-note 2{{declared here}}
1588     + return [=, &a] {
1589     + // expected-error@-1 {{capturing a structured binding is not yet supported in OpenMP}}
1590     + return a + b;
1591     + // expected-error@-1 {{capturing a structured binding is not yet supported in OpenMP}}
1592     + };
1593     +}
1594     diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
1595     index 9356dd4a23774b..b3f91ef794ba22 100644
1596     --- a/clang/tools/libclang/CIndex.cpp
1597     +++ b/clang/tools/libclang/CIndex.cpp
1598     @@ -3482,9 +3482,11 @@ bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) {
1599     C != CEnd; ++C) {
1600     if (!C->capturesVariable())
1601     continue;
1602     -
1603     - if (Visit(MakeCursorVariableRef(C->getCapturedVar(), C->getLocation(),
1604     - TU)))
1605     + // TODO: handle structured bindings here ?
1606     + if (!isa<VarDecl>(C->getCapturedVar()))
1607     + continue;
1608     + if (Visit(MakeCursorVariableRef(cast<VarDecl>(C->getCapturedVar()),
1609     + C->getLocation(), TU)))
1610     return true;
1611     }
1612     // Visit init captures
1613     diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html
1614     index 41b788e82d73de..5aae4ba8228261 100755
1615     --- a/clang/www/cxx_status.html
1616     +++ b/clang/www/cxx_status.html
1617     @@ -1140,7 +1140,7 @@ <h2 id="cxx20">C++20 implementation status</h2>
1618     <tr>
1619     <td rowspan="2">Structured binding extensions</td>
1620     <td><a href="https://wg21.link/p1091r3">P1091R3</a></td>
1621     - <td rowspan="2" class="partial" align="center">Partial</td>
1622     + <td rowspan="2" class="unreleased" align="center">Clang 16</td>
1623     </tr>
1624     <tr>
1625     <td><a href="https://wg21.link/p1381r1">P1381R1</a></td>