[PATCH] D31540: Prefer non-friend to friend in in redeclaration chain

Yaron Keren via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Mar 31 09:12:57 PDT 2017


yaron.keren created this revision.

Address http://bugs.llvm.org/pr30994 so that a non-friend can properly replace a friend, and a visible friend can properly replace an invisible friend but not vice verse. This also fixes two FIXME in SemaTemplate/friend-template.cpp.


Repository:
  rL LLVM

https://reviews.llvm.org/D31540

Files:
  tools/clang/include/clang/AST/DeclBase.h
  tools/clang/lib/AST/Decl.cpp
  tools/clang/lib/AST/DeclBase.cpp
  tools/clang/test/SemaTemplate/friend-template.cpp


Index: tools/clang/test/SemaTemplate/friend-template.cpp
===================================================================
--- tools/clang/test/SemaTemplate/friend-template.cpp
+++ tools/clang/test/SemaTemplate/friend-template.cpp
@@ -68,17 +68,12 @@
   Foo<int> foo;
 
   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 +292,11 @@
   int n = C::D<void*>().f();
 
   struct F {
-    template<int> struct G;
+    template<int> struct G; // expected-note {{previous}}
   };
   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}}
+      // expected-error {{different type 'char' in template redeclaration}}
   };
   H<int> h1; // ok
   H<char> h2; // expected-note {{instantiation}}
Index: tools/clang/lib/AST/DeclBase.cpp
===================================================================
--- tools/clang/lib/AST/DeclBase.cpp
+++ tools/clang/lib/AST/DeclBase.cpp
@@ -861,6 +861,21 @@
   return Ty->getAs<FunctionType>();
 }
 
+bool Decl::isThisDeclarationADefinition() const {
+  if (auto *TD = dyn_cast<TagDecl>(this))
+    return TD->isThisDeclarationADefinition();
+  if (auto *FD = dyn_cast<FunctionDecl>(this))
+    return FD->isThisDeclarationADefinition();
+  if (auto *VD = dyn_cast<VarDecl>(this))
+    return VD->isThisDeclarationADefinition();
+  if (auto *CTD = dyn_cast<ClassTemplateDecl>(this))
+    return CTD->isThisDeclarationADefinition();
+  if (auto *FTD = dyn_cast<FunctionTemplateDecl>(this))
+    return FTD->isThisDeclarationADefinition();
+  if (auto *VTD = dyn_cast<VarTemplateDecl>(this))
+    return VTD->isThisDeclarationADefinition();
+  return false;
+}
 
 /// Starting at a given context (a Decl or DeclContext), look for a
 /// code context that is not a closure (a lambda, block, etc.).
Index: tools/clang/lib/AST/Decl.cpp
===================================================================
--- tools/clang/lib/AST/Decl.cpp
+++ tools/clang/lib/AST/Decl.cpp
@@ -1536,6 +1536,10 @@
   if (isa<ObjCMethodDecl>(this))
     return false;
 
+  if (getFriendObjectKind() > OldD->getFriendObjectKind() &&
+      !isThisDeclarationADefinition())
+    return false;
+
   // For parameters, pick the newer one. This is either an error or (in
   // Objective-C) permitted as an extension.
   if (isa<ParmVarDecl>(this))
Index: tools/clang/include/clang/AST/DeclBase.h
===================================================================
--- tools/clang/include/clang/AST/DeclBase.h
+++ tools/clang/include/clang/AST/DeclBase.h
@@ -417,6 +417,8 @@
     return const_cast<Decl*>(this)->getTranslationUnitDecl();
   }
 
+  bool isThisDeclarationADefinition() const;
+
   bool isInAnonymousNamespace() const;
 
   bool isInStdNamespace() const;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D31540.93654.patch
Type: text/x-patch
Size: 3798 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170331/8a7ad29b/attachment.bin>


More information about the cfe-commits mailing list