Skip to content

Commit

Permalink
feat: support anonymous union members
Browse files Browse the repository at this point in the history
  • Loading branch information
sdkrystian committed Oct 17, 2024
1 parent c56dcae commit 7ad5853
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 5 deletions.
3 changes: 3 additions & 0 deletions include/mrdocs/Metadata/Field.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ struct FieldInfo
*/
ExprInfo Default;

/** Whether the field is a variant member */
bool IsVariant = false;

/** Whether the field is declared mutable */
bool IsMutable = false;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{{#if (eq kind "overload")}}{{>special-name-suffix (front members)~}}
{{else if (eq kind "function")~}}
{{#if (eq class "constructor")}}[.small]#[constructor]#
{{~else if (eq class "destructor")~}}[.small]#[destructor]#
{{~else if (eq class "destructor")}}[.small]#[destructor]#
{{~/if~}}
{{else if (eq kind "field")~}}
{{#if isVariant}}[.small]#[variant member]#{{/if~}}
{{/if}}
48 changes: 44 additions & 4 deletions src/lib/AST/ASTVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,11 @@ class ASTVisitor
if(DC->isFileContext() ||
DC->isFunctionOrMethod())
break;

if(auto* RD = dyn_cast<CXXRecordDecl>(DC);
RD && RD->isAnonymousStructOrUnion())
continue;

// when extracting dependencies, we want to extract
// all members of the containing class, not just this one
if(auto* TD = dyn_cast<TagDecl>(DC))
Expand Down Expand Up @@ -1519,6 +1524,16 @@ class ASTVisitor
return false;
}

// don't extract anonymous unions
if(const auto* RD = dyn_cast<RecordDecl>(D);
RD && RD->isAnonymousStructOrUnion())
return false;

// don't extract implicitly generated declarations
// (except for IndirectFieldDecls)
if(D->isImplicit() && !isa<IndirectFieldDecl>(D))
return false;

if (!config_->input.include.empty())
{
// Get filename
Expand Down Expand Up @@ -1959,10 +1974,15 @@ class ASTVisitor
{
switch(D->getKind())
{
case Decl::CXXRecord:
// we treat anonymous unions as "transparent"
if(auto* RD = cast<CXXRecordDecl>(D);
RD->isAnonymousStructOrUnion())
break;
[[fallthrough]];
case Decl::TranslationUnit:
case Decl::Namespace:
case Decl::Enum:
case Decl::CXXRecord:
case Decl::ClassTemplateSpecialization:
case Decl::ClassTemplatePartialSpecialization:
return D;
Expand Down Expand Up @@ -2373,6 +2393,8 @@ class ASTVisitor

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

I.IsVariant = D->getParent()->isUnion();

I.IsMutable = D->isMutable();

if(const Expr* E = D->getInClassInitializer())
Expand Down Expand Up @@ -2793,6 +2815,17 @@ class ASTVisitor
void
traverse(FieldDecl*);

/** Traverse a member of an anonymous union.
This function is called by traverseDecl to traverse
a member of an anonymous union.
A IndirectFieldDecl inherits from ValueDecl.
*/
void
traverse(IndirectFieldDecl*);

/** Traverse a concept definition
This function is called by traverseDecl to traverse a
Expand Down Expand Up @@ -3061,6 +3094,14 @@ traverse(FieldDecl* D)
auto [I, created] = *exp;
buildField(I, created, D);
}

void
ASTVisitor::
traverse(IndirectFieldDecl* D)
{
traverse(D->getAnonField());
}

//------------------------------------------------
// ConceptDecl

Expand Down Expand Up @@ -3348,9 +3389,8 @@ traverseDecl(
{
MRDOCS_ASSERT(D);

// Decl had a semantic error or is implicitly
// generated by the implementation
if(D->isInvalidDecl() || D->isImplicit())
// Decl had a semantic error
if(D->isInvalidDecl())
return;

SymbolFilter::FilterScope scope(symbolFilter_);
Expand Down
1 change: 1 addition & 0 deletions src/lib/Gen/xml/XMLWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,7 @@ writeField(
{"id", "is-mutable"}
});

writeAttr(I.IsVariant, "is-variant", tags_);
writeAttr(I.IsMaybeUnused, "maybe-unused", tags_);
writeAttr(I.IsDeprecated, "deprecated", tags_);
writeAttr(I.HasNoUniqueAddress, "no-unique-address", tags_);
Expand Down
1 change: 1 addition & 0 deletions src/lib/Metadata/DomMetadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,7 @@ DomInfo<T>::construct() const
{ "default", dom::stringOrNull(I_.Default.Written) },
{ "isMaybeUnused", I_.IsMaybeUnused },
{ "isDeprecated", I_.IsDeprecated },
{ "isVariant", I_.IsVariant },
{ "isMutable", I_.IsMutable },
{ "isBitfield", I_.IsBitfield },
{ "hasNoUniqueAddress", I_.HasNoUniqueAddress }
Expand Down
1 change: 1 addition & 0 deletions src/lib/Metadata/Reduce.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ void merge(FieldInfo& I, FieldInfo&& Other)
mergeExprInfo(I.BitfieldWidth,
std::move(Other.BitfieldWidth));

I.IsVariant |= Other.IsVariant;
I.IsMutable |= Other.IsMutable;
I.IsMaybeUnused |= Other.IsMaybeUnused;
I.IsDeprecated |= Other.IsDeprecated;
Expand Down
16 changes: 16 additions & 0 deletions test-files/golden-tests/union.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
union A
{
int x;
bool y;
};

struct B
{
union
{
int x;
bool y;
};

int z;
};
36 changes: 36 additions & 0 deletions test-files/golden-tests/union.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?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=">
<union name="A" id="rOga+mYntM7ytFb7bhJSklZ0r34=">
<file path="union.cpp" line="1" class="def"/>
<field name="x" id="Be23kXXQRAQHfKNTp2HOM2jouJo=">
<file path="union.cpp" line="3" class="def"/>
<attr id="is-variant"/>
<type name="int"/>
</field>
<field name="y" id="HqUCV+CnE+akUirdwlf8maZxw40=">
<file path="union.cpp" line="4" class="def"/>
<attr id="is-variant"/>
<type name="bool"/>
</field>
</union>
<struct name="B" id="3JsK1DO0O+wZhv+0meptQrbs3fY=">
<file path="union.cpp" line="7" class="def"/>
<field name="x" id="QtOrWpj/+5ytPBCEoNlbW+uW/oA=">
<file path="union.cpp" line="11" class="def"/>
<attr id="is-variant"/>
<type name="int"/>
</field>
<field name="y" id="8o+2/UVx4hIiDLQRYohp688sXmI=">
<file path="union.cpp" line="12" class="def"/>
<attr id="is-variant"/>
<type name="bool"/>
</field>
<field name="z" id="zTVqdWL2ShJziu85kaeOk2wfYFs=">
<file path="union.cpp" line="15" class="def"/>
<type name="int"/>
</field>
</struct>
</namespace>
</mrdocs>

0 comments on commit 7ad5853

Please sign in to comment.