Skip to content

Commit

Permalink
CPreProcessor: support variadic macros with GNU cpp extension syntax
Browse files Browse the repository at this point in the history
Consider input:

  #define debug(format, args...) fprintf (stderr, format, args)

With this change,

* ctags extracts "args" with parameter kind,
* ctags extracts "debug" with "(format,args...)" as
  the signature field.

The option like

   -D'debug(format, args...)=fprintf (stderr, format, args)'

also works with this change.

Signed-off-by: Masatake YAMATO <[email protected]>
  • Loading branch information
masatake committed Jan 28, 2025
1 parent ed34962 commit df8ac88
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 1 deletion.
1 change: 1 addition & 0 deletions Units/parser-cxx.r/complex-macros.d/args.ctags
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
-D DECLARE_FUNCTION_2(_ret,_name)=_ret _name();
-D DECLARE_FUNCTION_3(_ret,_name,...)=_ret _name(__VA_ARGS__);
-D DEPRECATED(...)=__VA_ARGS__ __attribute__((deprecated))
-D ENUM_GNUX(n,e...)=enum n { e }
-D DECLARE_TWO_VERSIONS_OF_FUNCTIONS(_prefix1,_prefix2)=DECLARE_FUNCTION_2(int,_prefix1 ## a) DECLARE_FUNCTION_2(int,_prefix2 ## a)
-D STRINGIFY(token)=#token
-D IMPLEMENT_FUNCTIONS(_prefix)=void _prefix ## a(){ }; void _prefix ## b(){ };
Expand Down
7 changes: 7 additions & 0 deletions Units/parser-cxx.r/complex-macros.d/expected.tags
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ a input.cpp /^DECLARE_FUNCTION_3(int,p3,int a,int b);$/;" z prototype:p3 typeref
b input.cpp /^DECLARE_FUNCTION_3(int,p3,int a,int b);$/;" z prototype:p3 typeref:typename:int file:
DEPRECATED input.cpp /^#define DEPRECATED(/;" d file: signature:(...)
p4 input.cpp /^DEPRECATED(int p4());$/;" p typeref:typename:int file: signature:() properties:deprecated
n input.cpp /^#define ENUM_GNUX(n,e...) enum n { e }$/;" D macro:ENUM_GNUX
e input.cpp /^#define ENUM_GNUX(n,e...) enum n { e }$/;" D macro:ENUM_GNUX
ENUM_GNUX input.cpp /^#define ENUM_GNUX(/;" d file: signature:(n,e...)
color input.cpp /^ENUM_GNUX(color, red, blue, green);$/;" g file:
red input.cpp /^ENUM_GNUX(color, red, blue, green);$/;" e enum:color file:
blue input.cpp /^ENUM_GNUX(color, red, blue, green);$/;" e enum:color file:
green input.cpp /^ENUM_GNUX(color, red, blue, green);$/;" e enum:color file:
_prefix1 input.cpp /^#define DECLARE_TWO_VERSIONS_OF_FUNCTIONS(_prefix1,_prefix2) \\$/;" D macro:DECLARE_TWO_VERSIONS_OF_FUNCTIONS
_prefix2 input.cpp /^#define DECLARE_TWO_VERSIONS_OF_FUNCTIONS(_prefix1,_prefix2) \\$/;" D macro:DECLARE_TWO_VERSIONS_OF_FUNCTIONS
DECLARE_TWO_VERSIONS_OF_FUNCTIONS input.cpp /^#define DECLARE_TWO_VERSIONS_OF_FUNCTIONS(/;" d file: signature:(_prefix1,_prefix2)
Expand Down
4 changes: 4 additions & 0 deletions Units/parser-cxx.r/complex-macros.d/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ DECLARE_FUNCTION_3(int,p3,int a,int b);

DEPRECATED(int p4());

#define ENUM_GNUX(n,e...) enum n { e }

ENUM_GNUX(color, red, blue, green);

// Recursive macro expansion

#define DECLARE_TWO_VERSIONS_OF_FUNCTIONS(_prefix1,_prefix2) \
Expand Down
32 changes: 31 additions & 1 deletion parsers/cpreprocessor.c
Original file line number Diff line number Diff line change
Expand Up @@ -985,7 +985,25 @@ static int directiveDefine (const int c, bool undef)

if (vStringLength (param) > 0)
{
int r = makeParamTag (param, nth++, vStringChar(param, 0) == '.');
bool gccext_placeholder = false;
if (vStringLength (param) > 3
&& strcmp(vStringValue (param) + vStringLength (param) - 3, "...") == 0)
{
/* args... in GCC extension
*
* #define debug(format, args...) fprintf (stderr, format, args)
*
* In this case, args should be tagged. However the signature field
* for debug must be "(format,args...)".
*/
vString *param_nodots = vStringNewNInit (vStringValue (param),
vStringLength (param) - 3);
makeParamTag (param_nodots, nth, false);
vStringDelete (param_nodots);
gccext_placeholder = true;
}

int r = makeParamTag (param, nth++, vStringChar(param, 0) == '.' || gccext_placeholder);
intArrayAdd (params, r);
vStringClear (param);
}
Expand Down Expand Up @@ -2410,13 +2428,25 @@ static cppMacroInfo * saveMacro(hashTable *table, const char * macro)

if(
(
/* #define debug(format, ...) fprintf (stderr, format, __VA_ARGS__) */
bIsVarArg &&
(paramLen == 3) &&
(strncmp(paramBegin[i],"...",3) == 0)
) || (
/* #define debug(MSG) fputs(MSG, stderr) */
(!bIsVarArg) &&
(paramLen == tokenLen) &&
(strncmp(paramBegin[i],tokenBegin,paramLen) == 0)
) || (
/* GCC extension:
* #define debug(format, args...) fprintf (stderr, format, args)
*/
(!bIsVarArg) &&
(paramLen == tokenLen + 3) &&
(strncmp(paramBegin[i] + tokenLen, "...", 3) == 0) &&
(strncmp(paramBegin[i], tokenBegin, tokenLen) == 0) &&
/* Let's have a side effect */
(bIsVarArg = true)
)
)
{
Expand Down

0 comments on commit df8ac88

Please sign in to comment.