diff --git a/src/lib/AST/ASTVisitor.cpp b/src/lib/AST/ASTVisitor.cpp
index 5783d37009..9a076f9c82 100644
--- a/src/lib/AST/ASTVisitor.cpp
+++ b/src/lib/AST/ASTVisitor.cpp
@@ -732,7 +732,24 @@ populate(
}
FriendInfo F;
populate(F, FD);
- I.Friends.push_back(std::move(F));
+ if (F.id != SymbolID::invalid)
+ {
+ Info* FI = this->find(F.id);
+ MRDOCS_CHECK_OR_CONTINUE(FI);
+ MRDOCS_CHECK_OR_CONTINUE(FI->Extraction != ExtractionMode::ImplementationDefined);
+ }
+ auto it = std::ranges::find_if(I.Friends, [&](FriendInfo const& FI)
+ {
+ return FI.id == F.id;
+ });
+ if (it != I.Friends.end())
+ {
+ merge(*it, std::move(F));
+ }
+ else
+ {
+ I.Friends.push_back(std::move(F));
+ }
}
}
}
diff --git a/test-files/golden-tests/symbols/record/friend-duplicate.adoc b/test-files/golden-tests/symbols/record/friend-duplicate.adoc
new file mode 100644
index 0000000000..8defca43c5
--- /dev/null
+++ b/test-files/golden-tests/symbols/record/friend-duplicate.adoc
@@ -0,0 +1,74 @@
+= Reference
+:mrdocs:
+
+[#index]
+== Global namespace
+
+=== Types
+
+[cols=1]
+|===
+| Name
+| link:#A[`A`]
+| link:#B[`B`]
+|===
+
+=== Functions
+
+[cols=1]
+|===
+| Name
+| link:#f[`f`]
+|===
+
+[#A]
+== A
+
+=== Synopsis
+
+Declared in `<friend‐duplicate.cpp>`
+
+[source,cpp,subs="verbatim,replacements,macros,-callouts"]
+----
+class A;
+----
+
+=== Friends
+
+[cols=2]
+|===
+| Name
+| Description
+| `link:#f[f]`
+|
+| `link:#B[B]`
+|
+|===
+
+[#B]
+== B
+
+=== Synopsis
+
+Declared in `<friend‐duplicate.cpp>`
+
+[source,cpp,subs="verbatim,replacements,macros,-callouts"]
+----
+class B;
+----
+
+[#f]
+== f
+
+=== Synopsis
+
+Declared in `<friend‐duplicate.cpp>`
+
+[source,cpp,subs="verbatim,replacements,macros,-callouts"]
+----
+void
+f();
+----
+
+
+[.small]#Created with https://www.mrdocs.com[MrDocs]#
diff --git a/test-files/golden-tests/symbols/record/friend-duplicate.cpp b/test-files/golden-tests/symbols/record/friend-duplicate.cpp
new file mode 100644
index 0000000000..1d68bafb23
--- /dev/null
+++ b/test-files/golden-tests/symbols/record/friend-duplicate.cpp
@@ -0,0 +1,14 @@
+class A
+{
+ friend class B;
+ friend class B;
+ friend class B;
+
+ friend void f();
+ friend void f();
+ friend void f();
+};
+
+class B {};
+
+void f();
\ No newline at end of file
diff --git a/test-files/golden-tests/symbols/record/friend-duplicate.html b/test-files/golden-tests/symbols/record/friend-duplicate.html
new file mode 100644
index 0000000000..f700e32048
--- /dev/null
+++ b/test-files/golden-tests/symbols/record/friend-duplicate.html
@@ -0,0 +1,118 @@
+
+
+Reference
+
+
+
+
Reference
+
+
+
Types
+
+
+
+| Name |
+
+
+
+
+A |
+B |
+
+
+
+
Functions
+
+
+
+
+
+
+
Synopsis
+
+Declared in <friend-duplicate.cpp>
+
+
+class A;
+
+
+
+
+
+
+
Friends
+
+
+
+| Name |
+Description |
+
+
+
+
+f |
+ |
+
+
+B |
+ |
+
+|===
+
+
+
+
+
+
+
+
Synopsis
+
+Declared in <friend-duplicate.cpp>
+
+
+class B;
+
+
+
+
+
+
+
+
+
+
Synopsis
+
+Declared in <friend-duplicate.cpp>
+
+
+void
+f();
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/test-files/golden-tests/symbols/record/friend-duplicate.xml b/test-files/golden-tests/symbols/record/friend-duplicate.xml
new file mode 100644
index 0000000000..fb92651f0d
--- /dev/null
+++ b/test-files/golden-tests/symbols/record/friend-duplicate.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test-files/golden-tests/symbols/record/friend-excluded.adoc b/test-files/golden-tests/symbols/record/friend-excluded.adoc
new file mode 100644
index 0000000000..53f678dc03
--- /dev/null
+++ b/test-files/golden-tests/symbols/record/friend-excluded.adoc
@@ -0,0 +1,74 @@
+= Reference
+:mrdocs:
+
+[#index]
+== Global namespace
+
+=== Types
+
+[cols=1]
+|===
+| Name
+| link:#A[`A`]
+| link:#B[`B`]
+|===
+
+=== Functions
+
+[cols=1]
+|===
+| Name
+| link:#f[`f`]
+|===
+
+[#A]
+== A
+
+=== Synopsis
+
+Declared in `<friend‐excluded.cpp>`
+
+[source,cpp,subs="verbatim,replacements,macros,-callouts"]
+----
+class A;
+----
+
+=== Friends
+
+[cols=2]
+|===
+| Name
+| Description
+| `link:#f[f]`
+|
+| `link:#B[B]`
+|
+|===
+
+[#B]
+== B
+
+=== Synopsis
+
+Declared in `<friend‐excluded.cpp>`
+
+[source,cpp,subs="verbatim,replacements,macros,-callouts"]
+----
+class B;
+----
+
+[#f]
+== f
+
+=== Synopsis
+
+Declared in `<friend‐excluded.cpp>`
+
+[source,cpp,subs="verbatim,replacements,macros,-callouts"]
+----
+void
+f();
+----
+
+
+[.small]#Created with https://www.mrdocs.com[MrDocs]#
diff --git a/test-files/golden-tests/symbols/record/friend-excluded.cpp b/test-files/golden-tests/symbols/record/friend-excluded.cpp
new file mode 100644
index 0000000000..d120da3ff4
--- /dev/null
+++ b/test-files/golden-tests/symbols/record/friend-excluded.cpp
@@ -0,0 +1,14 @@
+namespace detail {
+class impl;
+}
+
+class B {};
+
+void f();
+
+class A
+{
+ friend class detail::impl;
+ friend class B;
+ friend void f();
+};
diff --git a/test-files/golden-tests/symbols/record/friend-excluded.html b/test-files/golden-tests/symbols/record/friend-excluded.html
new file mode 100644
index 0000000000..ca9e5f7b9c
--- /dev/null
+++ b/test-files/golden-tests/symbols/record/friend-excluded.html
@@ -0,0 +1,118 @@
+
+
+Reference
+
+
+
+
Reference
+
+
+
Types
+
+
+
+| Name |
+
+
+
+
+A |
+B |
+
+
+
+
Functions
+
+
+
+
+
+
+
Synopsis
+
+Declared in <friend-excluded.cpp>
+
+
+class A;
+
+
+
+
+
+
+
Friends
+
+
+
+| Name |
+Description |
+
+
+
+
+f |
+ |
+
+
+B |
+ |
+
+|===
+
+
+
+
+
+
+
+
Synopsis
+
+Declared in <friend-excluded.cpp>
+
+
+class B;
+
+
+
+
+
+
+
+
+
+
Synopsis
+
+Declared in <friend-excluded.cpp>
+
+
+void
+f();
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/test-files/golden-tests/symbols/record/friend-excluded.xml b/test-files/golden-tests/symbols/record/friend-excluded.xml
new file mode 100644
index 0000000000..9463bb2224
--- /dev/null
+++ b/test-files/golden-tests/symbols/record/friend-excluded.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test-files/golden-tests/symbols/record/friend-excluded.yml b/test-files/golden-tests/symbols/record/friend-excluded.yml
new file mode 100644
index 0000000000..93de8e6887
--- /dev/null
+++ b/test-files/golden-tests/symbols/record/friend-excluded.yml
@@ -0,0 +1,2 @@
+implementation-defined:
+ - detail::**
\ No newline at end of file