|
20 | 20 | #include "clang/AST/Expr.h"
|
21 | 21 | #include "clang/AST/ExprConcepts.h"
|
22 | 22 | #include "clang/AST/PrettyDeclStackTrace.h"
|
| 23 | +#include "clang/AST/RecursiveASTVisitor.h" |
23 | 24 | #include "clang/AST/Type.h"
|
24 | 25 | #include "clang/AST/TypeLoc.h"
|
25 | 26 | #include "clang/AST/TypeVisitor.h"
|
@@ -87,12 +88,19 @@ struct Response {
|
87 | 88 | // than lambda classes.
|
88 | 89 | const FunctionDecl *
|
89 | 90 | getPrimaryTemplateOfGenericLambda(const FunctionDecl *LambdaCallOperator) {
|
| 91 | + if (!isLambdaCallOperator(LambdaCallOperator)) |
| 92 | + return LambdaCallOperator; |
90 | 93 | while (true) {
|
91 | 94 | if (auto *FTD = dyn_cast_if_present<FunctionTemplateDecl>(
|
92 | 95 | LambdaCallOperator->getDescribedTemplate());
|
93 | 96 | FTD && FTD->getInstantiatedFromMemberTemplate()) {
|
94 | 97 | LambdaCallOperator =
|
95 | 98 | FTD->getInstantiatedFromMemberTemplate()->getTemplatedDecl();
|
| 99 | + } else if (LambdaCallOperator->getPrimaryTemplate()) { |
| 100 | + // Cases where the lambda operator is instantiated in |
| 101 | + // TemplateDeclInstantiator::VisitCXXMethodDecl. |
| 102 | + LambdaCallOperator = |
| 103 | + LambdaCallOperator->getPrimaryTemplate()->getTemplatedDecl(); |
96 | 104 | } else if (auto *Prev = cast<CXXMethodDecl>(LambdaCallOperator)
|
97 | 105 | ->getInstantiatedFromMemberFunction())
|
98 | 106 | LambdaCallOperator = Prev;
|
@@ -138,22 +146,28 @@ getEnclosingTypeAliasTemplateDecl(Sema &SemaRef) {
|
138 | 146 | // Check if we are currently inside of a lambda expression that is
|
139 | 147 | // surrounded by a using alias declaration. e.g.
|
140 | 148 | // template <class> using type = decltype([](auto) { ^ }());
|
141 |
| -// By checking if: |
142 |
| -// 1. The lambda expression and the using alias declaration share the |
143 |
| -// same declaration context. |
144 |
| -// 2. They have the same template depth. |
145 | 149 | // We have to do so since a TypeAliasTemplateDecl (or a TypeAliasDecl) is never
|
146 | 150 | // a DeclContext, nor does it have an associated specialization Decl from which
|
147 | 151 | // we could collect these template arguments.
|
148 | 152 | bool isLambdaEnclosedByTypeAliasDecl(
|
149 |
| - const FunctionDecl *PrimaryLambdaCallOperator, |
| 153 | + const FunctionDecl *LambdaCallOperator, |
150 | 154 | const TypeAliasTemplateDecl *PrimaryTypeAliasDecl) {
|
151 |
| - return cast<CXXRecordDecl>(PrimaryLambdaCallOperator->getDeclContext()) |
152 |
| - ->getTemplateDepth() == |
153 |
| - PrimaryTypeAliasDecl->getTemplateDepth() && |
154 |
| - getLambdaAwareParentOfDeclContext( |
155 |
| - const_cast<FunctionDecl *>(PrimaryLambdaCallOperator)) == |
156 |
| - PrimaryTypeAliasDecl->getDeclContext(); |
| 155 | + struct Visitor : RecursiveASTVisitor<Visitor> { |
| 156 | + Visitor(const FunctionDecl *CallOperator) : CallOperator(CallOperator) {} |
| 157 | + bool VisitLambdaExpr(const LambdaExpr *LE) { |
| 158 | + // Return true to bail out of the traversal, implying the Decl contains |
| 159 | + // the lambda. |
| 160 | + return getPrimaryTemplateOfGenericLambda(LE->getCallOperator()) != |
| 161 | + CallOperator; |
| 162 | + } |
| 163 | + const FunctionDecl *CallOperator; |
| 164 | + }; |
| 165 | + |
| 166 | + QualType Underlying = |
| 167 | + PrimaryTypeAliasDecl->getTemplatedDecl()->getUnderlyingType(); |
| 168 | + |
| 169 | + return !Visitor(getPrimaryTemplateOfGenericLambda(LambdaCallOperator)) |
| 170 | + .TraverseType(Underlying); |
157 | 171 | }
|
158 | 172 |
|
159 | 173 | // Add template arguments from a variable template instantiation.
|
@@ -290,23 +304,8 @@ Response HandleFunction(Sema &SemaRef, const FunctionDecl *Function,
|
290 | 304 |
|
291 | 305 | // If this function is a generic lambda specialization, we are done.
|
292 | 306 | if (!ForConstraintInstantiation &&
|
293 |
| - isGenericLambdaCallOperatorOrStaticInvokerSpecialization(Function)) { |
294 |
| - // TypeAliasTemplateDecls should be taken into account, e.g. |
295 |
| - // when we're deducing the return type of a lambda. |
296 |
| - // |
297 |
| - // template <class> int Value = 0; |
298 |
| - // template <class T> |
299 |
| - // using T = decltype([]<int U = 0>() { return Value<T>; }()); |
300 |
| - // |
301 |
| - if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl(SemaRef)) { |
302 |
| - if (isLambdaEnclosedByTypeAliasDecl( |
303 |
| - /*PrimaryLambdaCallOperator=*/getPrimaryTemplateOfGenericLambda( |
304 |
| - Function), |
305 |
| - /*PrimaryTypeAliasDecl=*/TypeAlias.PrimaryTypeAliasDecl)) |
306 |
| - return Response::UseNextDecl(Function); |
307 |
| - } |
| 307 | + isGenericLambdaCallOperatorOrStaticInvokerSpecialization(Function)) |
308 | 308 | return Response::Done();
|
309 |
| - } |
310 | 309 |
|
311 | 310 | } else if (Function->getDescribedFunctionTemplate()) {
|
312 | 311 | assert(
|
@@ -418,10 +417,9 @@ Response HandleRecordDecl(Sema &SemaRef, const CXXRecordDecl *Rec,
|
418 | 417 | // Retrieve the template arguments for a using alias declaration.
|
419 | 418 | // This is necessary for constraint checking, since we always keep
|
420 | 419 | // constraints relative to the primary template.
|
421 |
| - if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl(SemaRef)) { |
422 |
| - const FunctionDecl *PrimaryLambdaCallOperator = |
423 |
| - getPrimaryTemplateOfGenericLambda(Rec->getLambdaCallOperator()); |
424 |
| - if (isLambdaEnclosedByTypeAliasDecl(PrimaryLambdaCallOperator, |
| 420 | + if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl(SemaRef); |
| 421 | + ForConstraintInstantiation && TypeAlias) { |
| 422 | + if (isLambdaEnclosedByTypeAliasDecl(Rec->getLambdaCallOperator(), |
425 | 423 | TypeAlias.PrimaryTypeAliasDecl)) {
|
426 | 424 | Result.addOuterTemplateArguments(TypeAlias.Template,
|
427 | 425 | TypeAlias.AssociatedTemplateArguments,
|
@@ -1642,12 +1640,17 @@ namespace {
|
1642 | 1640 |
|
1643 | 1641 | CXXRecordDecl::LambdaDependencyKind
|
1644 | 1642 | ComputeLambdaDependency(LambdaScopeInfo *LSI) {
|
1645 |
| - auto &CCS = SemaRef.CodeSynthesisContexts.back(); |
1646 |
| - if (CCS.Kind == |
1647 |
| - Sema::CodeSynthesisContext::TypeAliasTemplateInstantiation) { |
1648 |
| - unsigned TypeAliasDeclDepth = CCS.Entity->getTemplateDepth(); |
| 1643 | + if (auto TypeAlias = |
| 1644 | + TemplateInstArgsHelpers::getEnclosingTypeAliasTemplateDecl( |
| 1645 | + getSema()); |
| 1646 | + TypeAlias && TemplateInstArgsHelpers::isLambdaEnclosedByTypeAliasDecl( |
| 1647 | + LSI->CallOperator, TypeAlias.PrimaryTypeAliasDecl)) { |
| 1648 | + unsigned TypeAliasDeclDepth = TypeAlias.Template->getTemplateDepth(); |
1649 | 1649 | if (TypeAliasDeclDepth >= TemplateArgs.getNumSubstitutedLevels())
|
1650 | 1650 | return CXXRecordDecl::LambdaDependencyKind::LDK_AlwaysDependent;
|
| 1651 | + for (const TemplateArgument &TA : TypeAlias.AssociatedTemplateArguments) |
| 1652 | + if (TA.isDependent()) |
| 1653 | + return CXXRecordDecl::LambdaDependencyKind::LDK_AlwaysDependent; |
1651 | 1654 | }
|
1652 | 1655 | return inherited::ComputeLambdaDependency(LSI);
|
1653 | 1656 | }
|
|
0 commit comments