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
