sepavloff created this revision.
sepavloff added a reviewer: rsmith.
sepavloff added a subscriber: cfe-commits.

If a function template was defined in a friend declaration in a
template class, it was not instantiated because template definition
was not found.

http://reviews.llvm.org/D21767

Files:
  lib/AST/Decl.cpp
  lib/Sema/SemaTemplateInstantiate.cpp
  test/SemaTemplate/instantiate-friend-function.cpp

Index: test/SemaTemplate/instantiate-friend-function.cpp
===================================================================
--- /dev/null
+++ test/SemaTemplate/instantiate-friend-function.cpp
@@ -0,0 +1,63 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -S -triple i686-pc-linux-gnu -std=c++11 %s -o - | FileCheck %s
+// expected-no-diagnostics
+
+template<typename T> void func_01(T *x);
+template<typename T1>
+struct C1 {
+  template<typename T> friend void func_01(T *x) {}
+};
+
+C1<int> v1a;
+
+void use_01(int *x) {
+  func_01(x);
+}
+// CHECK: _Z7func_01IiEvPT_:
+
+
+template<typename T1>
+struct C2 {
+  template<typename T> friend void func_02(T *x) {}
+};
+
+C2<int> v2a;
+template<typename T> void func_02(T *x);
+
+void use_02(int *x) {
+  func_02(x);
+}
+// CHECK: _Z7func_02IiEvPT_:
+
+
+template<typename T1>
+struct C3a {
+  template<typename T> friend void func_03(T *x) {}
+};
+template<typename T1>
+struct C3b {
+  template<typename T> friend void func_03(T *x) {}
+};
+
+template<typename T> void func_03(T *x) {}
+
+void use_03(int *x) {
+  func_03(x);
+}
+// CHECK: _Z7func_03IiEvPT_:
+
+
+template<typename T> constexpr int func_04(const T x);
+template<typename T1>
+struct C4 {
+  template<typename T> friend constexpr int func_04(const T x) { return sizeof(T); }
+};
+
+C4<int> v4;
+
+void use_04(int *x) {
+  static_assert(func_04(short(122)) == sizeof(short), "Invalid calculation");
+  static_assert(func_04(122) == sizeof(int), "Invalid calculation");
+  static_assert(func_04(122L) == sizeof(long), "Invalid calculation");
+  static_assert(func_04(122LL) == sizeof(long long), "Invalid calculation");
+}
Index: lib/Sema/SemaTemplateInstantiate.cpp
===================================================================
--- lib/Sema/SemaTemplateInstantiate.cpp
+++ lib/Sema/SemaTemplateInstantiate.cpp
@@ -164,6 +164,13 @@
         RelativeToPrimary = false;
         continue;
       }
+
+      if (Pattern && Pattern->getFriendObjectKind() &&
+          Function->getDeclContext()->isFileContext()) {
+        Ctx = const_cast<DeclContext*>(Pattern->getLexicalDeclContext());
+        RelativeToPrimary = false;
+        continue;
+      }
     } else if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Ctx)) {
       if (ClassTemplateDecl *ClassTemplate = Rec->getDescribedClassTemplate()) {
         QualType T = ClassTemplate->getInjectedClassNameSpecialization();
Index: lib/AST/Decl.cpp
===================================================================
--- lib/AST/Decl.cpp
+++ lib/AST/Decl.cpp
@@ -3152,19 +3152,13 @@
            "template");
     return getPrimaryTemplate()->getTemplatedDecl();
   }
-  
+
   if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) {
-    while (Primary->getInstantiatedFromMemberTemplate()) {
-      // If we have hit a point where the user provided a specialization of
-      // this template, we're done looking.
-      if (Primary->isMemberSpecialization())
-        break;
-      Primary = Primary->getInstantiatedFromMemberTemplate();
-    }
-    
+    if (FunctionTemplateDecl *Def = Primary->getDefinition())
+      Primary = Def;
     return Primary->getTemplatedDecl();
-  } 
-    
+  }
+
   return getInstantiatedFromMemberFunction();
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to