Skip to content

Commit b51d6d2

Browse files
committed
issue #10708 Incorrect parsing to xml of c++11 constructs in methods and functions
1 parent 5086f9f commit b51d6d2

File tree

8 files changed

+189
-8
lines changed

8 files changed

+189
-8
lines changed

src/memberdef.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ class MemberDefImpl : public DefinitionMixin<MemberDefMutable>
178178
bool isStrongEnumValue() const override;
179179
bool livesInsideEnum() const override;
180180
bool isSliceLocal() const override;
181+
bool isNoDiscard() const override;
181182
bool isConstExpr() const override;
182183
bool isConstEval() const override;
183184
bool isConstInit() const override;
@@ -773,6 +774,8 @@ class MemberDefAliasImpl : public DefinitionAliasMixin<MemberDef>
773774
{ return getMdAlias()->livesInsideEnum(); }
774775
bool isSliceLocal() const override
775776
{ return getMdAlias()->isSliceLocal(); }
777+
bool isNoDiscard() const override
778+
{ return getMdAlias()->isNoDiscard(); }
776779
bool isConstExpr() const override
777780
{ return getMdAlias()->isConstExpr(); }
778781
bool isConstEval() const override
@@ -2805,6 +2808,7 @@ StringVector MemberDefImpl::getLabels(const Definition *container) const
28052808
if (isPrivateGettable()) sl.push_back("private get");
28062809
if (isPrivateSettable()) sl.push_back("private set");
28072810
}
2811+
if (isNoDiscard()) sl.push_back("nodiscard");
28082812
if (isConstExpr()) sl.push_back("constexpr");
28092813
if (isConstEval()) sl.push_back("consteval");
28102814
if (isConstInit()) sl.push_back("constinit");
@@ -3470,6 +3474,9 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml,
34703474
ldef.remove(pos, prefix.length());
34713475
}
34723476
}
3477+
ldef.stripPrefix("constexpr ");
3478+
ldef.stripPrefix("consteval ");
3479+
ldef.stripPrefix("constinit ");
34733480

34743481
//----------------------------------------
34753482

@@ -5444,6 +5451,11 @@ bool MemberDefImpl::isSliceLocal() const
54445451
return m_memSpec.isLocal();
54455452
}
54465453

5454+
bool MemberDefImpl::isNoDiscard() const
5455+
{
5456+
return m_memSpec.isNoDiscard();
5457+
}
5458+
54475459
bool MemberDefImpl::isConstExpr() const
54485460
{
54495461
return m_memSpec.isConstExpr();

src/memberdef.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ class MemberDef : public Definition
190190
virtual bool isConstExpr() const = 0;
191191
virtual bool isConstEval() const = 0;
192192
virtual bool isConstInit() const = 0;
193+
virtual bool isNoDiscard() const = 0;
193194
virtual int numberOfFlowKeyWords() const = 0;
194195

195196
// derived getters

src/scanner.l

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5725,6 +5725,12 @@ NONLopt [^\n]*
57255725
BEGIN(SkipPHPString);
57265726
}
57275727
}
5728+
<SkipC11Attribute>{ID} {
5729+
if (QCString(yytext)=="nodiscard")
5730+
{
5731+
yyextra->current->spec.setNoDiscard(true);
5732+
}
5733+
}
57285734
<SkipInits,SkipC11Inits,SkipCurly,SkipCurlyCpp,SkipC11Attribute>. { }
57295735
<SkipString,SkipPHPString>\\. { }
57305736
<SkipString>\" {

src/types.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,8 @@ class LocalToc
373373
/* 45 */ TSPEC(Strong) TSPEC(Weak) TSPEC(Unretained) TSPEC(Alias) TSPEC(ConstExp) \
374374
/* 50 */ TSPEC(Default) TSPEC(Delete) TSPEC(NoExcept) TSPEC(Attribute) TSPEC(Property) \
375375
/* 55 */ TSPEC(Readonly) TSPEC(Bound) TSPEC(Constrained) TSPEC(Transient) TSPEC(MaybeVoid) \
376-
/* 60 */ TSPEC(MaybeDefault) TSPEC(MaybeAmbiguous) TSPEC(Published) TSPEC(ConstEval) TSPEC(ConstInit)
376+
/* 60 */ TSPEC(MaybeDefault) TSPEC(MaybeAmbiguous) TSPEC(Published) TSPEC(ConstEval) TSPEC(ConstInit) \
377+
/* 65 */ TSPEC(NoDiscard)
377378

