Skip to content

Commit 9f92b3d

Browse files
committedMar 12, 2019
[analyzer] Fix function macro crash
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. Patch by Tibor Brunner! Differential Revision: https://reviews.llvm.org/D57893 llvm-svn: 355903
1 parent 20ea21c commit 9f92b3d

File tree

3 files changed

+516
-4
lines changed

3 files changed

+516
-4
lines changed
 

‎clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp

+20-4
Original file line numberDiff line numberDiff line change
@@ -900,7 +900,7 @@ static std::string getMacroNameAndPrintExpansion(
900900
// If this is a function-like macro, skip its arguments, as
901901
// getExpandedMacro() already printed them. If this is the case, let's
902902
// first jump to the '(' token.
903-
if (MI->getNumParams() != 0)
903+
if (std::next(It)->is(tok::l_paren))
904904
It = getMatchingRParen(++It, E);
905905
continue;
906906
}
@@ -928,7 +928,15 @@ static std::string getMacroNameAndPrintExpansion(
928928

929929
getMacroNameAndPrintExpansion(Printer, ArgIt->getLocation(), PP,
930930
Info.Args, AlreadyProcessedTokens);
931-
if (MI->getNumParams() != 0)
931+
// Peek the next token if it is a tok::l_paren. This way we can decide
932+
// if this is the application or just a reference to a function maxro
933+
// symbol:
934+
//
935+
// #define apply(f) ...
936+
// #define func(x) ...
937+
// apply(func)
938+
// apply(func(42))
939+
if (std::next(ArgIt)->is(tok::l_paren))
932940
ArgIt = getMatchingRParen(++ArgIt, ArgEnd);
933941
}
934942
continue;
@@ -990,8 +998,16 @@ static MacroNameAndArgs getMacroNameAndArgs(SourceLocation ExpanLoc,
990998
return { MacroName, MI, {} };
991999

9921000
RawLexer.LexFromRawLexer(TheTok);
993-
assert(TheTok.is(tok::l_paren) &&
994-
"The token after the macro's identifier token should be '('!");
1001+
// When this is a token which expands to another macro function then its
1002+
// parentheses are not at its expansion locaiton. For example:
1003+
//
1004+
// #define foo(x) int bar() { return x; }
1005+
// #define apply_zero(f) f(0)
1006+
// apply_zero(foo)
1007+
// ^
1008+
// This is not a tok::l_paren, but foo is a function.
1009+
if (TheTok.isNot(tok::l_paren))
1010+
return { MacroName, MI, {} };
9951011

9961012
MacroArgMap Args;
9971013

‎clang/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist

+478
Original file line numberDiff line numberDiff line change
@@ -5577,6 +5577,484 @@
55775577
</array>
55785578
</dict>
55795579
</dict>
5580+
<dict>
5581+
<key>path</key>
5582+
<array>
5583+
<dict>
5584+
<key>kind</key><string>control</string>
5585+
<key>edges</key>
5586+
<array>
5587+
<dict>
5588+
<key>start</key>
5589+
<array>
5590+
<dict>
5591+
<key>line</key><integer>459</integer>
5592+
<key>col</key><integer>33</integer>
5593+
<key>file</key><integer>0</integer>
5594+
</dict>
5595+
<dict>
5596+
<key>line</key><integer>459</integer>
5597+
<key>col</key><integer>33</integer>
5598+
<key>file</key><integer>0</integer>
5599+
</dict>
5600+
</array>
5601+
<key>end</key>
5602+
<array>
5603+
<dict>
5604+
<key>line</key><integer>459</integer>
5605+
<key>col</key><integer>37</integer>
5606+
<key>file</key><integer>0</integer>
5607+
</dict>
5608+
<dict>
5609+
<key>line</key><integer>459</integer>
5610+
<key>col</key><integer>39</integer>
5611+
<key>file</key><integer>0</integer>
5612+
</dict>
5613+
</array>
5614+
</dict>
5615+
</array>
5616+
</dict>
5617+
<dict>
5618+
<key>kind</key><string>event</string>
5619+
<key>location</key>
5620+
<dict>
5621+
<key>line</key><integer>459</integer>
5622+
<key>col</key><integer>37</integer>
5623+
<key>file</key><integer>0</integer>
5624+
</dict>
5625+
<key>ranges</key>
5626+
<array>
5627+
<array>
5628+
<dict>
5629+
<key>line</key><integer>459</integer>
5630+
<key>col</key><integer>37</integer>
5631+
<key>file</key><integer>0</integer>
5632+
</dict>
5633+
<dict>
5634+
<key>line</key><integer>459</integer>
5635+
<key>col</key><integer>41</integer>
5636+
<key>file</key><integer>0</integer>
5637+
</dict>
5638+
</array>
5639+
</array>
5640+
<key>depth</key><integer>0</integer>
5641+
<key>extended_message</key>
5642+
<string>Calling &apos;foo&apos;</string>
5643+
<key>message</key>
5644+
<string>Calling &apos;foo&apos;</string>
5645+
</dict>
5646+
<dict>
5647+
<key>kind</key><string>event</string>
5648+
<key>location</key>
5649+
<dict>
5650+
<key>line</key><integer>458</integer>
5651+
<key>col</key><integer>1</integer>
5652+
<key>file</key><integer>0</integer>
5653+
</dict>
5654+
<key>depth</key><integer>1</integer>
5655+
<key>extended_message</key>
5656+
<string>Entered call from &apos;useZeroApplier1&apos;</string>
5657+
<key>message</key>
5658+
<string>Entered call from &apos;useZeroApplier1&apos;</string>
5659+
</dict>
5660+
<dict>
5661+
<key>kind</key><string>event</string>
5662+
<key>location</key>
5663+
<dict>
5664+
<key>line</key><integer>458</integer>
5665+
<key>col</key><integer>1</integer>
5666+
<key>file</key><integer>0</integer>
5667+
</dict>
5668+
<key>ranges</key>
5669+
<array>
5670+
<array>
5671+
<dict>
5672+
<key>line</key><integer>458</integer>
5673+
<key>col</key><integer>1</integer>
5674+
<key>file</key><integer>0</integer>
5675+
</dict>
5676+
<dict>
5677+
<key>line</key><integer>458</integer>
5678+
<key>col</key><integer>16</integer>
5679+
<key>file</key><integer>0</integer>
5680+
</dict>
5681+
</array>
5682+
</array>
5683+
<key>depth</key><integer>1</integer>
5684+
<key>extended_message</key>
5685+
<string>Returning zero</string>
5686+
<key>message</key>
5687+
<string>Returning zero</string>
5688+
</dict>
5689+
<dict>
5690+
<key>kind</key><string>event</string>
5691+
<key>location</key>
5692+
<dict>
5693+
<key>line</key><integer>459</integer>
5694+
<key>col</key><integer>37</integer>
5695+
<key>file</key><integer>0</integer>
5696+
</dict>
5697+
<key>ranges</key>
5698+
<array>
5699+
<array>
5700+
<dict>
5701+
<key>line</key><integer>459</integer>
5702+
<key>col</key><integer>37</integer>
5703+
<key>file</key><integer>0</integer>
5704+
</dict>
5705+
<dict>
5706+
<key>line</key><integer>459</integer>
5707+
<key>col</key><integer>41</integer>
5708+
<key>file</key><integer>0</integer>
5709+
</dict>
5710+
</array>
5711+
</array>
5712+
<key>depth</key><integer>0</integer>
5713+
<key>extended_message</key>
5714+
<string>Returning from &apos;foo&apos;</string>
5715+
<key>message</key>
5716+
<string>Returning from &apos;foo&apos;</string>
5717+
</dict>
5718+
<dict>
5719+
<key>kind</key><string>control</string>
5720+
<key>edges</key>
5721+
<array>
5722+
<dict>
5723+
<key>start</key>
5724+
<array>
5725+
<dict>
5726+
<key>line</key><integer>459</integer>
5727+
<key>col</key><integer>37</integer>
5728+
<key>file</key><integer>0</integer>
5729+
</dict>
5730+
<dict>
5731+
<key>line</key><integer>459</integer>
5732+
<key>col</key><integer>39</integer>
5733+
<key>file</key><integer>0</integer>
5734+
</dict>
5735+
</array>
5736+
<key>end</key>
5737+
<array>
5738+
<dict>
5739+
<key>line</key><integer>459</integer>
5740+
<key>col</key><integer>35</integer>
5741+
<key>file</key><integer>0</integer>
5742+
</dict>
5743+
<dict>
5744+
<key>line</key><integer>459</integer>
5745+
<key>col</key><integer>35</integer>
5746+
<key>file</key><integer>0</integer>
5747+
</dict>
5748+
</array>
5749+
</dict>
5750+
</array>
5751+
</dict>
5752+
<dict>
5753+
<key>kind</key><string>event</string>
5754+
<key>location</key>
5755+
<dict>
5756+
<key>line</key><integer>459</integer>
5757+
<key>col</key><integer>35</integer>
5758+
<key>file</key><integer>0</integer>
5759+
</dict>
5760+
<key>ranges</key>
5761+
<array>
5762+
<array>
5763+
<dict>
5764+
<key>line</key><integer>459</integer>
5765+
<key>col</key><integer>33</integer>
5766+
<key>file</key><integer>0</integer>
5767+
</dict>
5768+
<dict>
5769+
<key>line</key><integer>459</integer>
5770+
<key>col</key><integer>41</integer>
5771+
<key>file</key><integer>0</integer>
5772+
</dict>
5773+
</array>
5774+
</array>
5775+
<key>depth</key><integer>0</integer>
5776+
<key>extended_message</key>
5777+
<string>Division by zero</string>
5778+
<key>message</key>
5779+
<string>Division by zero</string>
5780+
</dict>
5781+
</array>
5782+
<key>macro_expansions</key>
5783+
<array>
5784+
<dict>
5785+
<key>location</key>
5786+
<dict>
5787+
<key>line</key><integer>458</integer>
5788+
<key>col</key><integer>1</integer>
5789+
<key>file</key><integer>0</integer>
5790+
</dict>
5791+
<key>name</key><string>APPLY_ZERO1</string>
5792+
<key>expansion</key><string>int foo() { return x; }(0)</string>
5793+
</dict>
5794+
</array>
5795+
<key>description</key><string>Division by zero</string>
5796+
<key>category</key><string>Logic error</string>
5797+
<key>type</key><string>Division by zero</string>
5798+
<key>check_name</key><string>core.DivideZero</string>
5799+
<!-- This hash is experimental and going to change! -->
5800+
<key>issue_hash_content_of_line_in_context</key><string>7ff82561a6c752746649d05220deeb40</string>
5801+
<key>issue_context_kind</key><string>function</string>
5802+
<key>issue_context</key><string>useZeroApplier1</string>
5803+
<key>issue_hash_function_offset</key><string>0</string>
5804+
<key>location</key>
5805+
<dict>
5806+
<key>line</key><integer>459</integer>
5807+
<key>col</key><integer>35</integer>
5808+
<key>file</key><integer>0</integer>
5809+
</dict>
5810+
<key>ExecutedLines</key>
5811+
<dict>
5812+
<key>0</key>
5813+
<array>
5814+
<integer>458</integer>
5815+
<integer>459</integer>
5816+
</array>
5817+
</dict>
5818+
</dict>
5819+
<dict>
5820+
<key>path</key>
5821+
<array>
5822+
<dict>
5823+
<key>kind</key><string>control</string>
5824+
<key>edges</key>
5825+
<array>
5826+
<dict>
5827+
<key>start</key>
5828+
<array>
5829+
<dict>
5830+
<key>line</key><integer>468</integer>
5831+
<key>col</key><integer>33</integer>
5832+
<key>file</key><integer>0</integer>
5833+
</dict>
5834+
<dict>
5835+
<key>line</key><integer>468</integer>
5836+
<key>col</key><integer>33</integer>
5837+
<key>file</key><integer>0</integer>
5838+
</dict>
5839+
</array>
5840+
<key>end</key>
5841+
<array>
5842+
<dict>
5843+
<key>line</key><integer>468</integer>
5844+
<key>col</key><integer>37</integer>
5845+
<key>file</key><integer>0</integer>
5846+
</dict>
5847+
<dict>
5848+
<key>line</key><integer>468</integer>
5849+
<key>col</key><integer>39</integer>
5850+
<key>file</key><integer>0</integer>
5851+
</dict>
5852+
</array>
5853+
</dict>
5854+
</array>
5855+
</dict>
5856+
<dict>
5857+
<key>kind</key><string>event</string>
5858+
<key>location</key>
5859+
<dict>
5860+
<key>line</key><integer>468</integer>
5861+
<key>col</key><integer>37</integer>
5862+
<key>file</key><integer>0</integer>
5863+
</dict>
5864+
<key>ranges</key>
5865+
<array>
5866+
<array>
5867+
<dict>
5868+
<key>line</key><integer>468</integer>
5869+
<key>col</key><integer>37</integer>
5870+
<key>file</key><integer>0</integer>
5871+
</dict>
5872+
<dict>
5873+
<key>line</key><integer>468</integer>
5874+
<key>col</key><integer>41</integer>
5875+
<key>file</key><integer>0</integer>
5876+
</dict>
5877+
</array>
5878+
</array>
5879+
<key>depth</key><integer>0</integer>
5880+
<key>extended_message</key>
5881+
<string>Calling &apos;bar&apos;</string>
5882+
<key>message</key>
5883+
<string>Calling &apos;bar&apos;</string>
5884+
</dict>
5885+
<dict>
5886+
<key>kind</key><string>event</string>
5887+
<key>location</key>
5888+
<dict>
5889+
<key>line</key><integer>467</integer>
5890+
<key>col</key><integer>1</integer>
5891+
<key>file</key><integer>0</integer>
5892+
</dict>
5893+
<key>depth</key><integer>1</integer>
5894+
<key>extended_message</key>
5895+
<string>Entered call from &apos;useZeroApplier2&apos;</string>
5896+
<key>message</key>
5897+
<string>Entered call from &apos;useZeroApplier2&apos;</string>
5898+
</dict>
5899+
<dict>
5900+
<key>kind</key><string>event</string>
5901+
<key>location</key>
5902+
<dict>
5903+
<key>line</key><integer>467</integer>
5904+
<key>col</key><integer>1</integer>
5905+
<key>file</key><integer>0</integer>
5906+
</dict>
5907+
<key>ranges</key>
5908+
<array>
5909+
<array>
5910+
<dict>
5911+
<key>line</key><integer>467</integer>
5912+
<key>col</key><integer>1</integer>
5913+
<key>file</key><integer>0</integer>
5914+
</dict>
5915+
<dict>
5916+
<key>line</key><integer>467</integer>
5917+
<key>col</key><integer>11</integer>
5918+
<key>file</key><integer>0</integer>
5919+
</dict>
5920+
</array>
5921+
</array>
5922+
<key>depth</key><integer>1</integer>
5923+
<key>extended_message</key>
5924+
<string>Returning zero</string>
5925+
<key>message</key>
5926+
<string>Returning zero</string>
5927+
</dict>
5928+
<dict>
5929+
<key>kind</key><string>event</string>
5930+
<key>location</key>
5931+
<dict>
5932+
<key>line</key><integer>468</integer>
5933+
<key>col</key><integer>37</integer>
5934+
<key>file</key><integer>0</integer>
5935+
</dict>
5936+
<key>ranges</key>
5937+
<array>
5938+
<array>
5939+
<dict>
5940+
<key>line</key><integer>468</integer>
5941+
<key>col</key><integer>37</integer>
5942+
<key>file</key><integer>0</integer>
5943+
</dict>
5944+
<dict>
5945+
<key>line</key><integer>468</integer>
5946+
<key>col</key><integer>41</integer>
5947+
<key>file</key><integer>0</integer>
5948+
</dict>
5949+
</array>
5950+
</array>
5951+
<key>depth</key><integer>0</integer>
5952+
<key>extended_message</key>
5953+
<string>Returning from &apos;bar&apos;</string>
5954+
<key>message</key>
5955+
<string>Returning from &apos;bar&apos;</string>
5956+
</dict>
5957+
<dict>
5958+
<key>kind</key><string>control</string>
5959+
<key>edges</key>
5960+
<array>
5961+
<dict>
5962+
<key>start</key>
5963+
<array>
5964+
<dict>
5965+
<key>line</key><integer>468</integer>
5966+
<key>col</key><integer>37</integer>
5967+
<key>file</key><integer>0</integer>
5968+
</dict>
5969+
<dict>
5970+
<key>line</key><integer>468</integer>
5971+
<key>col</key><integer>39</integer>
5972+
<key>file</key><integer>0</integer>
5973+
</dict>
5974+
</array>
5975+
<key>end</key>
5976+
<array>
5977+
<dict>
5978+
<key>line</key><integer>468</integer>
5979+
<key>col</key><integer>35</integer>
5980+
<key>file</key><integer>0</integer>
5981+
</dict>
5982+
<dict>
5983+
<key>line</key><integer>468</integer>
5984+
<key>col</key><integer>35</integer>
5985+
<key>file</key><integer>0</integer>
5986+
</dict>
5987+
</array>
5988+
</dict>
5989+
</array>
5990+
</dict>
5991+
<dict>
5992+
<key>kind</key><string>event</string>
5993+
<key>location</key>
5994+
<dict>
5995+
<key>line</key><integer>468</integer>
5996+
<key>col</key><integer>35</integer>
5997+
<key>file</key><integer>0</integer>
5998+
</dict>
5999+
<key>ranges</key>
6000+
<array>
6001+
<array>
6002+
<dict>
6003+
<key>line</key><integer>468</integer>
6004+
<key>col</key><integer>33</integer>
6005+
<key>file</key><integer>0</integer>
6006+
</dict>
6007+
<dict>
6008+
<key>line</key><integer>468</integer>
6009+
<key>col</key><integer>41</integer>
6010+
<key>file</key><integer>0</integer>
6011+
</dict>
6012+
</array>
6013+
</array>
6014+
<key>depth</key><integer>0</integer>
6015+
<key>extended_message</key>
6016+
<string>Division by zero</string>
6017+
<key>message</key>
6018+
<string>Division by zero</string>
6019+
</dict>
6020+
</array>
6021+
<key>macro_expansions</key>
6022+
<array>
6023+
<dict>
6024+
<key>location</key>
6025+
<dict>
6026+
<key>line</key><integer>467</integer>
6027+
<key>col</key><integer>1</integer>
6028+
<key>file</key><integer>0</integer>
6029+
</dict>
6030+
<key>name</key><string>APPLY_ZERO2</string>
6031+
<key>expansion</key><string>int bar() { return 0; }</string>
6032+
</dict>
6033+
</array>
6034+
<key>description</key><string>Division by zero</string>
6035+
<key>category</key><string>Logic error</string>
6036+
<key>type</key><string>Division by zero</string>
6037+
<key>check_name</key><string>core.DivideZero</string>
6038+
<!-- This hash is experimental and going to change! -->
6039+
<key>issue_hash_content_of_line_in_context</key><string>dd82c11b436b00009e37f54b1620a728</string>
6040+
<key>issue_context_kind</key><string>function</string>
6041+
<key>issue_context</key><string>useZeroApplier2</string>
6042+
<key>issue_hash_function_offset</key><string>0</string>
6043+
<key>location</key>
6044+
<dict>
6045+
<key>line</key><integer>468</integer>
6046+
<key>col</key><integer>35</integer>
6047+
<key>file</key><integer>0</integer>
6048+
</dict>
6049+
<key>ExecutedLines</key>
6050+
<dict>
6051+
<key>0</key>
6052+
<array>
6053+
<integer>467</integer>
6054+
<integer>468</integer>
6055+
</array>
6056+
</dict>
6057+
</dict>
55806058
</array>
55816059
<key>files</key>
55826060
<array>

‎clang/test/Analysis/plist-macros-with-expansion.cpp

+18
Original file line numberDiff line numberDiff line change
@@ -451,3 +451,21 @@ void recursiveMacroUser() {
451451
1 / value; // expected-warning{{Division by zero}}
452452
// expected-warning@-1{{expression result unused}}
453453
}
454+
455+
#define FOO(x) int foo() { return x; }
456+
#define APPLY_ZERO1(function) function(0)
457+
458+
APPLY_ZERO1(FOO)
459+
void useZeroApplier1() { (void)(1 / foo()); } // expected-warning{{Division by zero}}
460+
461+
// CHECK: <key>name</key><string>APPLY_ZERO1</string>
462+
// CHECK-NEXT: <key>expansion</key><string>int foo() { return x; }(0)</string>
463+
464+
#define BAR(x) int bar() { return x; }
465+
#define APPLY_ZERO2 BAR(0)
466+
467+
APPLY_ZERO2
468+
void useZeroApplier2() { (void)(1 / bar()); } // expected-warning{{Division by zero}}
469+
470+
// CHECK: <key>name</key><string>APPLY_ZERO2</string>
471+
// CHECK-NEXT: <key>expansion</key><string>int bar() { return 0; }</string>

0 commit comments

Comments
 (0)
Please sign in to comment.