Index: lib/StaticAnalyzer/Core/PlistDiagnostics.cpp =================================================================== --- lib/StaticAnalyzer/Core/PlistDiagnostics.cpp +++ lib/StaticAnalyzer/Core/PlistDiagnostics.cpp @@ -785,17 +785,46 @@ // If this token is the current macro's argument, we should expand it. if (Args && Args->count(II)) { + + bool WasPreviousTokenHash = false; + if (It != MI->tokens_begin()) + WasPreviousTokenHash = (It - 1)->is(tok::hash); + + // If WasPreviousTokenHash is true, the starting '"' was printed in the + // previous iteration. + for (const Token &ExpandedArgT : Args->at(II)) { - ExpansionOS << PP.getSpelling(ExpandedArgT) + ' '; + ExpansionOS << PP.getSpelling(ExpandedArgT); + + // If the previous token was #, printing spaces would modify a string. + if (!WasPreviousTokenHash) + ExpansionOS << ' '; } + + if (WasPreviousTokenHash) + ExpansionOS << "\" "; continue; } } - // TODO: Handle tok::hash and tok::hashhash. - // If control reaches here, there's nothing left to do, print the token. - ExpansionOS << PP.getSpelling(T) + ' '; + ExpansionOS << PP.getSpelling(T); + + if (It != E) { + Token NextTok = *(It + 1); + + if (NextTok.is(tok::hash)) + ExpansionOS << " \""; + + if (NextTok.isOneOf(tok::hash, tok::hashhash)) { + // Don't print the # or ## token. + ++It; + // Don't print space. + continue; + } + } + + ExpansionOS << ' '; } return {MacroName, ExpansionOS.str()}; Index: test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist =================================================================== --- test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist +++ test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist @@ -3,7 +3,7 @@ clang_version -clang version 8.0.0 (http://mainstream.inf.elte.hu/Szelethus/clang 531e9e44e37061619212a542a5d1076525fdbea9) (https://github.com/llvm-mirror/llvm 1ffbf26a1a0a190d69327af875a3337b74a2ce82) +clang version 8.0.0 (http://mainstream.inf.elte.hu/Szelethus/clang 263b6f72a3ff1483b445ba5bd8c1cdefcad4f6f6) (https://github.com/llvm-mirror/llvm 1ffbf26a1a0a190d69327af875a3337b74a2ce82) diagnostics @@ -3757,7 +3757,7 @@ file0 nameDECLARE_FUNC_AND_SET_TO_NULL - expansionvoid generated_ ## whatever ( ) ; ptr = nullptr ; + expansionvoid generated_whatever ( ) ; ptr = nullptr ; kindevent @@ -3889,12 +3889,12 @@ start - line290 + line285 col3 file0 - line290 + line285 col5 file0 @@ -3902,12 +3902,179 @@ end - line291 + line286 col3 file0 - line291 + line286 + col19 + file0 + + + + + + + kindmacro_expansion + location + + line286 + col3 + file0 + + nameTO_NULL_AND_PRINT + expansiona = 0 ; print ( "Will this ## cause a crash?" ) + + + kindevent + location + + line286 + col3 + file0 + + ranges + + + + line286 + col3 + file0 + + + line286 + col53 + file0 + + + + depth0 + extended_message + Null pointer value stored to 'a' + message + Null pointer value stored to 'a' + + + kindcontrol + edges + + + start + + + line287 + col3 + file0 + + + line287 + col3 + file0 + + + end + + + line287 + col6 + file0 + + + line287 + col6 + file0 + + + + + + + kindevent + location + + line287 + col6 + file0 + + ranges + + + + line287 + col4 + file0 + + + line287 + col4 + file0 + + + + depth0 + extended_message + Dereference of null pointer (loaded from variable 'a') + message + Dereference of null pointer (loaded from variable 'a') + + + descriptionDereference of null pointer (loaded from variable 'a') + categoryLogic error + typeDereference of null pointer + check_namecore.NullDereference + + issue_hash_content_of_line_in_context6817572ced27cb7d28fc87b2aba75fb4 + issue_context_kindfunction + issue_contextmacroArgContainsHashHashInStringTest + issue_hash_function_offset3 + location + + line287 + col6 + file0 + + ExecutedLines + + 0 + + 284 + 285 + 286 + 287 + + + + + path + + + kindcontrol + edges + + + start + + + line298 + col3 + file0 + + + line298 + col5 + file0 + + + end + + + line299 + col3 + file0 + + + line299 col11 file0 @@ -3919,18 +4086,18 @@ kindmacro_expansion location - line291 + line299 col3 file0 namePRINT_STR - expansionprint ( # Hello ) ; ptr = nullptr + expansionprint ( "Hello ") ; ptr = nullptr kindevent location - line291 + line299 col3 file0 @@ -3938,12 +4105,12 @@ - line291 + line299 col3 file0 - line291 + line299 col23 file0 @@ -3963,12 +4130,12 @@ start - line292 + line300 col3 file0 - line292 + line300 col3 file0 @@ -3976,12 +4143,12 @@ end - line292 + line300 col8 file0 - line292 + line300 col8 file0 @@ -3993,7 +4160,7 @@ kindevent location - line292 + line300 col8 file0 @@ -4001,12 +4168,12 @@ - line292 + line300 col4 file0 - line292 + line300 col6 file0 @@ -4030,7 +4197,7 @@ issue_hash_function_offset3 location - line292 + line300 col8 file0 @@ -4038,10 +4205,177 @@ 0 - 289 - 290 - 291 - 292 + 297 + 298 + 299 + 300 + + + + + path + + + kindcontrol + edges + + + start + + + line307 + col3 + file0 + + + line307 + col5 + file0 + + + end + + + line308 + col3 + file0 + + + line308 + col19 + file0 + + + + + + + kindmacro_expansion + location + + line308 + col3 + file0 + + nameTO_NULL_AND_PRINT + expansiona = 0 ; print ( "Will this # cause a crash?" ) + + + kindevent + location + + line308 + col3 + file0 + + ranges + + + + line308 + col3 + file0 + + + line308 + col52 + file0 + + + + depth0 + extended_message + Null pointer value stored to 'a' + message + Null pointer value stored to 'a' + + + kindcontrol + edges + + + start + + + line309 + col3 + file0 + + + line309 + col3 + file0 + + + end + + + line309 + col6 + file0 + + + line309 + col6 + file0 + + + + + + + kindevent + location + + line309 + col6 + file0 + + ranges + + + + line309 + col4 + file0 + + + line309 + col4 + file0 + + + + depth0 + extended_message + Dereference of null pointer (loaded from variable 'a') + message + Dereference of null pointer (loaded from variable 'a') + + + descriptionDereference of null pointer (loaded from variable 'a') + categoryLogic error + typeDereference of null pointer + check_namecore.NullDereference + + issue_hash_content_of_line_in_contextb1da2db423e721067ed5cfda858890be + issue_context_kindfunction + issue_contextmacroArgContainsHashInStringTest + issue_hash_function_offset3 + location + + line309 + col6 + file0 + + ExecutedLines + + 0 + + 306 + 307 + 308 + 309 Index: test/Analysis/plist-macros-with-expansion.cpp =================================================================== --- test/Analysis/plist-macros-with-expansion.cpp +++ test/Analysis/plist-macros-with-expansion.cpp @@ -278,9 +278,17 @@ *ptr = 5; // expected-warning{{Dereference of null pointer}} } -// TODO: Should expand correctly. // CHECK: nameDECLARE_FUNC_AND_SET_TO_NULL -// CHECK: expansionvoid generated_ ## whatever ( ) ; ptr = nullptr ; +// CHECK: expansionvoid generated_whatever ( ) ; ptr = nullptr ; + +void macroArgContainsHashHashInStringTest() { + int *a; + TO_NULL_AND_PRINT(a, "Will this ## cause a crash?"); + *a = 5; // expected-warning{{Dereference of null pointer}} +} + +// CHECK: nameTO_NULL_AND_PRINT +// CHECK: expansiona = 0 ; print ( "Will this ## cause a crash?" ) #define PRINT_STR(str, ptr) \ print(#str); \ @@ -292,6 +300,14 @@ *ptr = 5; // expected-warning{{Dereference of null pointer}} } -// TODO: Should expand correctly. // CHECK: namePRINT_STR -// CHECK: expansionprint ( # Hello ) ; ptr = nullptr +// CHECK: expansionprint ( "Hello" ) ; ptr = nullptr + +void macroArgContainsHashInStringTest() { + int *a; + TO_NULL_AND_PRINT(a, "Will this # cause a crash?"); + *a = 5; // expected-warning{{Dereference of null pointer}} +} + +// CHECK: nameTO_NULL_AND_PRINT +// CHECK: expansiona = 0 ; print ( "Will this # cause a crash?" )