r181675 - Fix stack overflow in linkage computation when a function with a deduced return

Richard Smith richard-llvm at metafoo.co.uk
Sun May 12 16:17:59 PDT 2013


Author: rsmith
Date: Sun May 12 18:17:59 2013
New Revision: 181675

URL: http://llvm.org/viewvc/llvm-project?rev=181675&view=rev
Log:
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.)

Added:
    cfe/trunk/test/CodeGenCXX/cxx1y-deduced-return-type.cpp
Modified:
    cfe/trunk/lib/AST/Decl.cpp

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=181675&r1=181674&r2=181675&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Sun May 12 18:17:59 2013
@@ -660,9 +660,20 @@ static LinkageInfo getLVForNamespaceScop
     // 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

Added: cfe/trunk/test/CodeGenCXX/cxx1y-deduced-return-type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx1y-deduced-return-type.cpp?rev=181675&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/cxx1y-deduced-return-type.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/cxx1y-deduced-return-type.cpp Sun May 12 18:17:59 2013
@@ -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());
+}





More information about the cfe-commits mailing list