From eff7c65d11435e2246e963fac8a3c87c38f00210 Mon Sep 17 00:00:00 2001 From: albert-github Date: Tue, 11 May 2021 15:15:34 +0200 Subject: issue #8542 Variadic macro expansion The variadic macro was not handled in case there were fixed arguments as well. --- src/pre.l | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/pre.l b/src/pre.l index 7b48ca7..54627ce 100644 --- a/src/pre.l +++ b/src/pre.l @@ -3241,10 +3241,17 @@ static void initPredefined(yyscan_t yyscanner,const QCString &fileName) ) // predefined function macro definition { static const reg::Ex reId(R"(\a\w*)"); + static const reg::Ex reVaArgs(R"(, *\.\.\. *$)"); reg::Iterator end; bool varArgs = false; int count = 0; std::map argMap; + reg::Iterator it1(ds.substr(i_obrace+1,i_cbrace-i_obrace-1),reVaArgs,0); + if (it1 != end) + { + i_cbrace -= it1->length(); + + } if (ds.substr(i_obrace+1,i_cbrace-i_obrace-1)=="...") { varArgs = true; @@ -3274,6 +3281,12 @@ static void initPredefined(yyscan_t yyscanner,const QCString &fileName) } ++it; } + if (it1!=end) + { + varArgs = true; + argMap.emplace("__VA_ARGS__",count); + count++; + } } // strip definition part std::string definition; -- cgit v0.12 From c53818345c516165fe2502ebdba9017c97f0bd99 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Thu, 20 May 2021 21:49:32 +0200 Subject: Did a bit of restructuring - avoids a second regEx - compute ds.substr part only once - unify varArgs only and fixed+varArgs cases --- src/pre.l | 77 +++++++++++++++++++++++++++++---------------------------------- 1 file changed, 36 insertions(+), 41 deletions(-) diff --git a/src/pre.l b/src/pre.l index 54627ce..8ea3974 100644 --- a/src/pre.l +++ b/src/pre.l @@ -3241,58 +3241,53 @@ static void initPredefined(yyscan_t yyscanner,const QCString &fileName) ) // predefined function macro definition { static const reg::Ex reId(R"(\a\w*)"); - static const reg::Ex reVaArgs(R"(, *\.\.\. *$)"); reg::Iterator end; - bool varArgs = false; - int count = 0; std::map argMap; - reg::Iterator it1(ds.substr(i_obrace+1,i_cbrace-i_obrace-1),reVaArgs,0); - if (it1 != end) - { - i_cbrace -= it1->length(); - - } - if (ds.substr(i_obrace+1,i_cbrace-i_obrace-1)=="...") + std::string args = ds.substr(i_obrace+1,i_cbrace-i_obrace-1); // part between ( and ) + size_t varArgsPos = args.find("..."); + bool hasVarArgs = varArgsPos!=std::string::npos; + if (hasVarArgs) { - varArgs = true; - argMap.emplace("__VA_ARGS__",count); - count++; + size_t lastCommaPos = args.rfind(',',varArgsPos); + i_cbrace = i_obrace+1; // leave out the varargs part + if (lastCommaPos!=std::string::npos) + { + i_cbrace += lastCommaPos; // but keep the explicit arguments if any + } } - else + size_t i=i_obrace+1; + //printf("predefined function macro '%s'\n",ds.c_str()); + int count = 0; + reg::Iterator arg_it(ds,reId,i); + // gather the formal arguments in a dictionary + while (i0) // see bug375037 { - const auto &match = *it; - size_t pi = match.position(); - size_t l = match.length(); - if (l>0) // see bug375037 - { - argMap.emplace(match.str(),count); - count++; - i=pi+l; - } - else - { - i++; - } - ++it; + argMap.emplace(match.str(),count); + count++; + i=pi+l; } - if (it1!=end) + else { - varArgs = true; - argMap.emplace("__VA_ARGS__",count); - count++; + i++; } + ++arg_it; + } + if (hasVarArgs) // add the variable argument if present + { + argMap.emplace("__VA_ARGS__",count); + count++; } + // strip definition part std::string definition; std::string in=ds.substr(i_equals+1); reg::Iterator re_it(in,reId); - size_t i=0; + i=0; // substitute all occurrences of formal arguments by their // corresponding markers for (; re_it!=end; ++re_it) @@ -3330,11 +3325,11 @@ static void initPredefined(yyscan_t yyscanner,const QCString &fileName) def.nonRecursive = nonRecursive; def.fileDef = state->yyFileDef; def.fileName = fileName; - def.varArgs = varArgs; + def.varArgs = hasVarArgs; state->contextDefines.insert(std::make_pair(def.name.str(),def)); - //printf("#define '%s' '%s' #nargs=%d\n", - // qPrint(def->name),qPrint(def->definition),def->nargs); + //printf("#define '%s' '%s' #nargs=%d hasVarArgs=%d\n", + // qPrint(def.name),qPrint(def.definition),def.nargs,def.varArgs); } } else if (!ds.empty()) // predefined non-function macro definition -- cgit v0.12