diff options
-rw-r--r-- | clang/lib/AST/Decl.cpp | 6 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/linkage.cpp | 25 |
2 files changed, 30 insertions, 1 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 80a32c5870d..a36fcf2507b 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -1049,8 +1049,12 @@ static LinkageInfo getLVForLocalDecl(const NamedDecl *D, return LinkageInfo::none(); const FunctionDecl *FD = getOutermostFunctionContext(D); - if (!FD || !FD->isInlined()) + if (!FD) + return LinkageInfo::none(); + + if (!FD->isInlined() && FD->getTemplateSpecializationKind() == TSK_Undeclared) return LinkageInfo::none(); + LinkageInfo LV = getLVForDecl(FD, computation); if (!isExternallyVisible(LV.getLinkage())) return LinkageInfo::none(); diff --git a/clang/test/CodeGenCXX/linkage.cpp b/clang/test/CodeGenCXX/linkage.cpp index 7f6188f4572..7c670293996 100644 --- a/clang/test/CodeGenCXX/linkage.cpp +++ b/clang/test/CodeGenCXX/linkage.cpp @@ -184,3 +184,28 @@ namespace test14 { } void h() { f(); } } + +namespace test15 { + // CHECK-DAG: define linkonce_odr void @_ZN6test153zedIZNS_3fooIiEEPvvE3bar_9EEvv( + template <class T> void zed() {} + template <class T> void *foo() { + class bar { + }; + return reinterpret_cast<void *>(zed<bar>); + } + void test() { foo<int>(); } +} + +namespace test16 { + // CHECK-DAG: define linkonce_odr void @_ZN6test163zedIZNS_3fooIiE3barEvE1S__10_EEvv( + template <class T> void zed() {} + template <class T> struct foo { + static void *bar(); + }; + template <class T> void *foo<T>::bar() { + class S { + }; + return reinterpret_cast<void *>(zed<S>); + } + void *test() { return foo<int>::bar(); } +} |