|
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,17 @@ 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 | + LambdaCallOperator = |
| 101 | + LambdaCallOperator->getPrimaryTemplate()->getTemplatedDecl(); |
96 | 102 | } else if (auto *Prev = cast<CXXMethodDecl>(LambdaCallOperator)
|
97 | 103 | ->getInstantiatedFromMemberFunction())
|
98 | 104 | LambdaCallOperator = Prev;
|
@@ -138,22 +144,26 @@ getEnclosingTypeAliasTemplateDecl(Sema &SemaRef) {
|
138 | 144 | // Check if we are currently inside of a lambda expression that is
|
139 | 145 | // surrounded by a using alias declaration. e.g.
|
140 | 146 | // 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 | 147 | // We have to do so since a TypeAliasTemplateDecl (or a TypeAliasDecl) is never
|
146 | 148 | // a DeclContext, nor does it have an associated specialization Decl from which
|
147 | 149 | // we could collect these template arguments.
|
148 | 150 | bool isLambdaEnclosedByTypeAliasDecl(
|
149 |
| - const FunctionDecl *PrimaryLambdaCallOperator, |
| 151 | + const FunctionDecl *LambdaCallOperator, |
150 | 152 | const TypeAliasTemplateDecl *PrimaryTypeAliasDecl) {
|
151 |
| - return cast<CXXRecordDecl>(PrimaryLambdaCallOperator->getDeclContext()) |
152 |
| - ->getTemplateDepth() == |
153 |
| - PrimaryTypeAliasDecl->getTemplateDepth() && |
154 |
| - getLambdaAwareParentOfDeclContext( |
155 |
| - const_cast<FunctionDecl *>(PrimaryLambdaCallOperator)) == |
156 |
| - PrimaryTypeAliasDecl->getDeclContext(); |
| 153 | + struct Visitor : RecursiveASTVisitor<Visitor> { |
| 154 | + Visitor(const FunctionDecl *CallOperator) : CallOperator(CallOperator) {} |
| 155 | + bool VisitLambdaExpr(const LambdaExpr *LE) { |
| 156 | + auto *G = getPrimaryTemplateOfGenericLambda(LE->getCallOperator()); |
| 157 | + return G != CallOperator; |
| 158 | + } |
| 159 | + const FunctionDecl *CallOperator; |
| 160 | + }; |
| 161 | + QualType Underlying = |
| 162 | + PrimaryTypeAliasDecl->getTemplatedDecl()->getUnderlyingType(); |
| 163 | + if (auto *DT = dyn_cast<DecltypeType>(Underlying.getTypePtr())) |
| 164 | + return !Visitor(getPrimaryTemplateOfGenericLambda(LambdaCallOperator)) |
| 165 | + .TraverseStmt(DT->getUnderlyingExpr()); |
| 166 | + return false; |
157 | 167 | }
|
158 | 168 |
|
159 | 169 | // Add template arguments from a variable template instantiation.
|
@@ -283,23 +293,8 @@ Response HandleFunction(Sema &SemaRef, const FunctionDecl *Function,
|
283 | 293 |
|
284 | 294 | // If this function is a generic lambda specialization, we are done.
|
285 | 295 | if (!ForConstraintInstantiation &&
|
286 |
| - isGenericLambdaCallOperatorOrStaticInvokerSpecialization(Function)) { |
287 |
| - // TypeAliasTemplateDecls should be taken into account, e.g. |
288 |
| - // when we're deducing the return type of a lambda. |
289 |
| - // |
290 |
| - // template <class> int Value = 0; |
291 |
| - // template <class T> |
292 |
| - // using T = decltype([]<int U = 0>() { return Value<T>; }()); |
293 |
| - // |
294 |
| - if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl(SemaRef)) { |
295 |
| - if (isLambdaEnclosedByTypeAliasDecl( |
296 |
| - /*PrimaryLambdaCallOperator=*/getPrimaryTemplateOfGenericLambda( |
297 |
| - Function), |
298 |
| - /*PrimaryTypeAliasDecl=*/TypeAlias.PrimaryTypeAliasDecl)) |
299 |
| - return Response::UseNextDecl(Function); |
300 |
| - } |
| 296 | + isGenericLambdaCallOperatorOrStaticInvokerSpecialization(Function)) |
301 | 297 | return Response::Done();
|
302 |
| - } |
303 | 298 |
|
304 | 299 | } else if (Function->getDescribedFunctionTemplate()) {
|
305 | 300 | assert(
|
@@ -412,9 +407,7 @@ Response HandleRecordDecl(Sema &SemaRef, const CXXRecordDecl *Rec,
|
412 | 407 | // This is necessary for constraint checking, since we always keep
|
413 | 408 | // constraints relative to the primary template.
|
414 | 409 | if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl(SemaRef)) {
|
415 |
| - const FunctionDecl *PrimaryLambdaCallOperator = |
416 |
| - getPrimaryTemplateOfGenericLambda(Rec->getLambdaCallOperator()); |
417 |
| - if (isLambdaEnclosedByTypeAliasDecl(PrimaryLambdaCallOperator, |
| 410 | + if (isLambdaEnclosedByTypeAliasDecl(Rec->getLambdaCallOperator(), |
418 | 411 | TypeAlias.PrimaryTypeAliasDecl)) {
|
419 | 412 | Result.addOuterTemplateArguments(TypeAlias.Template,
|
420 | 413 | TypeAlias.AssociatedTemplateArguments,
|
@@ -1670,12 +1663,17 @@ namespace {
|
1670 | 1663 |
|
1671 | 1664 | CXXRecordDecl::LambdaDependencyKind
|
1672 | 1665 | ComputeLambdaDependency(LambdaScopeInfo *LSI) {
|
1673 |
| - auto &CCS = SemaRef.CodeSynthesisContexts.back(); |
1674 |
| - if (CCS.Kind == |
1675 |
| - Sema::CodeSynthesisContext::TypeAliasTemplateInstantiation) { |
1676 |
| - unsigned TypeAliasDeclDepth = CCS.Entity->getTemplateDepth(); |
| 1666 | + if (auto TypeAlias = |
| 1667 | + TemplateInstArgsHelpers::getEnclosingTypeAliasTemplateDecl( |
| 1668 | + getSema()); |
| 1669 | + TypeAlias && TemplateInstArgsHelpers::isLambdaEnclosedByTypeAliasDecl( |
| 1670 | + LSI->CallOperator, TypeAlias.PrimaryTypeAliasDecl)) { |
| 1671 | + unsigned TypeAliasDeclDepth = TypeAlias.Template->getTemplateDepth(); |
1677 | 1672 | if (TypeAliasDeclDepth >= TemplateArgs.getNumSubstitutedLevels())
|
1678 | 1673 | return CXXRecordDecl::LambdaDependencyKind::LDK_AlwaysDependent;
|
| 1674 | + for (TemplateArgument TA : TypeAlias.AssociatedTemplateArguments) |
| 1675 | + if (TA.isDependent()) |
| 1676 | + return CXXRecordDecl::LambdaDependencyKind::LDK_AlwaysDependent; |
1679 | 1677 | }
|
1680 | 1678 | return inherited::ComputeLambdaDependency(LSI);
|
1681 | 1679 | }
|
|
0 commit comments