Skip to content

fix: avoid infinite recursion in OverloadsFinalizer #897

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/lib/Metadata/Finalizers/OverloadsFinalizer.cpp
Original file line number Diff line number Diff line change
@@ -188,7 +188,8 @@ void
OverloadsFinalizer::
operator()(RecordInfo& I)
{
MRDOCS_CHECK_OR(!finalized_.contains(I.id));
MRDOCS_CHECK_OR(finalized_.emplace(I.id).second);

for (auto& b: I.Bases)
{
auto& BT = b.Type;
@@ -213,7 +214,6 @@ operator()(RecordInfo& I)
foldRecordMembers(I.Interface.Public.Records);
foldRecordMembers(I.Interface.Protected.Records);
foldRecordMembers(I.Interface.Private.Records);
finalized_.emplace(I.id);
}

} // clang::mrdocs
342 changes: 342 additions & 0 deletions test-files/golden-tests/config/overloads/bases.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,342 @@
= Reference
:mrdocs:

[#index]
== Global namespace

=== Types

[cols=1]
|===
| Name
| <<Base1,`Base1`>>
| <<Base2,`Base2`>>
| <<BaseBase1,`BaseBase1`>>
| <<BaseBase2,`BaseBase2`>>
| <<User,`User`>>
|===

[#Base1]
== Base1

=== Synopsis

Declared in `&lt;bases&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
struct Base1
: <<BaseBase1,BaseBase1>>;
----

=== Base Classes

[cols=2]
|===
| Name
| Description
| `<<BaseBase1,BaseBase1>>`
|
|===

=== Member Functions

[cols=2]
|===
| Name
| Description
| <<Base1-foo-0b,`foo`>>
|
|===

=== Derived Classes

[cols=2]
|===
| Name
| Description
| <<User,`User`>>
|
|===

[#Base1-foo-0b]
== <<Base1,Base1>>::foo

=== Synopses

Declared in `&lt;bases&period;cpp&gt;`


[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
void
<<BaseBase1-foo,foo>>(bool);
----

[.small]#<<BaseBase1-foo,_» more&period;&period;&period;_>>#


[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
void
<<Base1-foo-0a,foo>>(int);
----

[.small]#<<Base1-foo-0a,_» more&period;&period;&period;_>>#

[#BaseBase1-foo]
== <<BaseBase1,BaseBase1>>::foo

=== Synopsis

Declared in `&lt;bases&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
void
foo(bool);
----

[#Base1-foo-0a]
== <<Base1,Base1>>::foo

=== Synopsis

Declared in `&lt;bases&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
void
foo(int);
----

[#Base2]
== Base2

=== Synopsis

Declared in `&lt;bases&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
struct Base2;
----

=== Member Functions

[cols=1]
|===
| Name
| <<Base2-foo,`foo`>>
|===

=== Derived Classes

[cols=2]
|===
| Name
| Description
| <<User,`User`>>
|
|===

[#Base2-foo]
== <<Base2,Base2>>::foo

=== Synopsis

Declared in `&lt;bases&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
void
foo(double);
----

[#BaseBase1]
== BaseBase1

=== Synopsis

Declared in `&lt;bases&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
struct BaseBase1;
----

=== Member Functions

[cols=1]
|===
| Name
| <<BaseBase1-foo,`foo`>>
|===

=== Derived Classes

[cols=2]
|===
| Name
| Description
| <<Base1,`Base1`>>
|
|===

[#BaseBase1-foo]
== <<BaseBase1,BaseBase1>>::foo

=== Synopsis

Declared in `&lt;bases&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
void
foo(bool);
----

[#BaseBase2]
== BaseBase2

=== Synopsis

Declared in `&lt;bases&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
struct BaseBase2;
----

=== Member Functions

[cols=1]
|===
| Name
| <<BaseBase2-foo,`foo`>>
|===

[#BaseBase2-foo]
== <<BaseBase2,BaseBase2>>::foo

=== Synopsis

Declared in `&lt;bases&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
void
foo(bool);
----

[#User]
== User

=== Synopsis

Declared in `&lt;bases&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
struct User
: <<Base1,Base1>>
, <<Base2,Base2>>;
----

=== Base Classes

[cols=2]
|===
| Name
| Description
| `<<Base1,Base1>>`
|
| `<<Base2,Base2>>`
|
|===

=== Member Functions

[cols=2]
|===
| Name
| Description
| <<User-foo-0a,`foo`>>
|
|===

[#User-foo-0a]
== <<User,User>>::foo

=== Synopses

Declared in `&lt;bases&period;cpp&gt;`


[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
void
<<BaseBase1-foo,foo>>(bool);
----

[.small]#<<BaseBase1-foo,_» more&period;&period;&period;_>>#


[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
void
<<User-foo-0e,foo>>(int);
----

[.small]#<<User-foo-0e,_» more&period;&period;&period;_>>#


[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
void
<<Base2-foo,foo>>(double);
----

[.small]#<<Base2-foo,_» more&period;&period;&period;_>>#

[#BaseBase1-foo]
== <<BaseBase1,BaseBase1>>::foo

=== Synopsis

Declared in `&lt;bases&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
void
foo(bool);
----

[#User-foo-0e]
== <<User,User>>::foo

=== Synopsis

Declared in `&lt;bases&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
void
foo(int);
----

[#Base2-foo]
== <<Base2,Base2>>::foo

=== Synopsis

Declared in `&lt;bases&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
void
foo(double);
----


[.small]#Created with https://www.mrdocs.com[MrDocs]#
19 changes: 19 additions & 0 deletions test-files/golden-tests/config/overloads/bases.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
struct BaseBase1 {
void foo(bool);
};

struct BaseBase2 {
void foo(bool);
};

struct Base1 : public BaseBase1 {
void foo(int);
};

struct Base2 : private BaseBase2 {
void foo(double);
};

struct User : public Base1, Base2 {
void foo(int);
};
455 changes: 455 additions & 0 deletions test-files/golden-tests/config/overloads/bases.html

Large diffs are not rendered by default.

78 changes: 78 additions & 0 deletions test-files/golden-tests/config/overloads/bases.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<mrdocs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://github.com/cppalliance/mrdocs/raw/develop/mrdocs.rnc">
<namespace id="//////////////////////////8=">
<struct name="Base1" id="fPqJJd+3NXTlHHqKqhTMPfKXPhk=">
<file short-path="bases.cpp" source-path="bases.cpp" line="9" class="def"/>
<base>
<type id="WNoskSPtB/EjkTOC1fE2588OsIQ=" name="BaseBase1"/>
</base>
<function name="foo" id="kI8W/dQwFJOgtU9vfRbr0/kyFw8=">
<file short-path="bases.cpp" source-path="bases.cpp" line="2"/>
<param>
<type name="bool"/>
</param>
</function>
<function name="foo" id="pettg1q43gpnhKsMuQBvtJmJ4i0=">
<file short-path="bases.cpp" source-path="bases.cpp" line="10"/>
<param>
<type name="int"/>
</param>
</function>
</struct>
<struct name="Base2" id="aGuVLIfHL9M3lQss11/ePeZLwjI=">
<file short-path="bases.cpp" source-path="bases.cpp" line="13" class="def"/>
<function name="foo" id="DEUAxX1KbLLKE+6GfEA05ZDkSqA=">
<file short-path="bases.cpp" source-path="bases.cpp" line="14"/>
<param>
<type name="double"/>
</param>
</function>
</struct>
<struct name="BaseBase1" id="WNoskSPtB/EjkTOC1fE2588OsIQ=">
<file short-path="bases.cpp" source-path="bases.cpp" line="1" class="def"/>
<function name="foo" id="kI8W/dQwFJOgtU9vfRbr0/kyFw8=">
<file short-path="bases.cpp" source-path="bases.cpp" line="2"/>
<param>
<type name="bool"/>
</param>
</function>
</struct>
<struct name="BaseBase2" id="s/EWfEpXdF6RR1ThDQR/Znta2MY=">
<file short-path="bases.cpp" source-path="bases.cpp" line="5" class="def"/>
<function name="foo" id="tvmIVdxYnbBqwN0T6kaiQw32jEw=">
<file short-path="bases.cpp" source-path="bases.cpp" line="6"/>
<param>
<type name="bool"/>
</param>
</function>
</struct>
<struct name="User" id="58L4g3hYK4jqMumS0ZVZ318awvI=">
<file short-path="bases.cpp" source-path="bases.cpp" line="17" class="def"/>
<base>
<type id="fPqJJd+3NXTlHHqKqhTMPfKXPhk=" name="Base1"/>
</base>
<base>
<type id="aGuVLIfHL9M3lQss11/ePeZLwjI=" name="Base2"/>
</base>
<function name="foo" id="kI8W/dQwFJOgtU9vfRbr0/kyFw8=">
<file short-path="bases.cpp" source-path="bases.cpp" line="2"/>
<param>
<type name="bool"/>
</param>
</function>
<function name="foo" id="4FhRxjj+xNF4cJKPmgXi0HEIISo=">
<file short-path="bases.cpp" source-path="bases.cpp" line="18"/>
<param>
<type name="int"/>
</param>
</function>
<function name="foo" id="DEUAxX1KbLLKE+6GfEA05ZDkSqA=">
<file short-path="bases.cpp" source-path="bases.cpp" line="14"/>
<param>
<type name="double"/>
</param>
</function>
</struct>
</namespace>
</mrdocs>
180 changes: 180 additions & 0 deletions test-files/golden-tests/config/overloads/recursion.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
= Reference
:mrdocs:

[#index]
== Global namespace

=== Types

[cols=1]
|===
| Name
| <<Bar-0a,`Bar`>>
| <<Bar-01,`Bar&lt;T, Foo&lt;Args&period;&period;&period;&gt;&gt;`>>
| <<Foo-02,`Foo`>>
| <<Foo-0c,`Foo&lt;T[]&gt;`>>
|===

[#Bar-0a]
== Bar

=== Synopsis

Declared in `&lt;recursion&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
template&lt;
typename T,
typename List&gt;
struct Bar
: <<Bar-0a,Bar>>&lt;T, <<Foo-02,Foo>>&lt;List&gt;&gt;;
----

=== Base Classes

[cols=2]
|===
| Name
| Description
| `<<Bar-0a,Bar>>&lt;T, <<Foo-02,Foo>>&lt;List&gt;&gt;`
|
|===

=== Member Functions

[cols=1]
|===
| Name
| <<Bar-0a-baz,`baz`>>
|===

=== Derived Classes

[cols=2]
|===
| Name
| Description
| <<Bar-0a,`Bar`>>
|
|===

[#Bar-0a-baz]
== <<Bar-0a,Bar>>::baz

=== Synopsis

Declared in `&lt;recursion&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
void
baz(bool);
----

[#Bar-01]
== Bar&lt;T, <<Foo-02,Foo>>&lt;Args&period;&period;&period;&gt;&gt;

=== Synopsis

Declared in `&lt;recursion&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
template&lt;
typename T,
typename&period;&period;&period; Args&gt;
struct <<Bar-0a,Bar>>&lt;T, <<Foo-02,Foo>>&lt;Args&period;&period;&period;&gt;&gt;;
----

=== Member Functions

[cols=1]
|===
| Name
| <<Bar-01-baz,`baz`>>
|===

[#Bar-01-baz]
== <<Bar-01,Bar>>&lt;T, <<Foo-02,Foo>>&lt;Args&period;&period;&period;&gt;&gt;::baz

=== Synopsis

Declared in `&lt;recursion&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
void
baz(Args&period;&period;&period;);
----

[#Foo-02]
== Foo

=== Synopsis

Declared in `&lt;recursion&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
template&lt;typename T&gt;
struct Foo;
----

=== Types

[cols=1]
|===
| Name
| <<Foo-02-Type,`Type`>>
|===

[#Foo-02-Type]
== <<Foo-02,Foo>>::Type

=== Synopsis

Declared in `&lt;recursion&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
using Type = T;
----

[#Foo-0c]
== Foo&lt;T[]&gt;

=== Synopsis

Declared in `&lt;recursion&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
template&lt;
typename T,
int N&gt;
struct <<Foo-02,Foo>>&lt;T[]&gt;;
----

=== Types

[cols=1]
|===
| Name
| <<Foo-0c-Type,`Type`>>
|===

[#Foo-0c-Type]
== <<Foo-0c,Foo>>&lt;T[]&gt;::Type

=== Synopsis

Declared in `&lt;recursion&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
using Type = <<Foo-02,Foo>>&lt;T&gt;;
----


[.small]#Created with https://www.mrdocs.com[MrDocs]#
19 changes: 19 additions & 0 deletions test-files/golden-tests/config/overloads/recursion.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
template <typename T>
struct Foo {
using Type = T;
};

template <typename T, int N>
struct Foo<T[N]> {
using Type = Foo<T>;
};

template <typename T, typename List>
struct Bar : Bar<T, Foo<List>> {
void baz(bool) {}
};

template <typename T, typename... Args>
struct Bar<T, Foo<Args...>> {
void baz(Args...) {}
};
257 changes: 257 additions & 0 deletions test-files/golden-tests/config/overloads/recursion.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
<html lang="en">
<head>
<title>Reference</title>
</head>
<body>
<div>
<h1>Reference</h1>
<div>
<div>
<h2 id="index">Global namespace</h2>
</div>
<h2>Types</h2>
<table style="table-layout: fixed; width: 100%;">
<thead>
<tr>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="#Bar-0a"><code>Bar</code></a> </td></tr><tr>
<td><a href="#Bar-01"><code>Bar&lt;T, Foo&lt;Args...&gt;&gt;</code></a> </td></tr><tr>
<td><a href="#Foo-02"><code>Foo</code></a> </td></tr><tr>
<td><a href="#Foo-0c"><code>Foo&lt;T[]&gt;</code></a> </td></tr>
</tbody>
</table>

</div>
<div>
<div>
<h2 id="Bar-0a">Bar</h2>
</div>
<div>
<h3>Synopsis</h3>
<div>
Declared in <code>&lt;recursion.cpp&gt;</code></div>
<pre>
<code class="source-code cpp">
template&lt;
typename T,
typename List&gt;
struct Bar
: <a href="#Bar-0a">Bar</a>&lt;T, <a href="#Foo-02">Foo</a>&lt;List&gt;&gt;;
</code>
</pre>
</div>
<div>
<h2>Base Classes</h2>
<table>
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr><td><code><a href="#Bar-0a">Bar</a>&lt;T, <a href="#Foo-02">Foo</a>&lt;List&gt;&gt;</code></td><td><span></span></td></tr>
</tbody>
</table>
</div>
<h2>Member Functions</h2>
<table style="table-layout: fixed; width: 100%;">
<thead>
<tr>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="#Bar-0a-baz"><code>baz</code></a> </td></tr>
</tbody>
</table>



<div>
<h2>Derived Classes</h2>
<table>
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr><td><a href="#Bar-0a"><code>Bar</code></a>
</td><td><span></span></td></tr>
</tbody>
</table>
</div>
</div>
<div>
<div>
<h2 id="Bar-0a-baz"><a href="#Bar-0a">Bar</a>::baz</h2>
</div>
<div>
<h3>Synopsis</h3>
<div>
Declared in <code>&lt;recursion.cpp&gt;</code></div>
<pre>
<code class="source-code cpp">
void
baz(bool);
</code>
</pre>
</div>
</div>
<div>
<div>
<h2 id="Bar-01">Bar&lt;T, <a href="#Foo-02">Foo</a>&lt;Args...&gt;&gt;</h2>
</div>
<div>
<h3>Synopsis</h3>
<div>
Declared in <code>&lt;recursion.cpp&gt;</code></div>
<pre>
<code class="source-code cpp">
template&lt;
typename T,
typename... Args&gt;
struct <a href="#Bar-0a">Bar</a>&lt;T, <a href="#Foo-02">Foo</a>&lt;Args...&gt;&gt;;
</code>
</pre>
</div>
<h2>Member Functions</h2>
<table style="table-layout: fixed; width: 100%;">
<thead>
<tr>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="#Bar-01-baz"><code>baz</code></a> </td></tr>
</tbody>
</table>



</div>
<div>
<div>
<h2 id="Bar-01-baz"><a href="#Bar-01">Bar</a>&lt;T, <a href="#Foo-02">Foo</a>&lt;Args...&gt;&gt;::baz</h2>
</div>
<div>
<h3>Synopsis</h3>
<div>
Declared in <code>&lt;recursion.cpp&gt;</code></div>
<pre>
<code class="source-code cpp">
void
baz(Args...);
</code>
</pre>
</div>
</div>
<div>
<div>
<h2 id="Foo-02">Foo</h2>
</div>
<div>
<h3>Synopsis</h3>
<div>
Declared in <code>&lt;recursion.cpp&gt;</code></div>
<pre>
<code class="source-code cpp">
template&lt;typename T&gt;
struct Foo;
</code>
</pre>
</div>
<h2>Types</h2>
<table style="table-layout: fixed; width: 100%;">
<thead>
<tr>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="#Foo-02-Type"><code>Type</code></a> </td></tr>
</tbody>
</table>



</div>
<div>
<div>
<h2 id="Foo-02-Type"><a href="#Foo-02">Foo</a>::Type</h2>
</div>
<div>
<h3>Synopsis</h3>
<div>
Declared in <code>&lt;recursion.cpp&gt;</code></div>
<pre>
<code class="source-code cpp">
using Type = T;
</code>
</pre>
</div>
</div>
<div>
<div>
<h2 id="Foo-0c">Foo&lt;T[]&gt;</h2>
</div>
<div>
<h3>Synopsis</h3>
<div>
Declared in <code>&lt;recursion.cpp&gt;</code></div>
<pre>
<code class="source-code cpp">
template&lt;
typename T,
int N&gt;
struct <a href="#Foo-02">Foo</a>&lt;T[]&gt;;
</code>
</pre>
</div>
<h2>Types</h2>
<table style="table-layout: fixed; width: 100%;">
<thead>
<tr>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="#Foo-0c-Type"><code>Type</code></a> </td></tr>
</tbody>
</table>



</div>
<div>
<div>
<h2 id="Foo-0c-Type"><a href="#Foo-0c">Foo</a>&lt;T[]&gt;::Type</h2>
</div>
<div>
<h3>Synopsis</h3>
<div>
Declared in <code>&lt;recursion.cpp&gt;</code></div>
<pre>
<code class="source-code cpp">
using Type = <a href="#Foo-02">Foo</a>&lt;T&gt;;
</code>
</pre>
</div>
</div>

</div>
<div>
<h4>Created with <a href="https://www.mrdocs.com">MrDocs</a></h4>
</div>
</body>
</html>
59 changes: 59 additions & 0 deletions test-files/golden-tests/config/overloads/recursion.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<mrdocs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://github.com/cppalliance/mrdocs/raw/develop/mrdocs.rnc">
<namespace id="//////////////////////////8=">
<template>
<tparam name="T" class="type"/>
<tparam name="List" class="type"/>
<struct name="Bar" id="oiOZHFM9L3UNuv/ZP1KO/X/WFxk=">
<file short-path="recursion.cpp" source-path="recursion.cpp" line="11" class="def"/>
<base>
<type id="oiOZHFM9L3UNuv/ZP1KO/X/WFxk=" name="Bar&lt;T, Foo&lt;List&gt;&gt;"/>
</base>
<function name="baz" id="R+zZ+Qah/EEoHYHzeEv480dDn+E=">
<file short-path="recursion.cpp" source-path="recursion.cpp" line="13" class="def"/>
<param>
<type name="bool"/>
</param>
</function>
</struct>
</template>
<template class="partial" id="oiOZHFM9L3UNuv/ZP1KO/X/WFxk=">
<tparam name="T" class="type"/>
<tparam name="Args" class="type"/>
<targ class="type" type="T"/>
<targ class="type" type="Foo&lt;Args...&gt;"/>
<struct name="Bar" id="HZthCSegUxsxRDWrS4n44NYpUrw=">
<file short-path="recursion.cpp" source-path="recursion.cpp" line="17" class="def"/>
<function name="baz" id="8J4PEz0jtGpOCKo9m4JZyM0RsI0=">
<file short-path="recursion.cpp" source-path="recursion.cpp" line="18" class="def"/>
<param>
<type is-pack="1" name="Args"/>
</param>
</function>
</struct>
</template>
<template>
<tparam name="T" class="type"/>
<struct name="Foo" id="K9gGykwd7KRRGNi+R55g4t5hn7k=">
<file short-path="recursion.cpp" source-path="recursion.cpp" line="1" class="def"/>
<namespace-alias name="Type" id="Y9myx0jdUOQGNZJ1dpRZFOglUEk=">
<file short-path="recursion.cpp" source-path="recursion.cpp" line="3"/>
<type name="T"/>
</namespace-alias>
</struct>
</template>
<template class="partial" id="K9gGykwd7KRRGNi+R55g4t5hn7k=">
<tparam name="T" class="type"/>
<tparam name="N" class="non-type" type="int"/>
<targ class="type" type="T[N]"/>
<struct name="Foo" id="z6D6n01NNtYGa5S6Dbc0F0J+0A0=">
<file short-path="recursion.cpp" source-path="recursion.cpp" line="7" class="def"/>
<namespace-alias name="Type" id="seBsc+T9MsfquzqHM8pPzHndzDI=">
<file short-path="recursion.cpp" source-path="recursion.cpp" line="8"/>
<type id="K9gGykwd7KRRGNi+R55g4t5hn7k=" name="Foo&lt;T&gt;"/>
</namespace-alias>
</struct>
</template>
</namespace>
</mrdocs>