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