Index: include/clang/AST/ASTLambda.h =================================================================== --- include/clang/AST/ASTLambda.h +++ include/clang/AST/ASTLambda.h @@ -31,7 +31,13 @@ return MD->getOverloadedOperator() == OO_Call; } +inline bool isLambdaCallOperator(const DeclContext* DC) { + if (!DC || !isa(DC)) return false; + return isLambdaCallOperator(cast(DC)); +} + inline bool isGenericLambdaCallOperatorSpecialization(CXXMethodDecl *MD) { + if (!MD) return false; CXXRecordDecl *LambdaClass = MD->getParent(); if (LambdaClass && LambdaClass->isGenericLambda()) return isLambdaCallOperator(MD) && @@ -44,6 +50,34 @@ return isGenericLambdaCallOperatorSpecialization( cast(D)); } + + +// Given a DeclContext, retrieve the inner most non-lambda enclosing scope (i.e. +// usually the parent function or the parent class (NSDMI's)) +inline const DeclContext* +getInnermostEnclosingNonLambdaContext(const DeclContext *DC) { + const CXXRecordDecl *Record = 0; + if (isLambdaCallOperator(DC)) + Record = cast(DC->getParent()); + else + Record = dyn_cast(DC); + const DeclContext *Ret = DC; + while (Record && Record->isLambda()) { + // Get the Containing DeclContext of this Lambda Class + Ret = Record->getDeclContext()->getRedeclContext(); + // Is it a lambda call operator? If so check its parent + if (isLambdaCallOperator(Ret)) + Record = cast(Ret)->getParent(); + else // otherwise we are done + break; + } + assert(Ret && "There should be a non-lambda enclosing decl context!"); + return Ret; +} + + + + } // clang #endif // LLVM_CLANG_AST_LAMBDA_H Index: lib/AST/Decl.cpp =================================================================== --- lib/AST/Decl.cpp +++ lib/AST/Decl.cpp @@ -13,6 +13,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTLambda.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/Attr.h" #include "clang/AST/DeclCXX.h" @@ -995,6 +996,7 @@ return None; } + static LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl, LVComputationKind computation) { // This lambda has its linkage/visibility determined by its owner. @@ -1005,9 +1007,20 @@ return getLVForDecl(cast(ContextDecl), computation); } - if (const NamedDecl *ND = dyn_cast(DC)) + // If this Lambda is within another Lambda, just keep climbing up + // until we are outside a lambda, because the linkage is determined + // by the parent decl context. This prevents recursion in + // settings such as nested lambdas used in NSDMI's, for e.g. + // + // template + // struct L { + // T t{}; + // T t2 = ([](int a) { return [](int b) { return b; };})(t)(t); + // }; + // L l; + if (const NamedDecl *ND = + dyn_cast(getInnermostEnclosingNonLambdaContext(DC))) return getLVForDecl(ND, computation); - return LinkageInfo::external(); } @@ -1121,7 +1134,6 @@ // This lambda has no mangling number, so it's internal. return LinkageInfo::internal(); } - // This lambda has its linkage/visibility determined by its owner. return getLVForClosure(D->getDeclContext()->getRedeclContext(), Record->getLambdaContextDecl(), computation); Index: test/SemaCXX/lambda-expressions.cpp =================================================================== --- test/SemaCXX/lambda-expressions.cpp +++ test/SemaCXX/lambda-expressions.cpp @@ -265,3 +265,13 @@ #endif } } + + +namespace lambdas_in_NSDMIs { +template + struct L { + T t{}; + T t2 = ([](int a) { return [](int b) { return b; };})(t)(t); + }; + L l; +} \ No newline at end of file