llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Oleksandr Tarasiuk (a-tarasyuk)

<details>
<summary>Changes</summary>

Fixes #<!-- -->104057

---

Patch is 90.25 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/191268.diff


29 Files Affected:

- (modified) clang/include/clang/AST/ASTStructuralEquivalence.h (+2) 
- (modified) clang/include/clang/AST/DeclFriend.h (+28-89) 
- (modified) clang/include/clang/AST/DeclTemplate.h (+31-36) 
- (modified) clang/include/clang/AST/RecursiveASTVisitor.h (+3-2) 
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+2) 
- (modified) clang/include/clang/Sema/Sema.h (+3) 
- (modified) clang/include/clang/Sema/Template.h (+1-1) 
- (modified) clang/lib/AST/ASTImporter.cpp (+110-15) 
- (modified) clang/lib/AST/ASTStructuralEquivalence.cpp (+48) 
- (modified) clang/lib/AST/DeclFriend.cpp (+39-25) 
- (modified) clang/lib/AST/DeclPrinter.cpp (+5-12) 
- (modified) clang/lib/AST/DeclTemplate.cpp (+26-13) 
- (modified) clang/lib/Sema/Sema.cpp (+3-2) 
- (modified) clang/lib/Sema/SemaAccess.cpp (+329-50) 
- (modified) clang/lib/Sema/SemaDeclCXX.cpp (+133-76) 
- (modified) clang/lib/Sema/SemaTemplate.cpp (+6-8) 
- (modified) clang/lib/Sema/SemaTemplateInstantiate.cpp (+8-12) 
- (modified) clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (+64-38) 
- (modified) clang/lib/Serialization/ASTReaderDecl.cpp (+7-9) 
- (modified) clang/lib/Serialization/ASTWriterDecl.cpp (+7-7) 
- (modified) clang/test/CXX/class.access/class.friend/p3-cxx0x.cpp (+2-2) 
- (modified) clang/test/CXX/drs/cwg18xx.cpp (+5-6) 
- (modified) clang/test/CXX/drs/cwg19xx.cpp (+4-4) 
- (modified) clang/test/CXX/drs/cwg6xx.cpp (+10-7) 
- (modified) clang/test/CXX/temp/temp.decls/temp.friend/p5.cpp (+138-13) 
- (added) clang/test/CXX/temp/temp.decls/temp.friend/p6.cpp (+24) 
- (modified) clang/test/SemaCXX/many-template-parameter-lists.cpp (+4-2) 
- (modified) clang/test/SemaTemplate/GH71595.cpp (+3-3) 
- (modified) clang/test/SemaTemplate/ctad.cpp (+5-4) 


