sepavloff updated this revision to Diff 106914.
sepavloff added a comment.

Aligned implementation with https://reviews.llvm.org/D21508.


https://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
@@ -165,6 +165,13 @@
         RelativeToPrimary = false;
         continue;
       }
+
+      if (Pattern && Pattern->getFriendObjectKind() != Decl::FOK_None &&
+          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
@@ -3249,7 +3249,23 @@
   }
   llvm_unreachable("All TSK values handled.");
 }
-   
+
+static FunctionTemplateDecl *getPatternFor(FunctionTemplateDecl *FTD) {
+  for (auto I : FTD->redecls()) {
+    auto D = cast<FunctionTemplateDecl>(I);
+    // If we have hit a point where the user provided a specialization of
+    // this template, we're done looking.
+    if (D->isMemberSpecialization())
+      return D;
+    if (D->isThisDeclarationADefinition())
+      return D;
+    if (FunctionTemplateDecl *Orig = D->getInstantiatedFromMemberTemplate())
+      if (FunctionTemplateDecl *Def = getPatternFor(Orig))
+        return Def;
+  }
+  return nullptr;
+}
+
 FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const {
   // Handle class scope explicit specialization special case.
   if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization) {
@@ -3274,14 +3290,8 @@
   }
 
   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 = getPatternFor(Primary))
+      Primary = Def;
     return getDefinitionOrSelf(Primary->getTemplatedDecl());
   } 
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D21767: Fix instantia... Serge Pavlov via Phabricator via cfe-commits

Reply via email to