[PATCH] D20192: [Sema] Fix bug to do with lookup of template friend function in namespace

Erik Pilkington via cfe-commits cfe-commits at lists.llvm.org
Wed May 11 17:58:30 PDT 2016


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

Clang erroneously rejects the following code because it does not find the default argument for `makeType` :

```
namespace n {
  template <class> struct Type {
    template <class T> friend Type<T> makeType();
  };

  template <class T = void> Type<T> makeType();

  void f() {
    Type<void> t;
    n::makeType<>(); // Error, lookup finds wrong version of makeType
  }
} // end namespace n
```

The problem is that during instantiation of `Type<void>` on the previous line the default template argument version of `makeType` is incorrectly swapped out of `DeclContext::LookupPtr` for the friend version. This patch fixes that by disallowing the swap in `NamedDecl::declarationReplaces()`.

This patch looks like it's a fix for PR10856, PR18038, PR20877, and PR26962.


http://reviews.llvm.org/D20192

Files:
  lib/AST/Decl.cpp
  test/SemaTemplate/friend-template.cpp

Index: test/SemaTemplate/friend-template.cpp
===================================================================
--- test/SemaTemplate/friend-template.cpp
+++ test/SemaTemplate/friend-template.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s
 // PR5057
 namespace test0 {
   namespace std {
@@ -69,16 +69,13 @@
 
   template<typename T, T Value> struct X2a;
 
-  template<typename T, int Size> struct X2b;
+  template<typename T, int Size> struct X2b; // expected-note {{previous non-type template parameter with type 'int' is here}}
 
   template<typename T>
   class X3 {
     template<typename U, U Value> friend struct X2a;
 
-    // FIXME: the redeclaration note ends up here because redeclaration
-    // lookup ends up finding the friend target from X3<int>.
-    template<typename U, T Value> friend struct X2b; // expected-error {{template non-type parameter has a different type 'long' in template redeclaration}} \
-      // expected-note {{previous non-type template parameter with type 'int' is here}}
+    template<typename U, T Value> friend struct X2b; // expected-error {{template non-type parameter has a different type 'long' in template redeclaration}}
   };
 
   X3<int> x3i; // okay
@@ -297,14 +294,10 @@
   int n = C::D<void*>().f();
 
   struct F {
-    template<int> struct G;
+    template<int> struct G; // expected-note {{previous non-type template parameter with type 'int' is here}}
   };
   template<typename T> struct H {
-    // FIXME: As with cases above, the note here is on an unhelpful declaration,
-    // and should point to the declaration of G within F.
-    template<T> friend struct F::G; // \
-      // expected-error {{different type 'char' in template redeclaration}} \
-      // expected-note {{previous}}
+    template<T> friend struct F::G; // expected-error {{different type 'char' in template redeclaration}}
   };
   H<int> h1; // ok
   H<char> h2; // expected-note {{instantiation}}
@@ -329,3 +322,16 @@
     foo(b); // expected-note {{in instantiation}}
   }
 }
+
+namespace PR26962 {
+template <class> struct Type {
+  template <class T> friend Type<T> makeType();
+};
+
+template <class T = void> Type<T> makeType();
+
+void f() {
+  Type<void> t;
+  PR26962::makeType<>();
+}
+} // end PR26962
Index: lib/AST/Decl.cpp
===================================================================
--- lib/AST/Decl.cpp
+++ lib/AST/Decl.cpp
@@ -1520,6 +1520,10 @@
   if (OldD->isFromASTFile() && isFromASTFile())
     return false;
 
+  // Do not replace a declaration with a friend.
+  if (getFriendObjectKind() != FOK_None)
+    return false;
+
   // A kind mismatch implies that the declaration is not replaced.
   if (OldD->getKind() != getKind())
     return false;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D20192.56988.patch
Type: text/x-patch
Size: 2787 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160512/64f4af36/attachment.bin>


More information about the cfe-commits mailing list