``````````diff
diff --git a/clang/include/clang/AST/ASTStructuralEquivalence.h 
b/clang/include/clang/AST/ASTStructuralEquivalence.h
index 6f82de1ae136d..89d7f8d6ba8ff 100644
--- a/clang/include/clang/AST/ASTStructuralEquivalence.h
+++ b/clang/include/clang/AST/ASTStructuralEquivalence.h
@@ -135,6 +135,8 @@ struct StructuralEquivalenceContext {
   /// \c VisitedDecls members) and can cause faulty equivalent results.
   bool IsEquivalent(Stmt *S1, Stmt *S2);
 
+  bool IsEquivalent(TemplateParameterList *TPL1, TemplateParameterList *TPL2);
+
   /// Find the index of the given anonymous struct/union within its
   /// context.
   ///
diff --git a/clang/include/clang/AST/DeclFriend.h 
b/clang/include/clang/AST/DeclFriend.h
index 1f8c210263677..2cd5a1af17fd8 100644
--- a/clang/include/clang/AST/DeclFriend.h
+++ b/clang/include/clang/AST/DeclFriend.h
@@ -15,20 +15,14 @@
 #define LLVM_CLANG_AST_DECLFRIEND_H
 
 #include "clang/AST/Decl.h"
-#include "clang/AST/DeclBase.h"
 #include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclTemplate.h"
-#include "clang/AST/ExternalASTSource.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/LLVM.h"
-#include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/PointerUnion.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Compiler.h"
-#include "llvm/Support/TrailingObjects.h"
 #include <cassert>
-#include <iterator>
 
 namespace clang {
 
@@ -49,9 +43,7 @@ class ASTContext;
 /// @endcode
 ///
 /// The semantic context of a friend decl is its declaring class.
-class FriendDecl final
-    : public Decl,
-      private llvm::TrailingObjects<FriendDecl, TemplateParameterList *> {
+class FriendDecl : public Decl {
   LLVM_DECLARE_VIRTUAL_ANCHOR_FUNCTION();
 
 public:
@@ -61,46 +53,35 @@ class FriendDecl final
   friend class CXXRecordDecl;
   friend class CXXRecordDecl::friend_iterator;
 
-  // The declaration that's a friend of this class.
-  FriendUnion Friend;
-
-  // A pointer to the next friend in the sequence.
-  LazyDeclPtr NextFriend;
-
-  // Location of the 'friend' specifier.
-  SourceLocation FriendLoc;
-
   // Location of the '...', if present.
   SourceLocation EllipsisLoc;
 
+  SourceLocation FriendLoc;
+
   /// True if this 'friend' declaration is unsupported.  Eventually we
   /// will support every possible friend declaration, but for now we
   /// silently ignore some and set this flag to authorize all access.
   LLVM_PREFERRED_TYPE(bool)
   unsigned UnsupportedFriend : 1;
 
-  // The number of "outer" template parameter lists in non-templatic
-  // (currently unsupported) friend type declarations, such as
-  //     template <class T> friend class A<T>::B;
-  unsigned NumTPLists : 31;
-
-  FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend,
-             SourceLocation FriendL, SourceLocation EllipsisLoc,
-             ArrayRef<TemplateParameterList *> FriendTypeTPLists)
-      : Decl(Decl::Friend, DC, L), Friend(Friend), FriendLoc(FriendL),
-        EllipsisLoc(EllipsisLoc), UnsupportedFriend(false),
-        NumTPLists(FriendTypeTPLists.size()) {
-    llvm::copy(FriendTypeTPLists, getTrailingObjects());
-  }
+protected:
+  // The declaration that's a friend of this class.
+  FriendUnion Friend;
 
-  FriendDecl(EmptyShell Empty, unsigned NumFriendTypeTPLists)
-      : Decl(Decl::Friend, Empty), UnsupportedFriend(false),
-        NumTPLists(NumFriendTypeTPLists) {}
+  LazyDeclPtr NextFriend;
+
+  FriendDecl(Kind K, DeclContext *DC, SourceLocation L, FriendUnion Friend,
+             SourceLocation FriendL, SourceLocation EllipsisLoc = {})
+      : Decl(K, DC, L), EllipsisLoc(EllipsisLoc), FriendLoc(FriendL),
+        UnsupportedFriend(false), Friend(Friend), NextFriend() {}
+
+  FriendDecl(Kind K, EmptyShell Empty)
+      : Decl(K, Empty), UnsupportedFriend(false) {}
 
   FriendDecl *getNextFriend() {
-    if (!NextFriend.isOffset())
-      return cast_or_null<FriendDecl>(NextFriend.get(nullptr));
-    return getNextFriendSlowCase();
+    if (NextFriend.isOffset())
+      return getNextFriendSlowCase();
+    return cast_or_null<FriendDecl>(NextFriend.get(nullptr));
   }
 
   FriendDecl *getNextFriendSlowCase();
@@ -109,14 +90,11 @@ class FriendDecl final
   friend class ASTDeclReader;
   friend class ASTDeclWriter;
   friend class ASTNodeImporter;
-  friend TrailingObjects;
 
-  static FriendDecl *
-  Create(ASTContext &C, DeclContext *DC, SourceLocation L, FriendUnion Friend_,
-         SourceLocation FriendL, SourceLocation EllipsisLoc = {},
-         ArrayRef<TemplateParameterList *> FriendTypeTPLists = {});
-  static FriendDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
-                                        unsigned FriendTypeNumTPLists);
+  static FriendDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
+                            FriendUnion Friend_, SourceLocation FriendL,
+                            SourceLocation EllipsisLoc = {});
+  static FriendDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
 
   /// If this friend declaration names an (untemplated but possibly
   /// dependent) type, return the type; otherwise return null.  This
@@ -126,58 +104,18 @@ class FriendDecl final
     return Friend.dyn_cast<TypeSourceInfo*>();
   }
 
