From d22a19d56f875990e41082db2254ede11d73e8bc Mon Sep 17 00:00:00 2001 From: Kristof Umann Date: Thu, 14 Mar 2019 13:38:16 +0000 Subject: [PATCH] [analyzer] Fix function macro crash Re-commit D57893. Differential Revision: https://reviews.llvm.org/D57893 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@356142 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/PlistDiagnostics.cpp | 26 +- .../plist-macros-with-expansion.cpp.plist | 478 ++++++++++++++++++ test/Analysis/plist-macros-with-expansion.cpp | 18 + 3 files changed, 518 insertions(+), 4 deletions(-) diff --git a/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp b/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp index 92d0720448..116eb6cd8e 100644 --- a/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp +++ b/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp @@ -900,7 +900,8 @@ static std::string getMacroNameAndPrintExpansion( // If this is a function-like macro, skip its arguments, as // getExpandedMacro() already printed them. If this is the case, let's // first jump to the '(' token. - if (MI->getNumParams() != 0) + auto N = std::next(It); + if (N != E && N->is(tok::l_paren)) It = getMatchingRParen(++It, E); continue; } @@ -928,7 +929,16 @@ static std::string getMacroNameAndPrintExpansion( getMacroNameAndPrintExpansion(Printer, ArgIt->getLocation(), PP, Info.Args, AlreadyProcessedTokens); - if (MI->getNumParams() != 0) + // 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)) + auto N = std::next(ArgIt); + if (N != ArgEnd && N->is(tok::l_paren)) ArgIt = getMatchingRParen(++ArgIt, ArgEnd); } continue; @@ -990,8 +1000,16 @@ static MacroNameAndArgs getMacroNameAndArgs(SourceLocation ExpanLoc, 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; diff --git a/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist b/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist index 68f02a38fd..a31063ac68 100644 --- a/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist +++ b/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist @@ -5577,6 +5577,484 @@ + + path + + + kindcontrol + edges + + + start + + + line459 + col33 + file0 + + + line459 + col33 + file0 + + + end + + + line459 + col37 + file0 + + + line459 + col39 + file0 + + + + + + + kindevent + location + + line459 + col37 + file0 + + ranges + + + + line459 + col37 + file0 + + + line459 + col41 + file0 + + + + depth0 + extended_message + Calling 'foo' + message + Calling 'foo' + + + kindevent + location + + line458 + col1 + file0 + + depth1 + extended_message + Entered call from 'useZeroApplier1' + message + Entered call from 'useZeroApplier1' + + + kindevent + location + + line458 + col1 + file0 + + ranges + + + + line458 + col1 + file0 + + + line458 + col16 + file0 + + + + depth1 + extended_message + Returning zero + message + Returning zero + + + kindevent + location + + line459 + col37 + file0 + + ranges + + + + line459 + col37 + file0 + + + line459 + col41 + file0 + + + + depth0 + extended_message + Returning from 'foo' + message + Returning from 'foo' + + + kindcontrol + edges + + + start + + + line459 + col37 + file0 + + + line459 + col39 + file0 + + + end + + + line459 + col35 + file0 + + + line459 + col35 + file0 + + + + + + + kindevent + location + + line459 + col35 + file0 + + ranges + + + + line459 + col33 + file0 + + + line459 + col41 + file0 + + + + depth0 + extended_message + Division by zero + message + Division by zero + + + macro_expansions + + + location + + line458 + col1 + file0 + + nameAPPLY_ZERO1 + expansionint foo() { return x; }(0) + + + descriptionDivision by zero + categoryLogic error + typeDivision by zero + check_namecore.DivideZero + + issue_hash_content_of_line_in_context7ff82561a6c752746649d05220deeb40 + issue_context_kindfunction + issue_contextuseZeroApplier1 + issue_hash_function_offset0 + location + + line459 + col35 + file0 + + ExecutedLines + + 0 + + 458 + 459 + + + + + path + + + kindcontrol + edges + + + start + + + line468 + col33 + file0 + + + line468 + col33 + file0 + + + end + + + line468 + col37 + file0 + + + line468 + col39 + file0 + + + + + + + kindevent + location + + line468 + col37 + file0 + + ranges + + + + line468 + col37 + file0 + + + line468 + col41 + file0 + + + + depth0 + extended_message + Calling 'bar' + message + Calling 'bar' + + + kindevent + location + + line467 + col1 + file0 + + depth1 + extended_message + Entered call from 'useZeroApplier2' + message + Entered call from 'useZeroApplier2' + + + kindevent + location + + line467 + col1 + file0 + + ranges + + + + line467 + col1 + file0 + + + line467 + col11 + file0 + + + + depth1 + extended_message + Returning zero + message + Returning zero + + + kindevent + location + + line468 + col37 + file0 + + ranges + + + + line468 + col37 + file0 + + + line468 + col41 + file0 + + + + depth0 + extended_message + Returning from 'bar' + message + Returning from 'bar' + + + kindcontrol + edges + + + start + + + line468 + col37 + file0 + + + line468 + col39 + file0 + + + end + + + line468 + col35 + file0 + + + line468 + col35 + file0 + + + + + + + kindevent + location + + line468 + col35 + file0 + + ranges + + + + line468 + col33 + file0 + + + line468 + col41 + file0 + + + + depth0 + extended_message + Division by zero + message + Division by zero + + + macro_expansions + + + location + + line467 + col1 + file0 + + nameAPPLY_ZERO2 + expansionint bar() { return 0; } + + + descriptionDivision by zero + categoryLogic error + typeDivision by zero + check_namecore.DivideZero + + issue_hash_content_of_line_in_contextdd82c11b436b00009e37f54b1620a728 + issue_context_kindfunction + issue_contextuseZeroApplier2 + issue_hash_function_offset0 + location + + line468 + col35 + file0 + + ExecutedLines + + 0 + + 467 + 468 + + + files diff --git a/test/Analysis/plist-macros-with-expansion.cpp b/test/Analysis/plist-macros-with-expansion.cpp index 057a165f94..c062a4782c 100644 --- a/test/Analysis/plist-macros-with-expansion.cpp +++ b/test/Analysis/plist-macros-with-expansion.cpp @@ -451,3 +451,21 @@ void recursiveMacroUser() { 1 / value; // expected-warning{{Division by zero}} // expected-warning@-1{{expression result unused}} } + +#define FOO(x) int foo() { return x; } +#define APPLY_ZERO1(function) function(0) + +APPLY_ZERO1(FOO) +void useZeroApplier1() { (void)(1 / foo()); } // expected-warning{{Division by zero}} + +// CHECK: nameAPPLY_ZERO1 +// CHECK-NEXT: expansionint foo() { return x; }(0) + +#define BAR(x) int bar() { return x; } +#define APPLY_ZERO2 BAR(0) + +APPLY_ZERO2 +void useZeroApplier2() { (void)(1 / bar()); } // expected-warning{{Division by zero}} + +// CHECK: nameAPPLY_ZERO2 +// CHECK-NEXT: expansionint bar() { return 0; } -- 2.40.0