Skip to content
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

feat: support anonymous union members #707

Merged
merged 1 commit into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
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
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>
Loading