diff --git a/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp b/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp --- a/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp +++ b/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp @@ -1132,7 +1132,7 @@ std::string MacroName = PP.getSpelling(TheTok); const auto *II = PP.getIdentifierInfo(MacroName); - assert(II && "Failed to acquire the IndetifierInfo for the macro!"); + assert(II && "Failed to acquire the IdentifierInfo for the macro!"); const MacroInfo *MI = getMacroInfoForLocation(PP, SM, II, ExpanLoc); // assert(MI && "The macro must've been defined at it's expansion location!"); @@ -1180,9 +1180,16 @@ // * > 1, then tok::comma is a part of the current arg. int ParenthesesDepth = 1; - // If we encounter __VA_ARGS__, we will lex until the closing tok::r_paren, - // even if we lex a tok::comma and ParanthesesDepth == 1. - const IdentifierInfo *__VA_ARGS__II = PP.getIdentifierInfo("__VA_ARGS__"); + // If we encounter the variadic arg, we will lex until the closing + // tok::r_paren, even if we lex a tok::comma and ParanthesesDepth == 1. + const IdentifierInfo *VariadicParamII = PP.getIdentifierInfo("__VA_ARGS__"); + if (MI->isGNUVarargs()) { + // If macro uses GNU-style variadic args, the param name is user-supplied, + // an not "__VA_ARGS__". E.g.: + // #define FOO(a, b, myvargs...) + // In this case, just use the last parameter: + VariadicParamII = *(MacroParams.rbegin()); + } for (const IdentifierInfo *CurrParamII : MacroParams) { MacroParamMap::mapped_type ArgTokens; @@ -1201,9 +1208,8 @@ // Lex the first token of the next macro parameter. TStream.next(TheTok); - while ( - !(ParenthesesDepth == 1 && - (CurrParamII == __VA_ARGS__II ? false : TheTok.is(tok::comma)))) { + while (CurrParamII == VariadicParamII || ParenthesesDepth != 1 || + !TheTok.is(tok::comma)) { assert(TheTok.isNot(tok::eof) && "EOF encountered while looking for expanded macro args!"); @@ -1226,7 +1232,7 @@ // PARAMS_RESOLVE_TO_VA_ARGS(__VA_ARGS__); // // ^~~~~~~~~~~ Variadic parameter here // - // void mulitpleParamsResolveToVA_ARGS(void) { + // void multipleParamsResolveToVA_ARGS(void) { // int x = 1; // DISPATCH(x, "LF1M healer"); // Multiple arguments are mapped to // // a single __VA_ARGS__ parameter. @@ -1237,8 +1243,8 @@ // PARAMS_RESOLVE_TO_VA_ARGS. By this point, we already noted during // the processing of DISPATCH what __VA_ARGS__ maps to, so we'll // retrieve the next series of tokens from that. - if (TheTok.getIdentifierInfo() == __VA_ARGS__II) { - TStream.injectRange(PrevParamMap.at(__VA_ARGS__II)); + if (TheTok.getIdentifierInfo() == VariadicParamII) { + TStream.injectRange(PrevParamMap.at(VariadicParamII)); TStream.next(TheTok); continue; } @@ -1248,9 +1254,9 @@ TStream.next(TheTok); } } else { - assert(CurrParamII == __VA_ARGS__II && + assert(CurrParamII == VariadicParamII && "No more macro arguments are found, but the current parameter " - "isn't __VA_ARGS__!"); + "isn't the variadic arg!"); } ParamMap.emplace(CurrParamII, std::move(ArgTokens)); diff --git a/clang/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist b/clang/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist --- a/clang/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist +++ b/clang/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist @@ -6787,6 +6787,142 @@ + + path + + + kindcontrol + edges + + + start + + + line537 + col3 + file0 + + + line537 + col5 + file0 + + + end + + + line539 + col3 + file0 + + + line539 + col15 + file0 + + + + + + + kindevent + location + + line539 + col3 + file0 + + ranges + + + + line539 + col3 + file0 + + + line539 + col26 + file0 + + + + depth0 + extended_message + The value 0 is assigned to 'a' + message + The value 0 is assigned to 'a' + + + kindevent + location + + line540 + col13 + file0 + + ranges + + + + line540 + col10 + file0 + + + line540 + col15 + file0 + + + + depth0 + extended_message + Division by zero + message + Division by zero + + + macro_expansions + + + location + + line539 + col3 + file0 + + nameBZ44493_GNUVA + expansion--(a); + + + descriptionDivision by zero + categoryLogic error + typeDivision by zero + check_namecore.DivideZero + + issue_hash_content_of_line_in_context21c6d180d8c8c30cf730b7a7136980a9 + issue_context_kindfunction + issue_contextbz44493 + issue_hash_function_offset4 + location + + line540 + col13 + file0 + + ExecutedLines + + 0 + + 536 + 537 + 538 + 539 + 540 + + + files diff --git a/clang/test/Analysis/plist-macros-with-expansion.cpp b/clang/test/Analysis/plist-macros-with-expansion.cpp --- a/clang/test/Analysis/plist-macros-with-expansion.cpp +++ b/clang/test/Analysis/plist-macros-with-expansion.cpp @@ -529,3 +529,17 @@ // FIXME: Stringify and escape __VA_ARGS__ correctly. // CHECK: nameSTRINGIFIED_VA_ARGS // CHECK-NEXT: expansionvariadicCFunction(x, "Additional supply depots required.", ")";x = 0; + +// bz44493: Support GNU-style named variadic arguments in plister +#define BZ44493_GNUVA(i, args...) --(i); + +int bz44493(void) { + int a = 2; + BZ44493_GNUVA(a); + BZ44493_GNUVA(a, "arg2"); + (void)(10 / a); // expected-warning{{Division by zero}} + return 0; +} + +// CHECK: nameBZ44493_GNUVA +// CHECK-NEXT: expansion--(a);