summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/AST/Decl.cpp6
-rw-r--r--clang/test/CodeGenCXX/linkage.cpp25
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(); }
+}
OpenPOWER on IntegriCloud