bruntib created this revision. bruntib added reviewers: NoQ, george.karpenkov, Szelethus, xazax.hun. Herald added subscribers: cfe-commits, dkrupp, donat.nagy, mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware. Herald added a project: clang.
When there is a functor-like macro which is passed as parameter to another "function" macro then its parameters are not listed at the place of expansion: #define foo(x) int bar() { return x; } #define hello(fvar) fvar(0) hello(foo) int main() { 1 / bar(); } Expansion of hello(foo) asserted Clang, because it expected an l_paren token in the 3rd line after "foo", since it is a function-like token. Repository: rC Clang https://reviews.llvm.org/D57893 Files: lib/StaticAnalyzer/Core/PlistDiagnostics.cpp Index: lib/StaticAnalyzer/Core/PlistDiagnostics.cpp =================================================================== --- lib/StaticAnalyzer/Core/PlistDiagnostics.cpp +++ lib/StaticAnalyzer/Core/PlistDiagnostics.cpp @@ -879,8 +879,18 @@ getMacroNameAndPrintExpansion(Printer, ArgIt->getLocation(), PP, Info.Args, AlreadyProcessedTokens); - if (MI->getNumParams() != 0) - ArgIt = getMatchingRParen(++ArgIt, ArgEnd); + // Peek the next token if it is a tok::l_paren. This way we can decide + // if this is the application or just a reference to a function maxro + // symbol: + // + // #define apply(f) ... + // #define func(x) ... + // apply(func) + // apply(func(42)) + if ((++ArgIt)->is(tok::l_paren)) + ArgIt = getMatchingRParen(ArgIt, ArgEnd); + else + --ArgIt; } continue; } @@ -941,8 +951,16 @@ return { MacroName, MI, {} }; RawLexer.LexFromRawLexer(TheTok); - assert(TheTok.is(tok::l_paren) && - "The token after the macro's identifier token should be '('!"); + // When this is a token which expands to another macro function then its + // parentheses are not at its expansion locaiton. For example: + // + // #define foo(x) int bar() { return x; } + // #define apply_zero(f) f(0) + // apply_zero(foo) + // ^ + // This is not a tok::l_paren, but foo is a function. + if (TheTok.isNot(tok::l_paren)) + return { MacroName, MI, {} }; MacroArgMap Args;
Index: lib/StaticAnalyzer/Core/PlistDiagnostics.cpp =================================================================== --- lib/StaticAnalyzer/Core/PlistDiagnostics.cpp +++ lib/StaticAnalyzer/Core/PlistDiagnostics.cpp @@ -879,8 +879,18 @@ getMacroNameAndPrintExpansion(Printer, ArgIt->getLocation(), PP, Info.Args, AlreadyProcessedTokens); - if (MI->getNumParams() != 0) - ArgIt = getMatchingRParen(++ArgIt, ArgEnd); + // Peek the next token if it is a tok::l_paren. This way we can decide + // if this is the application or just a reference to a function maxro + // symbol: + // + // #define apply(f) ... + // #define func(x) ... + // apply(func) + // apply(func(42)) + if ((++ArgIt)->is(tok::l_paren)) + ArgIt = getMatchingRParen(ArgIt, ArgEnd); + else + --ArgIt; } continue; } @@ -941,8 +951,16 @@ return { MacroName, MI, {} }; RawLexer.LexFromRawLexer(TheTok); - assert(TheTok.is(tok::l_paren) && - "The token after the macro's identifier token should be '('!"); + // When this is a token which expands to another macro function then its + // parentheses are not at its expansion locaiton. For example: + // + // #define foo(x) int bar() { return x; } + // #define apply_zero(f) f(0) + // apply_zero(foo) + // ^ + // This is not a tok::l_paren, but foo is a function. + if (TheTok.isNot(tok::l_paren)) + return { MacroName, MI, {} }; MacroArgMap Args;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits