@@ -3363,6 +3363,30 @@ getFriendCountAndPosition(FriendDecl *FD) {
33633363 return std::make_tuple (FriendCount, *FriendPosition);
33643364}
33653365
3366+ // Returns the DeclContext of the underlying friend declaration/type. If that
3367+ // is a dependent type then the returned optional does not have a value.
3368+ static Optional<DeclContext *> getDCOfUnderlyingDecl (FriendDecl *FrD) {
3369+ if (NamedDecl *ND = FrD->getFriendDecl ())
3370+ return ND->getDeclContext ();
3371+ if (FrD->getFriendType ()) {
3372+ QualType Ty = FrD->getFriendType ()->getType ();
3373+ if (isa<ElaboratedType>(Ty))
3374+ Ty = cast<ElaboratedType>(Ty)->getNamedType ();
3375+ if (!Ty->isDependentType ()) {
3376+ if (const auto *RTy = dyn_cast<RecordType>(Ty))
3377+ return RTy->getAsCXXRecordDecl ()->getDeclContext ();
3378+ else if (const auto *SpecTy = dyn_cast<TemplateSpecializationType>(Ty))
3379+ return SpecTy->getAsCXXRecordDecl ()->getDeclContext ();
3380+ else if (const auto TypedefTy = dyn_cast<TypedefType>(Ty))
3381+ return TypedefTy->getDecl ()->getDeclContext ();
3382+ else
3383+ llvm_unreachable (" Unhandled type of friend" );
3384+ }
3385+ }
3386+ // DependentType
3387+ return Optional<DeclContext *>();
3388+ }
3389+
33663390ExpectedDecl ASTNodeImporter::VisitFriendDecl (FriendDecl *D) {
33673391 // Import the major distinguishing characteristics of a declaration.
33683392 DeclContext *DC, *LexicalDC;
@@ -3373,25 +3397,39 @@ ExpectedDecl ASTNodeImporter::VisitFriendDecl(FriendDecl *D) {
33733397 // FriendDecl is not a NamedDecl so we cannot use lookup.
33743398 // We try to maintain order and count of redundant friend declarations.
33753399 auto *RD = cast<CXXRecordDecl>(DC);
3376- FriendDecl *ImportedFriend = RD->getFirstFriend ();
33773400 SmallVector<FriendDecl *, 2 > ImportedEquivalentFriends;
33783401
3379- while (ImportedFriend) {
3402+ for (FriendDecl *ImportedFriend = RD->getFirstFriend (); ImportedFriend;
3403+ ImportedFriend = ImportedFriend->getNextFriend ()) {
3404+
3405+ // Compare the semantic DeclContext of the underlying declarations of the
3406+ // existing and the to be imported friend.
3407+ // Normally, lookup ensures this, but with friends we cannot use the lookup.
3408+ Optional<DeclContext *> ImportedFriendDC =
3409+ getDCOfUnderlyingDecl (ImportedFriend);
3410+ Optional<DeclContext *> FromFriendDC = getDCOfUnderlyingDecl (D);
3411+ if (FromFriendDC) { // The underlying friend type is not dependent.
3412+ ExpectedDecl FriendDCDeclOrErr = import (cast<Decl>(*FromFriendDC));
3413+ if (!FriendDCDeclOrErr)
3414+ return FriendDCDeclOrErr.takeError ();
3415+ DeclContext *FriendDC = cast<DeclContext>(*FriendDCDeclOrErr);
3416+ if (ImportedFriendDC != FriendDC)
3417+ continue ;
3418+ }
3419+
33803420 bool Match = false ;
3381- if (D->getFriendDecl () && ImportedFriend->getFriendDecl ()) {
3421+ if (D->getFriendDecl () && ImportedFriend->getFriendDecl ())
33823422 Match =
33833423 isStructuralMatch (D->getFriendDecl (), ImportedFriend->getFriendDecl (),
33843424 /* Complain=*/ false );
3385- } else if (D->getFriendType () && ImportedFriend->getFriendType ()) {
3425+ else if (D->getFriendType () && ImportedFriend->getFriendType ())
33863426 Match = Importer.IsStructurallyEquivalent (
33873427 D->getFriendType ()->getType (),
33883428 ImportedFriend->getFriendType ()->getType (), /* Complain=*/ false );
3389- }
33903429 if (Match)
33913430 ImportedEquivalentFriends.push_back (ImportedFriend);
3392-
3393- ImportedFriend = ImportedFriend->getNextFriend ();
33943431 }
3432+
33953433 std::tuple<unsigned int , unsigned int > CountAndPosition =
33963434 getFriendCountAndPosition (D);
33973435
0 commit comments