Skip to content

Commit 8d8a007

Browse files
committed
feat: support anonymous union members
1 parent 1e162bf commit 8d8a007

File tree

8 files changed

+105
-5
lines changed

8 files changed

+105
-5
lines changed

include/mrdocs/Metadata/Field.hpp

+3
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ struct FieldInfo
3838
*/
3939
ExprInfo Default;
4040

41+
/** Whether the field is a variant member */
42+
bool IsVariant = false;
43+
4144
/** Whether the field is declared mutable */
4245
bool IsMutable = false;
4346

Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{{#if (eq kind "overload")}}{{>special-name-suffix (front members)~}}
22
{{else if (eq kind "function")~}}
33
{{#if (eq class "constructor")}}[.small]#[constructor]#
4-
{{~else if (eq class "destructor")~}}[.small]#[destructor]#
4+
{{~else if (eq class "destructor")}}[.small]#[destructor]#
55
{{~/if~}}
6+
{{else if (eq kind "field")~}}
7+
{{#if isVariant}}[.small]#[variant member]#{{/if~}}
68
{{/if}}

src/lib/AST/ASTVisitor.cpp

+44-4
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,11 @@ class ASTVisitor
547547
if(DC->isFileContext() ||
548548
DC->isFunctionOrMethod())
549549
break;
550+
551+
if(auto* RD = dyn_cast<CXXRecordDecl>(DC);
552+
RD && RD->isAnonymousStructOrUnion())
553+
continue;
554+
550555
// when extracting dependencies, we want to extract
551556
// all members of the containing class, not just this one
552557
if(auto* TD = dyn_cast<TagDecl>(DC))
@@ -1519,6 +1524,16 @@ class ASTVisitor
15191524
return false;
15201525
}
15211526

1527+
// don't extract anonymous unions
1528+
if(const auto* RD = dyn_cast<RecordDecl>(D);
1529+
RD && RD->isAnonymousStructOrUnion())
1530+
return false;
1531+
1532+
// don't extract implicitly generated declarations
1533+
// (except for IndirectFieldDecls)
1534+
if(D->isImplicit() && !isa<IndirectFieldDecl>(D))
1535+
return false;
1536+
15221537
if (!config_->input.include.empty())
15231538
{
15241539
// Get filename
@@ -1959,10 +1974,15 @@ class ASTVisitor
19591974
{
19601975
switch(D->getKind())
19611976
{
1977+
case Decl::CXXRecord:
1978+
// we treat anonymous unions as "transparent"
1979+
if(auto* RD = cast<CXXRecordDecl>(D);
1980+
RD->isAnonymousStructOrUnion())
1981+
break;
1982+
[[fallthrough]];
19621983
case Decl::TranslationUnit:
19631984
case Decl::Namespace:
19641985
case Decl::Enum:
1965-
case Decl::CXXRecord:
19661986
case Decl::ClassTemplateSpecialization:
19671987
case Decl::ClassTemplatePartialSpecialization:
19681988
return D;
@@ -2373,6 +2393,8 @@ class ASTVisitor
23732393

23742394
I.Type = buildTypeInfo(D->getType());
23752395

2396+
I.IsVariant = D->getParent()->isUnion();
2397+
23762398
I.IsMutable = D->isMutable();
23772399

23782400
if(const Expr* E = D->getInClassInitializer())
@@ -2793,6 +2815,17 @@ class ASTVisitor
27932815
void
27942816
traverse(FieldDecl*);
27952817

2818+
/** Traverse a member of an anonymous union.
2819+
2820+
This function is called by traverseDecl to traverse
2821+
a member of an anonymous union.
2822+
2823+
A IndirectFieldDecl inherits from ValueDecl.
2824+
2825+
*/
2826+
void
2827+
traverse(IndirectFieldDecl*);
2828+
27962829
/** Traverse a concept definition
27972830
27982831
This function is called by traverseDecl to traverse a
@@ -3061,6 +3094,14 @@ traverse(FieldDecl* D)
30613094
auto [I, created] = *exp;
30623095
buildField(I, created, D);
30633096
}
3097+
3098+
void
3099+
ASTVisitor::
3100+
traverse(IndirectFieldDecl* D)
3101+
{
3102+
traverse(D->getAnonField());
3103+
}
3104+
30643105
//------------------------------------------------
30653106
// ConceptDecl
30663107

@@ -3348,9 +3389,8 @@ traverseDecl(
33483389
{
33493390
MRDOCS_ASSERT(D);
33503391

3351-
// Decl had a semantic error or is implicitly
3352-
// generated by the implementation
3353-
if(D->isInvalidDecl() || D->isImplicit())
3392+
// Decl had a semantic error
3393+
if(D->isInvalidDecl())
33543394
return;
33553395

33563396
SymbolFilter::FilterScope scope(symbolFilter_);

src/lib/Gen/xml/XMLWriter.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,7 @@ writeField(
566566
{"id", "is-mutable"}
567567
});
568568

569+
writeAttr(I.IsVariant, "is-variant", tags_);
569570
writeAttr(I.IsMaybeUnused, "maybe-unused", tags_);
570571
writeAttr(I.IsDeprecated, "deprecated", tags_);
571572
writeAttr(I.HasNoUniqueAddress, "no-unique-address", tags_);

src/lib/Metadata/DomMetadata.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -851,6 +851,7 @@ DomInfo<T>::construct() const
851851
{ "default", dom::stringOrNull(I_.Default.Written) },
852852
{ "isMaybeUnused", I_.IsMaybeUnused },
853853
{ "isDeprecated", I_.IsDeprecated },
854+
{ "isVariant", I_.IsVariant },
854855
{ "isMutable", I_.IsMutable },
855856
{ "isBitfield", I_.IsBitfield },
856857
{ "hasNoUniqueAddress", I_.HasNoUniqueAddress }

src/lib/Metadata/Reduce.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ void merge(FieldInfo& I, FieldInfo&& Other)
292292
mergeExprInfo(I.BitfieldWidth,
293293
std::move(Other.BitfieldWidth));
294294

295+
I.IsVariant |= Other.IsVariant;
295296
I.IsMutable |= Other.IsMutable;
296297
I.IsMaybeUnused |= Other.IsMaybeUnused;
297298
I.IsDeprecated |= Other.IsDeprecated;

test-files/golden-tests/union.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
union A
2+
{
3+
int x;
4+
bool y;
5+
};
6+
7+
struct B
8+
{
9+
union
10+
{
11+
int x;
12+
bool y;
13+
};
14+
15+
int z;
16+
};

test-files/golden-tests/union.xml

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<mrdocs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:noNamespaceSchemaLocation="https://github.com/cppalliance/mrdocs/raw/develop/mrdocs.rnc">
4+
<namespace id="//////////////////////////8=">
5+
<union name="A" id="rOga+mYntM7ytFb7bhJSklZ0r34=">
6+
<file path="union.cpp" line="1" class="def"/>
7+
<field name="x" id="Be23kXXQRAQHfKNTp2HOM2jouJo=">
8+
<file path="union.cpp" line="3" class="def"/>
9+
<attr id="is-variant"/>
10+
<type name="int"/>
11+
</field>
12+
<field name="y" id="HqUCV+CnE+akUirdwlf8maZxw40=">
13+
<file path="union.cpp" line="4" class="def"/>
14+
<attr id="is-variant"/>
15+
<type name="bool"/>
16+
</field>
17+
</union>
18+
<struct name="B" id="3JsK1DO0O+wZhv+0meptQrbs3fY=">
19+
<file path="union.cpp" line="7" class="def"/>
20+
<field name="x" id="QtOrWpj/+5ytPBCEoNlbW+uW/oA=">
21+
<file path="union.cpp" line="11" class="def"/>
22+
<attr id="is-variant"/>
23+
<type name="int"/>
24+
</field>
25+
<field name="y" id="8o+2/UVx4hIiDLQRYohp688sXmI=">
26+
<file path="union.cpp" line="12" class="def"/>
27+
<attr id="is-variant"/>
28+
<type name="bool"/>
29+
</field>
30+
<field name="z" id="zTVqdWL2ShJziu85kaeOk2wfYFs=">
31+
<file path="union.cpp" line="15" class="def"/>
32+
<type name="int"/>
33+
</field>
34+
</struct>
35+
</namespace>
36+
</mrdocs>

0 commit comments

Comments
 (0)