378379
/** Wrapper class for a number of boolean properties.
379380
* The properties are packed together, and initialized to false.

src/xmlgen.cpp

Lines changed: 83 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -531,8 +531,11 @@ static void stripQualifiers(QCString &typeStr)
531531
typeStr.stripPrefix("friend ");
532532
while (!done)
533533
{
534-
if (typeStr.stripPrefix("static "));
535-
else if (typeStr.stripPrefix("virtual "));
534+
if (typeStr.stripPrefix("static ")) {}
535+
else if (typeStr.stripPrefix("constexpr ")) {}
536+
else if (typeStr.stripPrefix("consteval ")) {}
537+
else if (typeStr.stripPrefix("constinit ")) {}
538+
else if (typeStr.stripPrefix("virtual ")) {}
536539
else if (typeStr=="virtual") typeStr="";
537540
else done=TRUE;
538541
}
@@ -557,6 +560,49 @@ static QCString memberOutputFileBase(const MemberDef *md)
557560
return md->getOutputFileBase();
558561
}
559562

563+
static QCString extractNoExcept(QCString &argsStr)
564+
{
565+
QCString expr;
566+
//printf("extractNoExcept(%s)\n",qPrint(argsStr));
567+
int i = argsStr.find("noexcept(");
568+
if (i!=-1)
569+
{
570+
int bracketCount = 1;
571+
size_t p = i+9;
572+
bool found = false;
573+
bool insideString = false;
574+
bool insideChar = false;
575+
char pc = 0;
576+
while (!found && p<argsStr.length())
577+
{
578+
char c = argsStr[p++];
579+
if (insideString)
580+
{
581+
if (c=='"' && pc!='\\') insideString=false;
582+
}
583+
else if (insideChar)
584+
{
585+
if (c=='\'' && pc!='\\') insideChar=false;
586+
}
587+
else
588+
{
589+
switch (c)
590+
{
591+
case '(': bracketCount++; break;
592+
case ')': bracketCount--; found = bracketCount==0; break;
593+
case '"': insideString = true; break;
594+
case '\'': insideChar = true; break;
595+
}
596+
}
597+
pc = c;
598+
}
599+
expr = argsStr.mid(i+9,p-i-10);
600+
argsStr = (argsStr.left(i) + argsStr.mid(p)).stripWhiteSpace();
601+
}
602+
//printf("extractNoExcept -> argsStr='%s', expr='%s'\n",qPrint(argsStr),qPrint(expr));
603+
return expr;
604+
}
605+
560606

561607
static void generateXMLForMember(const MemberDef *md,TextStream &ti,TextStream &t,const Definition *def)
562608
{
@@ -605,6 +651,30 @@ static void generateXMLForMember(const MemberDef *md,TextStream &ti,TextStream &
605651
}
606652

607653
QCString nameStr = md->name();
654+
QCString typeStr = md->typeString();
655+
QCString argsStr = md->argsString();
656+
QCString defStr = md->definition();
657+
defStr.stripPrefix("constexpr ");
658+
defStr.stripPrefix("consteval ");
659+
defStr.stripPrefix("constinit ");
660+
stripAnonymousMarkers(typeStr);
661+
stripQualifiers(typeStr);
662+
if (typeStr=="auto")
663+
{
664+
int i=argsStr.findRev("->");
665+
if (i!=-1) // move trailing return type into type and strip it from argsStr
666+
{
667+
typeStr=argsStr.mid(i+2).stripWhiteSpace();
668+
argsStr=argsStr.left(i).stripWhiteSpace();
669+
i=defStr.find("auto ");
670+
if (i!=-1)
671+
{
672+
defStr=defStr.left(i)+typeStr+defStr.mid(i+4);
673+
}
674+
}
675+
}
676+
QCString noExceptExpr = extractNoExcept(argsStr);
677+
608678
stripAnonymousMarkers(nameStr);
609679
ti << " <member refid=\"" << memberOutputFileBase(md)
610680
<< "_1" << md->anchor() << "\" kind=\"" << memType << "\"><name>"
@@ -642,6 +712,11 @@ static void generateXMLForMember(const MemberDef *md,TextStream &ti,TextStream &
642712
if (md->isStatic()) t << "yes"; else t << "no";
643713
t << "\"";
644714

715+
if (md->isNoDiscard())
716+
{
717+
t << " nodiscard=\"yes\"";
718+
}
719+
645720
if (md->isConstExpr())
646721
{
647722
t << " constexpr=\"yes\"";
@@ -714,6 +789,11 @@ static void generateXMLForMember(const MemberDef *md,TextStream &ti,TextStream &
714789
t << " noexcept=\"yes\"";
715790
}
716791

792+
if (!noExceptExpr.isEmpty())
793+
{
794+
t << " noexceptexpression=\"" << convertToXML(noExceptExpr) << "\"";
795+
}
796+
717797
if (al.volatileSpecifier())
718798
{
719799
t << " volatile=\"yes\"";
@@ -859,20 +939,16 @@ static void generateXMLForMember(const MemberDef *md,TextStream &ti,TextStream &
859939
)
860940
{
861941
writeMemberTemplateLists(md,t);
862-
QCString typeStr = md->typeString();
863-
stripAnonymousMarkers(typeStr);
864-
stripQualifiers(typeStr);
865942
t << " <type>";
866943
linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,typeStr);
867944
t << "</type>\n";
868-
QCString defStr = md->definition();
869945
if (md->isTypeAlias())
870946
{
871947
defStr+=" = "+md->initializer();
872948
}
873949
stripAnonymousMarkers(defStr);
874950
t << " <definition>" << convertToXML(defStr) << "</definition>\n";
875-
t << " <argsstring>" << convertToXML(md->argsString()) << "</argsstring>\n";
951+
t << " <argsstring>" << convertToXML(argsStr) << "</argsstring>\n";
876952
}
877953

878954
if (md->memberType() == MemberType_Enumeration)

templates/xml/compound.xsd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,8 @@
220220
<xsd:attribute name="volatile" type="DoxBool" use="optional"/>
221221
<xsd:attribute name="mutable" type="DoxBool" use="optional"/>
222222
<xsd:attribute name="noexcept" type="DoxBool" use="optional"/>
223+
<xsd:attribute name="noexceptexpression" type="xsd:string" use="optional"/>
224+
<xsd:attribute name="nodiscard" type="DoxBool" use="optional"/>
223225
<xsd:attribute name="constexpr" type="DoxBool" use="optional"/>
224226
<xsd:attribute name="consteval" type="DoxBool" use="optional"/>
225227
<xsd:attribute name="constinit" type="DoxBool" use="optional"/>

testing/102/class_a.xml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="" xml:lang="en-US">
3+
<compounddef id="class_a" kind="class" language="C++" prot="public">
4+
<compoundname>A</compoundname>
5+
<includes refid="102__header_8hpp" local="no">102_header.hpp</includes>
6+
<sectiondef kind="public-func">
7+
<memberdef kind="function" id="class_a_1ac5350de77c7e927b4bafa27a899743a8" prot="public" static="no" nodiscard="yes" constexpr="yes" const="no" explicit="no" inline="yes" noexcept="yes" noexceptexpression="std::is_nothrow_move_assignable_v&lt; A &gt;" virt="non-virtual">
8+
<type>int</type>
9+
<definition>int A::do_stuff</definition>
10+
<argsstring>()</argsstring>
11+
<name>do_stuff</name>
12+
<qualifiedname>A::do_stuff</qualifiedname>
13+
<briefdescription>
14+
<para>Does stuff. </para>
15+
</briefdescription>
16+
<detaileddescription>
17+
<para>Details </para>
18+
</detaileddescription>
19+
<inbodydescription>
20+
</inbodydescription>
21+
<location file="102_header.hpp" line="15" column="20" bodyfile="102_header.hpp" bodystart="15" bodyend="17"/>
22+
</memberdef>
23+
<memberdef kind="function" id="class_a_1aa0ac26ebde08a69be4382f29077bd5d4" prot="public" static="no" nodiscard="yes" constexpr="yes" const="no" explicit="no" inline="yes" noexcept="yes" noexceptexpression="std::is_nothrow_move_assignable_v&lt; A &gt;" virt="non-virtual">
24+
<type>int</type>
25+
<definition>int A::do_stuff2</definition>
26+
<argsstring>()</argsstring>
27+
<name>do_stuff2</name>
28+
<qualifiedname>A::do_stuff2</qualifiedname>
29+
<briefdescription>
30+
<para>Does stuff. </para>
31+
</briefdescription>
32+
<detaileddescription>
33+
<para>Details </para>
34+
</detaileddescription>
35+
<inbodydescription>
36+
</inbodydescription>
37+
<location file="102_header.hpp" line="21" column="21" bodyfile="102_header.hpp" bodystart="21" bodyend="23"/>
38+
</memberdef>
39+
</sectiondef>
40+
<briefdescription>
41+
<para>Some class. </para>
42+
</briefdescription>
43+
<detaileddescription>
44+
</detaileddescription>
45+
<location file="102_header.hpp" line="10" column="1" bodyfile="102_header.hpp" bodystart="11" bodyend="24"/>
46+
<listofallmembers>
47+
<member refid="class_a_1ac5350de77c7e927b4bafa27a899743a8" prot="public" virt="non-virtual">
48+
<scope>A</scope>
49+
<name>do_stuff</name>
50+
</member>
51+
<member refid="class_a_1aa0ac26ebde08a69be4382f29077bd5d4" prot="public" virt="non-virtual">
52+
<scope>A</scope>
53+
<name>do_stuff2</name>
54+
</member>
55+
</listofallmembers>
56+
</compounddef>
57+
</doxygen>

testing/102_header.hpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// objective: test noexcept with expression and nodiscard and constexpr
2+
// check: class_a.xml
3+
//
4+
#ifndef INCLUDE_GUARD
5+
#define INCLUDE_GUARD
6+
7+
#include <type_traits>
8+
9+
/// @brief Some class
10+
class A
11+
{
12+
public:
13+
/// @brief Does stuff
14+
/// @details Details
15+
[[nodiscard]] constexpr int do_stuff() noexcept(std::is_nothrow_move_assignable_v<A>)
16+
{
17+
}
18+
19+
/// @brief Does stuff
20+
/// @details Details
21+
[[nodiscard]] constexpr auto do_stuff2() noexcept(std::is_nothrow_move_assignable_v<A>) -> int
22+
{
23+
}
24+
};
25+
26+
#endif

0 commit comments

Comments
 (0)