Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[clang] Fix linkage of nested lambdas.
patch from Philippe Daouadi <blastrock@free.fr>

This is an attempt to fix
[PR#44368](https://bugs.llvm.org/show_bug.cgi?id=44368)

This effectively reverts [D1783](https://reviews.llvm.org/D1783). It
doesn't break the current tests and fixes the test that this commit
adds.

We now decide of a lambda linkage only depending on the visibility of
its parent context.

Differential Revision: https://reviews.llvm.org/D73701
  • Loading branch information
darkbuck committed Feb 7, 2020
1 parent cbe0c82 commit 2926917
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 31 deletions.
33 changes: 2 additions & 31 deletions clang/lib/AST/Decl.cpp
Expand Up @@ -1318,19 +1318,6 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
LV.isVisibilityExplicit());
}

static inline const CXXRecordDecl*
getOutermostEnclosingLambda(const CXXRecordDecl *Record) {
const CXXRecordDecl *Ret = Record;
while (Record && Record->isLambda()) {
Ret = Record;
if (!Record->getParent()) break;
// Get the Containing Class of this Lambda Class
Record = dyn_cast_or_null<CXXRecordDecl>(
Record->getParent()->getParent());
}
return Ret;
}

LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D,
LVComputationKind computation,
bool IgnoreVarTypeLinkage) {
Expand Down Expand Up @@ -1396,25 +1383,9 @@ LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D,
return getInternalLinkageFor(D);
}

// This lambda has its linkage/visibility determined:
// - either by the outermost lambda if that lambda has no mangling
// number.
// - or by the parent of the outer most lambda
// This prevents infinite recursion in settings such as nested lambdas
// used in NSDMI's, for e.g.
// struct L {
// int t{};
// int t2 = ([](int a) { return [](int b) { return b; };})(t)(t);
// };
const CXXRecordDecl *OuterMostLambda =
getOutermostEnclosingLambda(Record);
if (OuterMostLambda->hasKnownLambdaInternalLinkage() ||
!OuterMostLambda->getLambdaManglingNumber())
return getInternalLinkageFor(D);

return getLVForClosure(
OuterMostLambda->getDeclContext()->getRedeclContext(),
OuterMostLambda->getLambdaContextDecl(), computation);
Record->getDeclContext()->getRedeclContext(),
Record->getLambdaContextDecl(), computation);
}

break;
Expand Down
16 changes: 16 additions & 0 deletions clang/test/CodeGenCXX/lambda-expressions-nested-linkage.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -fblocks -emit-llvm -o - %s -fexceptions -std=c++11 | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -fblocks -emit-llvm -o - %s -fexceptions -std=c++14 | FileCheck --check-prefixes=CHECK,CXX14 %s

// CHECK-LABEL: define void @_ZN19non_inline_function3fooEv()
// CHECK-LABEL: define internal void @"_ZZN19non_inline_function3fooEvENK3$_0clEi"(%class.anon
Expand Down Expand Up @@ -51,3 +52,18 @@ inline int foo() {
}
int use = foo();
}

#if __cplusplus >= 201402L
// CXX14-LABEL: define internal void @"_ZZZN32lambda_capture_in_generic_lambda3fooIiEEDavENKUlT_E_clIZNS_L1fEvE3$_1EEDaS1_ENKUlvE_clEv"
namespace lambda_capture_in_generic_lambda {
template <typename T> auto foo() {
return [](auto func) {
[func] { func(); }();
};
}
static void f() {
foo<int>()([] { });
}
void f1() { f(); }
}
#endif

0 comments on commit 2926917

Please sign in to comment.