r191645 - Fix computation of linkage within nested lambdas.
Faisal Vali
faisalv at yahoo.com
Sun Sep 29 13:00:16 PDT 2013
Author: faisalv
Date: Sun Sep 29 15:00:15 2013
New Revision: 191645
URL: http://llvm.org/viewvc/llvm-project?rev=191645&view=rev
Log:
Fix computation of linkage within nested lambdas.
When nested lambdas are used in NSDMI's - this prevents infinite recursion.
See http://llvm-reviews.chandlerc.com/D1783 for Doug's approval regarding the code, and then request for some tests.
[On a related note, I need this patch so as to pass tests of transformations of nested lambdas returned from member functions]
Added:
cfe/trunk/test/CodeGenCXX/lambda-expressions-nested-linkage.cpp
Modified:
cfe/trunk/lib/AST/Decl.cpp
cfe/trunk/test/SemaCXX/lambda-expressions.cpp
Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=191645&r1=191644&r2=191645&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Sun Sep 29 15:00:15 2013
@@ -1004,10 +1004,8 @@ static LinkageInfo getLVForClosure(const
else
return getLVForDecl(cast<NamedDecl>(ContextDecl), computation);
}
-
if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC))
return getLVForDecl(ND, computation);
-
return LinkageInfo::external();
}
@@ -1092,6 +1090,19 @@ static LinkageInfo getLVForLocalDecl(con
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;
+}
+
static LinkageInfo computeLVForDecl(const NamedDecl *D,
LVComputationKind computation) {
// Objective-C: treat all Objective-C declarations as having external
@@ -1122,9 +1133,24 @@ static LinkageInfo computeLVForDecl(cons
return LinkageInfo::internal();
}
- // This lambda has its linkage/visibility determined by its owner.
- return getLVForClosure(D->getDeclContext()->getRedeclContext(),
- Record->getLambdaContextDecl(), computation);
+ // 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->getLambdaManglingNumber())
+ return LinkageInfo::internal();
+
+ return getLVForClosure(
+ OuterMostLambda->getDeclContext()->getRedeclContext(),
+ OuterMostLambda->getLambdaContextDecl(), computation);
}
break;
Added: cfe/trunk/test/CodeGenCXX/lambda-expressions-nested-linkage.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/lambda-expressions-nested-linkage.cpp?rev=191645&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/lambda-expressions-nested-linkage.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/lambda-expressions-nested-linkage.cpp Sun Sep 29 15:00:15 2013
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -fblocks -emit-llvm -o - %s -fexceptions -std=c++11 | FileCheck %s
+
+// CHECK-LABEL: define void @_ZN19non_inline_function3fooEv()
+// CHECK-LABEL: define internal void @"_ZZN19non_inline_function3fooEvENK3$_0clEi"
+// CHECK-LABEL: define internal signext i8 @"_ZZZN19non_inline_function3fooEvENK3$_0clEiENKUlcE_clEc"
+namespace non_inline_function {
+void foo() {
+ auto L = [](int a) {
+ return [](char b) {
+ return b;
+ };
+ };
+ L(3)('a');
+}
+}
+// CHECK-LABEL: define linkonce_odr i32 @_ZN15inline_function3fooEv
+// CHECK-LABEL: define linkonce_odr void @_ZZN15inline_function3fooEvENKUliE_clEi
+// CHECK-LABEL: define linkonce_odr signext i8 @_ZZZN15inline_function3fooEvENKUliE_clEiENKUlcE_clEc
+namespace inline_function {
+inline int foo() {
+ auto L = [](int a) {
+ return [](char b) {
+ return b;
+ };
+ };
+ L(3)('a');
+}
+int use = foo();
+}
+
+// CHECK-LABEL: define linkonce_odr void @_ZN12non_template1LC1Ev
+// CHECK-LABEL: define linkonce_odr void @_ZNK12non_template1L1tMUliE_clEi(%class.anon
+// CHECK-LABEL: define linkonce_odr i32 @_ZZNK12non_template1L1tMUliE_clEiENKUliE_clEi(%class.anon
+namespace non_template {
+ struct L {
+ int t = ([](int a) { return [](int b) { return b; };})(2)(3);
+ };
+ L l;
+}
+
+// CHECK-LABEL: define linkonce_odr void @_ZN32lambdas_in_NSDMIs_template_class1LIiEC2Ev
+// CHECK-LABEL: define linkonce_odr void @_ZNK32lambdas_in_NSDMIs_template_class1LIiEUliE_clEi(%class.anon
+// CHECK-LABEL: linkonce_odr i32 @_ZZNK32lambdas_in_NSDMIs_template_class1LIiEUliE_clEiENKUliE_clEi(%class.anon
+namespace lambdas_in_NSDMIs_template_class {
+template<class T>
+struct L {
+ T t2 = ([](int a) { return [](int b) { return b; };})(T{})(T{});
+};
+L<int> l;
+}
+
+
+
Modified: cfe/trunk/test/SemaCXX/lambda-expressions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/lambda-expressions.cpp?rev=191645&r1=191644&r2=191645&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/lambda-expressions.cpp (original)
+++ cfe/trunk/test/SemaCXX/lambda-expressions.cpp Sun Sep 29 15:00:15 2013
@@ -265,3 +265,21 @@ namespace TypeDeduction {
#endif
}
}
+
+
+namespace lambdas_in_NSDMIs {
+ template<class T>
+ struct L {
+ T t{};
+ T t2 = ([](int a) { return [](int b) { return b; };})(t)(t);
+ };
+ L<int> l;
+
+ namespace non_template {
+ struct L {
+ int t = 0;
+ int t2 = ([](int a) { return [](int b) { return b; };})(t)(t);
+ };
+ L l;
+ }
+}
\ No newline at end of file
More information about the cfe-commits
mailing list