-  unsigned getFriendTypeNumTemplateParameterLists() const {
-    return NumTPLists;
-  }
-
-  TemplateParameterList *getFriendTypeTemplateParameterList(unsigned N) const {
-    return getTrailingObjects(NumTPLists)[N];
-  }
-
   /// If this friend declaration doesn't name a type, return the inner
   /// declaration.
   NamedDecl *getFriendDecl() const {
     return Friend.dyn_cast<NamedDecl *>();
   }
 
-  /// Retrieves the location of the 'friend' keyword.
-  SourceLocation getFriendLoc() const {
-    return FriendLoc;
-  }
-
   /// Retrieves the location of the '...', if present.
   SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
 
-  /// Retrieves the source range for the friend declaration.
-  SourceRange getSourceRange() const override LLVM_READONLY {
-    if (TypeSourceInfo *TInfo = getFriendType()) {
-      SourceLocation StartL = (NumTPLists == 0)
-                                  ? getFriendLoc()
-                                  : getTrailingObjects()[0]->getTemplateLoc();
-      SourceLocation EndL = isPackExpansion() ? getEllipsisLoc()
-                                              : 
TInfo->getTypeLoc().getEndLoc();
-      return SourceRange(StartL, EndL);
-    }
-
-    if (isPackExpansion())
-      return SourceRange(getFriendLoc(), getEllipsisLoc());
-
-    if (NamedDecl *ND = getFriendDecl()) {
-      if (const auto *FD = dyn_cast<FunctionDecl>(ND))
-        return FD->getSourceRange();
-      if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(ND))
-        return FTD->getSourceRange();
-      if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND))
-        return CTD->getSourceRange();
-      if (const auto *DD = dyn_cast<DeclaratorDecl>(ND)) {
-        if (DD->getOuterLocStart() != DD->getInnerLocStart())
-          return DD->getSourceRange();
-      }
-      return SourceRange(getFriendLoc(), ND->getEndLoc());
-    }
-
-    return SourceRange(getFriendLoc(), getLocation());
-  }
+  SourceLocation getFriendLoc() const { return FriendLoc; }
+
+  SourceRange getSourceRange() const override LLVM_READONLY;
 
   /// Determines if this friend kind is unsupported.
   bool isUnsupportedFriend() const {
@@ -191,9 +129,10 @@ class FriendDecl final
 
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
-  static bool classofKind(Kind K) { return K == Decl::Friend; }
+  static bool classofKind(Kind K) {
+    return K == Decl::Friend || K == Decl::FriendTemplate;
+  }
 };
