summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2013-05-12 23:17:59 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2013-05-12 23:17:59 +0000
commit50f4afcc281ab9ca023e3c92e8078e6d8378af62 (patch)
treee1301bb4dd33b6433909e4ed99158892d815ba8e
parentce42cc6d4dd2a07cba6205222c940d326a7fd3b2 (diff)
downloadbcm5719-llvm-50f4afcc281ab9ca023e3c92e8078e6d8378af62.tar.gz
bcm5719-llvm-50f4afcc281ab9ca023e3c92e8078e6d8378af62.zip
Fix stack overflow in linkage computation when a function with a deduced return
type returns a lambda defined within itself. The computation of linkage for the function looked at the linkage of the lambda, and vice versa. This is solved by not checking whether an 'auto' in a function return type deduces to a type with unique external linkage. We don't need this check, because the type deduced for 'auto' doesn't affect whether two otherwise-identical declarations would name different functions, so we don't need to give an ostensibly external-linkage function internal linkage for this reason. (We also don't need unique-external linkage in C++11 onwards at all, but that's not implemented yet.) llvm-svn: 181675
-rw-r--r--clang/lib/AST/Decl.cpp17
-rw-r--r--clang/test/CodeGenCXX/cxx1y-deduced-return-type.cpp32
2 files changed, 46 insertions, 3 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index ab9d73b9178..df923d67364 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -660,9 +660,20 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
// this translation unit. However, we should use the C linkage
// rules instead for extern "C" declarations.
if (Context.getLangOpts().CPlusPlus &&
- !Function->isInExternCContext() &&
- Function->getType()->getLinkage() == UniqueExternalLinkage)
- return LinkageInfo::uniqueExternal();
+ !Function->isInExternCContext()) {
+ // Only look at the type-as-written. If this function has an auto-deduced
+ // return type, we can't compute the linkage of that type because it could
+ // require looking at the linkage of this function, and we don't need this
+ // for correctness because the type is not part of the function's
+ // signature.
+ // FIXME: This is a hack. We should be able to solve this circularity some
+ // other way.
+ QualType TypeAsWritten = Function->getType();
+ if (TypeSourceInfo *TSI = Function->getTypeSourceInfo())
+ TypeAsWritten = TSI->getType();
+ if (TypeAsWritten->getLinkage() == UniqueExternalLinkage)
+ return LinkageInfo::uniqueExternal();
+ }
// Consider LV from the template and the template arguments.
// We're at file scope, so we do not need to worry about nested
diff --git a/clang/test/CodeGenCXX/cxx1y-deduced-return-type.cpp b/clang/test/CodeGenCXX/cxx1y-deduced-return-type.cpp
new file mode 100644
index 00000000000..edf673df4ae
--- /dev/null
+++ b/clang/test/CodeGenCXX/cxx1y-deduced-return-type.cpp
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -std=c++1y -emit-llvm %s -o - | FileCheck %s
+
+// CHECK: @x = global {{.*}} zeroinitializer
+
+// CHECK: define {{.*}} @_Z1fv
+inline auto f() {
+ int n = 0;
+ // CHECK: load i32
+ // CHECK: store i32
+ // CHECK: ret
+ return [=] () mutable { return ++n; };
+}
+
+auto x = f();
+
+template<typename T> auto *g(T t) { return t; }
+template<typename T> decltype(auto) h(T t) { return t; }
+
+// CHECK: define {{.*}} @_Z1zv
+void z() {
+ // CHECK: call {{.*}} @_Z1gIPZ1fvEUlvE_EPDaT_(
+ // CHECK: call {{.*}} @_Z1hIPZ1fvEUlvE_EDcT_(
+ g(&x);
+ h(&x);
+}
+
+auto i() { return [] {}; }
+// CHECK: define {{.*}} @_Z1jv
+auto j() {
+ // CHECK: call {{.*}} @"_Z1hIZ1ivE3$_0EDcT_"()
+ h(i());
+}
OpenPOWER on IntegriCloud