static LinkageInfo getLVForDecl(const NamedDecl *D,
LVComputationKind computation);
+static const FunctionDecl *getOutermostFunctionContext(const Decl *D) {
+ const FunctionDecl *Ret = NULL;
+ const DeclContext *DC = D->getDeclContext();
+ while (DC->getDeclKind() != Decl::TranslationUnit) {
+ const FunctionDecl *F = dyn_cast<FunctionDecl>(DC);
+ if (F)
+ Ret = F;
+ DC = DC->getParent();
+ }
+ return Ret;
+}
+
+/// Get the linkage and visibility to be used when this type is a template
+/// argument. This is normally just the linkage and visibility of the type,
+/// but for function local types we need to check the linkage and visibility
+/// of the function.
+static LinkageInfo getLIForTemplateTypeArgument(QualType T) {
+ LinkageInfo LI = T->getLinkageAndVisibility();
+ if (LI.getLinkage() != NoLinkage)
+ return LI;
+
+ const TagType *TT = dyn_cast<TagType>(T);
+ if (!TT)
+ return LI;
+
+ const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TT->getDecl());
+ if (!RD)
+ return LI;
+
+ const FunctionDecl *FD = getOutermostFunctionContext(RD);
+ if (!FD)
+ return LI;
+
+ if (!FD->isInlined())
+ return LI;
+
+ return FD->getLinkageAndVisibility();
+}
+
/// \brief Get the most restrictive linkage for the types and
/// declarations in the given template argument list.
///
continue;
case TemplateArgument::Type:
- LV.merge(arg.getAsType()->getLinkageAndVisibility());
+ LV.merge(getLIForTemplateTypeArgument(arg.getAsType()));
continue;
case TemplateArgument::Declaration:
--- /dev/null
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -std=c++11 -O1 -disable-llvm-optzns %s -o - | FileCheck %s
+
+// CHECK: define internal void @_ZN5test31fIZNS_1gEvE1SEEvT_(
+// CHECK: define linkonce_odr void @_ZN5test41fIZNS_1gILi1EEEPvvE1SEEvT_(
+// CHECK: define linkonce_odr void @_ZN5test51fIZNS_1gILi1EEEPvvE1S_1EEvT_(
+// CHECK: define internal void @_ZN5test71fIZZNS_1gEvEN1S1hEvE1T_4EEvv(
+// CHECK: define linkonce_odr void @_ZN5test61fIZZNS_1gEvEN1S1hE_2vE1T_3EEvv(
+// CHECK: define internal void @_ZN5test21fIZNS_L1gEvE1S_0EEvT_(
+// CHECK: define linkonce_odr void @_ZN5test11fIZNS_1gEvE1SEEvT_(
+
+namespace test1 {
+ template <typename T> void f(T) {}
+ inline void *g() {
+ struct S {
+ } s;
+ return reinterpret_cast<void *>(f<S>);
+ }
+ void *h() { return g(); }
+}
+
+namespace test2 {
+ template <typename T> void f(T) {}
+ static inline void *g() {
+ struct S {
+ } s;
+ return reinterpret_cast<void *>(f<S>);
+ }
+ void *h() { return g(); }
+}
+
+namespace test3 {
+ template <typename T> void f(T) {}
+ void *g() {
+ struct S {
+ } s;
+ return reinterpret_cast<void *>(f<S>);
+ }
+ void *h() { return g(); }
+}
+
+namespace test4 {
+ template <typename T> void f(T) {}
+ template <int N> inline void *g() {
+ struct S {
+ } s;
+ return reinterpret_cast<void *>(f<S>);
+ }
+ extern template void *g<1>();
+ template void *g<1>();
+}
+
+namespace test5 {
+ template <typename T> void f(T) {}
+ template <int N> inline void *g() {
+ struct S {
+ } s;
+ return reinterpret_cast<void *>(f<S>);
+ }
+ extern template void *g<1>();
+ void *h() { return g<1>(); }
+}
+
+namespace test6 {
+ template <typename T> void f() {}
+
+ inline void *g() {
+ struct S {
+ void *h() {
+ struct T {
+ };
+ return (void *)f<T>;
+ }
+ } s;
+ return s.h();
+ }
+
+ void *h() { return g(); }
+}
+
+namespace test7 {
+ template <typename T> void f() {}
+
+ void *g() {
+ struct S {
+ void *h() {
+ struct T {
+ };
+ return (void *)f<T>;
+ }
+ } s;
+ return s.h();
+ }
+
+ void *h() { return g(); }
+}