-
 /// An iterator over the friend declarations of a class.
 class CXXRecordDecl::friend_iterator {
   friend class CXXRecordDecl;
diff --git a/clang/include/clang/AST/DeclTemplate.h 
b/clang/include/clang/AST/DeclTemplate.h
index a4a1bb9c13c79..1653c26910b8b 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -19,6 +19,7 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclBase.h"
 #include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclFriend.h"
 #include "clang/AST/DeclarationName.h"
 #include "clang/AST/Redeclarable.h"
 #include "clang/AST/TemplateBase.h"
@@ -2473,42 +2474,43 @@ class ClassTemplateDecl : public 
RedeclarableTemplateDecl {
 ///
 /// \note This class is not currently in use.  All of the above
 /// will yield a FriendDecl, not a FriendTemplateDecl.
-class FriendTemplateDecl : public Decl {
-  virtual void anchor();
-
-public:
-  using FriendUnion = llvm::PointerUnion<NamedDecl *,TypeSourceInfo *>;
+class FriendTemplateDecl final
+    : public FriendDecl,
+      private llvm::TrailingObjects<FriendTemplateDecl,
+                                    TemplateParameterList *> {
+  void anchor() override;
 
 private:
-  // The number of template parameters;  always non-zero.
-  unsigned NumParams = 0;
+  unsigned NumTPLists : 31;
 
-  // The parameter list.
-  TemplateParameterList **Params = nullptr;
-
-  // The declaration that's a friend of this class.
-  FriendUnion Friend;
-
-  // Location of the 'friend' specifier.
-  SourceLocation FriendLoc;
-
-  FriendTemplateDecl(DeclContext *DC, SourceLocation Loc,
-                     TemplateParameterList **Params, unsigned NumParams,
-                     FriendUnion Friend, SourceLocation FriendLoc)
-      : Decl(Decl::FriendTemplate, DC, Loc), NumParams(NumParams),
-        Params(Params), Friend(Friend), FriendLoc(FriendLoc) {}
+  FriendTemplateDecl(DeclContext *DC, SourceLocation Loc, FriendUnion Friend,
+                     SourceLocation FriendLoc, SourceLocation EllipsisLoc,
+                     ArrayRef<TemplateParameterList *> FriendTypeTPLists)
+      : FriendDecl(Decl::FriendTemplate, DC, Loc, Friend, FriendLoc,
+                   EllipsisLoc),
+        NumTPLists(FriendTypeTPLists.size()) {
+    llvm::copy(FriendTypeTPLists, getTrailingObjects());
+  }
 
-  FriendTemplateDecl(EmptyShell Empty) : Decl(Decl::FriendTemplate, Empty) {}
+  FriendTemplateDecl(EmptyShell Empty, unsigned NumFriendTypeTPLists)
+      : FriendDecl(Decl::FriendTemplate, Empty),
+        NumTPLists(NumFriendTypeTPLists) {}
 
 public:
   friend class ASTDeclReader;
+  friend class ASTDeclWriter;
+  friend TrailingObjects;
 
   static FriendTemplateDecl *
   Create(ASTContext &Context, DeclContext *DC, SourceLocation Loc,
-         MutableArrayRef<TemplateParameterList *> Params, FriendUnion Friend,
-         SourceLocation FriendLoc);
+         FriendUnion Friend, SourceLocation FriendLoc,
+         ArrayRef<TemplateParameterList *> FriendTypeTPLists = {},
+         SourceLocation EllipsisLoc = {});
 
-  static FriendTemplateDecl *CreateDeserialized(ASTContext &C, GlobalDeclID 
ID);
+  static FriendTemplateDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
+                                                unsigned FriendTypeNumTPLists);
+
+  SourceRange getSourceRange() const override LLVM_READONLY;
 
   /// If this friend declaration names a templated type (or
   /// a dependent member type of a templated type), return that
@@ -2524,19 +2526,12 @@ class FriendTemplateDecl : public Decl {
     return Friend.dyn_cast<NamedDecl*>();
   }
 
-  /// Retrieves the location of the 'friend' keyword.
-  SourceLocation getFriendLoc() const {
-    return FriendLoc;
+  TemplateParameterList *getFriendTypeTemplateParameterList(unsigned N) const {
+    assert(N < NumTPLists);
+    return getTrailingObjects()[N];
   }
 
-  TemplateParameterList *getTemplateParameterList(unsigned i) const {
-    assert(i <= NumParams);
-    return Params[i];
-  }
-
-  unsigned getNumTemplateParameters() const {
-    return NumParams;
-  }
+  unsigned getFriendTypeNumTemplateParameterLists() const { return NumTPLists; 
}
 
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h 
b/clang/include/clang/AST/RecursiveASTVisitor.h
index 1a14dd2c666b5..cd4fd5b598d4a 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -1727,8 +1727,9 @@ DEF_TRAVERSE_DECL(FriendTemplateDecl, {
     TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc()));
   else
     TRY_TO(TraverseDecl(D->getFriendDecl()));
-  for (unsigned I = 0, E = D->getNumTemplateParameters(); I < E; ++I) {
-    TemplateParameterList *TPL = D->getTemplateParameterList(I);
+  for (unsigned I = 0, E = D->getFriendTypeNumTemplateParameterLists(); I < E;
+       ++I) {
+    TemplateParameterList *TPL = D->getFriendTypeTemplateParameterList(I);
     for (TemplateParameterList::iterator ITPL = TPL->begin(), ETPL = 
TPL->end();
          ITPL != ETPL; ++ITPL) {
       TRY_TO(TraverseDecl(*ITPL));
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 4cd4efc55c416..f7e3d8af1dbb8 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1921,6 +1921,8 @@ def err_friend_template_decl_multiple_specifiers: Error<
   "a friend declaration that befriends a template must contain exactly one 
type-specifier">;
 def friend_template_decl_malformed_pack_expansion : Error<
   "friend declaration expands pack %0 that is declared it its own template 
parameter list">;
+def err_dependent_friend_not_member : Error<
+  "friend declaration does not name a member of a class template 
specialization">;
 
 def err_invalid_base_in_interface : Error<
   "interface type cannot inherit from "
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 760555d9c8b9b..544d892c1535c 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -12012,6 +12012,9 @@ class Sema final : public SemaBase {
   bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous);
   void CompleteMemberSpecialization(NamedDecl *Member, LookupResult &Previous);
 
+  bool CheckDependentFriend(SourceLocation Loc, NestedNameSpecifier NNS,
+                            TemplateParameterList *FPL);
+
   // Explicit instantiation of a class template specialization
   DeclResult ActOnExplicitInstantiation(
       Scope *S, SourceLocation ExternLoc, SourceLocation TemplateLoc,
diff --git a/clang/include/clang/Sema/Template.h 
b/clang/include/clang/Sema/Template.h
index b0170c21feb1a..62b1c16de82c1 100644
--- a/clang/include/clang/Sema/Template.h
+++ b/clang/include/clang/Sema/Template.h
@@ -715,7 +715,7 @@ enum class TemplateSubstitutionKind : char {
 
     // Helper functions for instantiating methods.
     TypeSourceInfo *SubstFunctionType(FunctionDecl *D,
-                             SmallVectorImpl<ParmVarDecl *> &Params);
+                                      SmallVectorImpl<ParmVarDecl *> &Params);
     bool InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl);
     bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl);
 
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 41ba98c53247d..782e4d710599c 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -537,6 +537,7 @@ namespace clang {
     ExpectedDecl VisitFieldDecl(FieldDecl *D);
     ExpectedDecl VisitIndirectFieldDecl(IndirectFieldDecl *D);
     ExpectedDecl VisitFriendDecl(FriendDecl *D);
+    ExpectedDecl VisitFriendTemplateDecl(FriendTemplateDecl *D);
     ExpectedDecl VisitObjCIvarDecl(ObjCIvarDecl *D);
     ExpectedDecl VisitVarDecl(VarDecl *D);
     ExpectedDecl VisitImplicitParamDecl(ImplicitParamDecl *D);
@@ -4541,10 +4542,40 @@ static bool IsEquivalentFriend(ASTImporter &Importer, 
FriendDecl *FD1,
       Importer.getToContext().getLangOpts(), FD1->getASTContext(),
       FD2->getASTContext(), NonEquivalentDecls,
       StructuralEquivalenceKind::Default,
-      /* StrictTypeSpelling = */ false, /* Complain = */ false);
+      /*StrictTypeSpelling=*/false, /*Complain=*/false);
   return Ctx.IsEquivalent(FD1, FD2);
 }
 
+static bool IsEquivalentFriend(ASTImporter &Importer, FriendTemplateDecl *FTD1,
+                               FriendTemplateDecl *FTD2) {
+  if (FTD1->getFriendTypeNumTemplateParameterLists() !=
+      FTD2->getFriendTypeNumTemplateParameterLists())
+    return false;
+
+  ASTImporter::NonEquivalentDeclSet NonEquivalentDecls;
+  StructuralEquivalenceContext Ctx(
+      Importer.getToContext().getLangOpts(), FTD1->getASTContext(),
+      FTD2->getASTContext(), NonEquivalentDecls,
+      StructuralEquivalenceKind::Default, /*StrictTypeSpelling=*/false,
+      /*Complain=*/false);
+
+  for (unsigned I = 0, N = FTD1->getFriendTypeNumTemplateParameterLists();
+       I != N; ++I) {
+    if (!Ctx.IsEquivalent(FTD1->getFriendTypeTemplateParameterList(I),
+                          FTD2->getFriendTypeTemplateParameterList(I)))
+      return false;
+  }
+
+  if ((!FTD1->getFriendType()) != (!FTD2->getFriendType()))
+    return false;
+
+  if (const TypeSourceInfo *TSI = FTD1->getFriendType())
+    return Importer.IsStructurallyEquivalent(
+        TSI->getType(), FTD2->getFriendType()->getType(), /*Complain=*/false);
+
+  return Ctx.IsEquivalent(FTD1, FTD2);
+}
+
 static FriendCountAndPosition getFriendCountAndPosition(ASTImporter &Importer,
                                                         FriendDecl *FD) {
   unsigned int FriendCount = 0;
@@ -4561,7 +4592,6 @@ static FriendCountAndPosition 
getFriendCountAndPosition(ASTImporter &Importer,
   }
 
   assert(FriendPosition && "Friend decl not found in own parent.");
-
   return {FriendCount, *FriendPosition};
 }
 
@@ -4576,9 +4606,11 @@ ExpectedDecl ASTNodeImporter::VisitFriendDecl(FriendDecl 
*D) {
   // We try to maintain order and count of redundant friend declarations.
   const auto *RD = cast<CXXRecordDecl>(DC);
   SmallVector<FriendDecl *, 2> ImportedEquivalentFriends;
-  for (FriendDecl *ImportedFriend : RD->friends())
-    if (IsEquivalentFriend(Importer, D, ImportedFriend))
-      ImportedEquivalentFriends.push_back(ImportedFriend);
+  for (FriendDecl *ImportedFriend : RD->friends()) {
+    if (ImportedFriend->getKind() == Decl::Friend &&
+        IsEquivalentFriend(Importer, D, cast<FriendDecl>(ImportedFriend)))
+      ImportedEquivalentFriends.push_back(cast<FriendDecl>(ImportedFriend));
+  }
 
   FriendCountAndPosition CountAndPosition =
       getFriendCountAndPosition(Importer, D);
@@ -4609,15 +4641,6 @@ ExpectedDecl ASTNodeImporter::VisitFriendDecl(FriendDecl 
*D) {
       return TSIOrErr.takeError();
   }
 
-  SmallVector<TemplateParameterList *, 1> ToTPLists(D->NumTPLists);
-  auto **FromTPLists = D->getTrailingObjects();
-  for (unsigned I = 0; I < D->NumTPLists; I++) {
-    if (auto ListOrErr = import(FromTPLists[I]))
-      ToTPLists[I] = *ListOrErr;
-    else
-      return ListOrErr.takeError();
-  }
-
   auto LocationOrErr = import(D->getLocation());
   if (!LocationOrErr)
     return LocationOrErr.takeError();
@@ -4631,7 +4654,7 @@ ExpectedDecl ASTNodeImporter::VisitFriendDecl(FriendDecl 
*D) {
   FriendDecl *FrD;
   if (GetImportedOrCreateDecl(FrD, D, Importer.getToContext(), DC,
                               *LocationOrErr, ToFU, *FriendLocOrErr,
-                              *EllipsisLocOrErr, ToTPLists))
+                              *EllipsisLocOrErr))
     return FrD;
 
   FrD->setAccess(D->getAccess());
@@ -4640,6 +4663,78 @@ ExpectedDecl ASTNodeImporter::VisitFriendDecl(FriendDecl 
*D) {
   return FrD;
 }
 
+ExpectedDecl ASTNodeImporter::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
+  DeclContext *DC, *LexicalDC;
+  if (Error Err = ImportDeclContext(D, DC, LexicalDC))
+    return std::move(Err);
+
+  const auto *RD = cast<CXXRecordDecl>(DC);
+  SmallVector<FriendTemplateDecl *, 2> ImportedEquivalentFriends;
+  for (FriendDecl *ImportedFriend : RD->friends()) {
+    if (isa<FriendTemplateDecl>(ImportedFriend) &&
+        IsEquivalentFriend(Importer, D,
+                           cast<FriendTemplateDecl>(ImportedFriend)))
+      ImportedEquivalentFriends.push_back(
+          cast<FriendTemplateDecl>(ImportedFriend));
+  }
+
+  FriendCountAndPosition CountAndPosition =
+      getFriendCountAndPosition(Importer, D);
+  assert(ImportedEquivalentFriends.size() <= CountAndPosition.TotalCount &&
+         "Class with non-...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/191268
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to