Skip to content

Commit 8dcfa3b

Browse files
committed
issue doxygen#11849 Incorrect evaluation of __VA_OPT__ when preprocessing
1 parent cf3d453 commit 8dcfa3b

File tree

1 file changed

+29
-7
lines changed

1 file changed

+29
-7
lines changed

src/pre.l

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1871,6 +1871,10 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER}
18711871
<RemoveCPPComment>{CPPC}
18721872
<RemoveCPPComment>[^\x06\n]+
18731873
<RemoveCPPComment>.
1874+
<DefineText>"#"/"__VA_OPT__" {
1875+
yyextra->defText+=yytext;
1876+
yyextra->defLitText+=yytext;
1877+
}
18741878
<DefineText>"#"/{IDSTART} {
18751879
outputChar(yyscanner,' ');
18761880
yyextra->quoteArg=TRUE;
@@ -2637,13 +2641,23 @@ static void skipCommentMacroName(yyscan_t yyscanner, const QCString &expr, QCStr
26372641
// Expand C++20's __VA_OPT__(x) to either x if hasOptionalArgs==true or to the empty string if false
26382642
static QCString expandVAOpt(const QCString &vaStr,bool hasOptionalArgs)
26392643
{
2644+
//printf("expandVAOpt(vaStr=%s,hasOptionalArgs=%d)\n",qPrint(vaStr),hasOptionalArgs);
26402645
QCString result;
26412646
int vo=0, vp=0;
26422647
result.clear();
26432648
int vl = static_cast<int>(vaStr.length());
26442649
while ((vo = vaStr.find("__VA_OPT__(",vp))!=-1)
26452650
{
2646-
result+=vaStr.left(vo);
2651+
bool hasHash = vo>0 && vaStr.at(vo-1)=='#';
2652+
if (hasHash)
2653+
{
2654+
result+=vaStr.mid(vp,vo-vp-1); // don't copy #
2655+
result+="\"";
2656+
}
2657+
else
2658+
{
2659+
result+=vaStr.mid(vp,vo-vp);
2660+
}
26472661
int ve=vo+11; // skip over '__VA_OPT__(' part
26482662
int bc=1;
26492663
while (bc>0 && ve<vl)
@@ -2659,6 +2673,10 @@ static QCString expandVAOpt(const QCString &vaStr,bool hasOptionalArgs)
26592673
//printf("vo=%d ve=%d voStr=%s\n",vo,ve,qPrint(voStr));
26602674
result+=voStr; // take 'x' from __VA_OPT__(x)
26612675
}
2676+
if (hasHash)
2677+
{
2678+
result+="\"";
2679+
}
26622680
vp=ve;
26632681
}
26642682
result+=vaStr.mid(vp);
@@ -2675,8 +2693,7 @@ static QCString expandVAOpt(const QCString &vaStr,bool hasOptionalArgs)
26752693
*/
26762694
static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCString *rest,int pos,int &len,const Define *def,QCString &result,int level)
26772695
{
2678-
//YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2679-
//printf(">replaceFunctionMacro(expr='%s',rest='%s',pos=%d,def='%s') level=%zu\n",qPrint(expr),rest ? qPrint(*rest) : 0,pos,qPrint(def->name),state->levelGuard.size());
2696+
//printf(">replaceFunctionMacro(expr='%s',rest='%s',pos=%d,def='%s') level=%zu\n",qPrint(expr),rest ? qPrint(*rest) : 0,pos,qPrint(def->name),preYYget_extra(yyscanner)->levelGuard.size());
26802697
uint32_t j=pos;
26812698
len=0;
26822699
result.clear();
@@ -2697,6 +2714,7 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin
26972714
std::map<std::string,std::string> argTable; // list of arguments
26982715
QCString arg;
26992716
int argCount=0;
2717+
int argCountNonEmpty=0;
27002718
bool done=FALSE;
27012719

27022720
// PHASE 1: read the macro arguments
@@ -2750,14 +2768,17 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin
27502768
{
27512769
if (c==',' && argCount==def->nargs-1 && def->varArgs)
27522770
{
2771+
expandExpression(yyscanner,arg,nullptr,0,level+1);
27532772
arg=arg.stripWhiteSpace();
27542773
arg+=',';
27552774
}
27562775
else
27572776
{
2777+
expandExpression(yyscanner,arg,nullptr,0,level+1);
2778+
arg=arg.stripWhiteSpace();
27582779
QCString argKey;
27592780
argKey.sprintf("@%d",argCount++); // key name
2760-
arg=arg.stripWhiteSpace();
2781+
if (c==',' || !arg.isEmpty()) argCountNonEmpty++;
27612782
// add argument to the lookup table
27622783
argTable.emplace(toStdString(argKey), toStdString(arg));
27632784
arg.clear();
@@ -2832,7 +2853,8 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin
28322853
// substitution of all formal arguments
28332854
QCString resExpr;
28342855
QCString d=def->definition.stripWhiteSpace();
2835-
if (def->varArgs) d = expandVAOpt(d,argCount!=def->nargs-1);
2856+
//printf("varArgs=%d argCount=%d def->nargs=%d d=%s\n",def->varArgs,argCount,def->nargs,qPrint(d));
2857+
if (def->varArgs) d = expandVAOpt(d,argCountNonEmpty!=def->nargs-1);
28362858
//printf("Macro definition: '%s'\n",qPrint(d));
28372859
bool inString=FALSE;
28382860
while (k<d.length())
@@ -2915,10 +2937,10 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin
29152937
}
29162938
len=j-pos;
29172939
result=resExpr;
2918-
//printf("<replaceFunctionMacro(expr='%s',rest='%s',pos=%d,def='%s',result='%s') level=%zu return=TRUE\n",qPrint(expr),rest ? qPrint(*rest) : 0,pos,qPrint(def->name),qPrint(result),state->levelGuard.size());
2940+
//printf("<replaceFunctionMacro(expr='%s',rest='%s',pos=%d,def='%s',result='%s') level=%zu return=TRUE\n",qPrint(expr),rest ? qPrint(*rest) : 0,pos,qPrint(def->name),qPrint(result),preYYget_extra(yyscanner)->levelGuard.size());
29192941
return TRUE;
29202942
}
2921-
//printf("<replaceFunctionMacro(expr='%s',rest='%s',pos=%d,def='%s',result='%s') level=%zu return=FALSE\n",qPrint(expr),rest ? qPrint(*rest) : 0,pos,qPrint(def->name),qPrint(result),state->levelGuard.size());
2943+
//printf("<replaceFunctionMacro(expr='%s',rest='%s',pos=%d,def='%s',result='%s') level=%zu return=FALSE\n",qPrint(expr),rest ? qPrint(*rest) : 0,pos,qPrint(def->name),qPrint(result),preYYget_extra(yyscanner)->levelGuard.size());
29222944
return FALSE;
29232945
}
29242946

0 commit comments

Comments
 (0)