1 //===--- PreprocessorTracker.cpp - Preprocessor tracking -*- C++ -*------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===--------------------------------------------------------------------===// 9 // 10 // The Basic Idea (Macro and Conditional Checking) 11 // 12 // Basically we install a PPCallbacks-derived object to track preprocessor 13 // activity, namely when a header file is entered/exited, when a macro 14 // is expanded, when "defined" is used, and when #if, #elif, #ifdef, 15 // and #ifndef are used. We save the state of macro and "defined" 16 // expressions in a map, keyed on a name/file/line/column quadruple. 17 // The map entries store the different states (values) that a macro expansion, 18 // "defined" expression, or condition expression has in the course of 19 // processing for the one location in the one header containing it, 20 // plus a list of the nested include stacks for the states. When a macro 21 // or "defined" expression evaluates to the same value, which is the 22 // desired case, only one state is stored. Similarly, for conditional 23 // directives, we save the condition expression states in a separate map. 24 // 25 // This information is collected as modularize compiles all the headers 26 // given to it to process. After all the compilations are performed, 27 // a check is performed for any entries in the maps that contain more 28 // than one different state, and for these an output message is generated. 29 // 30 // For example: 31 // 32 // (...)/SubHeader.h:11:5: 33 // #if SYMBOL == 1 34 // ^ 35 // error: Macro instance 'SYMBOL' has different values in this header, 36 // depending on how it was included. 37 // 'SYMBOL' expanded to: '1' with respect to these inclusion paths: 38 // (...)/Header1.h 39 // (...)/SubHeader.h 40 // (...)/SubHeader.h:3:9: 41 // #define SYMBOL 1 42 // ^ 43 // Macro defined here. 44 // 'SYMBOL' expanded to: '2' with respect to these inclusion paths: 45 // (...)/Header2.h 46 // (...)/SubHeader.h 47 // (...)/SubHeader.h:7:9: 48 // #define SYMBOL 2 49 // ^ 50 // Macro defined here. 51 // 52 // The Basic Idea ('Extern "C/C++" {}' Or 'namespace {}') With Nested 53 // '#include' Checking) 54 // 55 // To check for '#include' directives nested inside 'Extern "C/C++" {}' 56 // or 'namespace {}' blocks, we keep track of the '#include' directives 57 // while running the preprocessor, and later during a walk of the AST 58 // we call a function to check for any '#include' directies inside 59 // an 'Extern "C/C++" {}' or 'namespace {}' block, given its source 60 // range. 61 // 62 // Design and Implementation Details (Macro and Conditional Checking) 63 // 64 // A PreprocessorTrackerImpl class implements the PreprocessorTracker 65 // interface. It uses a PreprocessorCallbacks class derived from PPCallbacks 66 // to track preprocessor activity, namely entering/exiting a header, macro 67 // expansions, use of "defined" expressions, and #if, #elif, #ifdef, and 68 // #ifndef conditional directives. PreprocessorTrackerImpl stores a map 69 // of MacroExpansionTracker objects keyed on a name/file/line/column 70 // value represented by a light-weight PPItemKey value object. This 71 // is the key top-level data structure tracking the values of macro 72 // expansion instances. Similarly, it stores a map of ConditionalTracker 73 // objects with the same kind of key, for tracking preprocessor conditional 74 // directives. 75 // 76 // The MacroExpansionTracker object represents one macro reference or use 77 // of a "defined" expression in a header file. It stores a handle to a 78 // string representing the unexpanded macro instance, a handle to a string 79 // representing the unpreprocessed source line containing the unexpanded 80 // macro instance, and a vector of one or more MacroExpansionInstance 81 // objects. 82 // 83 // The MacroExpansionInstance object represents one or more expansions 84 // of a macro reference, for the case where the macro expands to the same 85 // value. MacroExpansionInstance stores a handle to a string representing 86 // the expanded macro value, a PPItemKey representing the file/line/column 87 // where the macro was defined, a handle to a string representing the source 88 // line containing the macro definition, and a vector of InclusionPathHandle 89 // values that represents the hierarchies of include files for each case 90 // where the particular header containing the macro reference was referenced 91 // or included. 92 93 // In the normal case where a macro instance always expands to the same 94 // value, the MacroExpansionTracker object will only contain one 95 // MacroExpansionInstance representing all the macro expansion instances. 96 // If a case was encountered where a macro instance expands to a value 97 // that is different from that seen before, or the macro was defined in 98 // a different place, a new MacroExpansionInstance object representing 99 // that case will be added to the vector in MacroExpansionTracker. If a 100 // macro instance expands to a value already seen before, the 101 // InclusionPathHandle representing that case's include file hierarchy 102 // will be added to the existing MacroExpansionInstance object. 103 104 // For checking conditional directives, the ConditionalTracker class 105 // functions similarly to MacroExpansionTracker, but tracks an #if, 106 // #elif, #ifdef, or #ifndef directive in a header file. It stores 107 // a vector of one or two ConditionalExpansionInstance objects, 108 // representing the cases where the conditional expression evaluates 109 // to true or false. This latter object stores the evaluated value 110 // of the condition expression (a bool) and a vector of 111 // InclusionPathHandles. 112 // 113 // To reduce the instances of string and object copying, the 114 // PreprocessorTrackerImpl class uses a StringPool to save all stored 115 // strings, and defines a StringHandle type to abstract the references 116 // to the strings. 117 // 118 // PreprocessorTrackerImpl also maintains a list representing the unique 119 // headers, which is just a vector of StringHandle's for the header file 120 // paths. A HeaderHandle abstracts a reference to a header, and is simply 121 // the index of the stored header file path. 122 // 123 // A HeaderInclusionPath class abstracts a unique hierarchy of header file 124 // inclusions. It simply stores a vector of HeaderHandles ordered from the 125 // top-most header (the one from the header list passed to modularize) down 126 // to the header containing the macro reference. PreprocessorTrackerImpl 127 // stores a vector of these objects. An InclusionPathHandle typedef 128 // abstracts a reference to one of the HeaderInclusionPath objects, and is 129 // simply the index of the stored HeaderInclusionPath object. The 130 // MacroExpansionInstance object stores a vector of these handles so that 131 // the reporting function can display the include hierarchies for the macro 132 // expansion instances represented by that object, to help the user 133 // understand how the header was included. (A future enhancement might 134 // be to associate a line number for the #include directives, but I 135 // think not doing so is good enough for the present.) 136 // 137 // A key reason for using these opaque handles was to try to keep all the 138 // internal objects light-weight value objects, in order to reduce string 139 // and object copying overhead, and to abstract this implementation detail. 140 // 141 // The key data structures are built up while modularize runs the headers 142 // through the compilation. A PreprocessorTracker instance is created and 143 // passed down to the AST action and consumer objects in modularize. For 144 // each new compilation instance, the consumer calls the 145 // PreprocessorTracker's handleNewPreprocessorEntry function, which sets 146 // up a PreprocessorCallbacks object for the preprocessor. At the end of 147 // the compilation instance, the PreprocessorTracker's 148 // handleNewPreprocessorExit function handles cleaning up with respect 149 // to the preprocessing instance. 150 // 151 // The PreprocessorCallbacks object uses an overidden FileChanged callback 152 // to determine when a header is entered and exited (including exiting the 153 // header during #include directives). It calls PreprocessorTracker's 154 // handleHeaderEntry and handleHeaderExit functions upon entering and 155 // exiting a header. These functions manage a stack of header handles 156 // representing by a vector, pushing and popping header handles as headers 157 // are entered and exited. When a HeaderInclusionPath object is created, 158 // it simply copies this stack. 159 // 160 // The PreprocessorCallbacks object uses an overridden MacroExpands callback 161 // to track when a macro expansion is performed. It calls a couple of helper 162 // functions to get the unexpanded and expanded macro values as strings, but 163 // then calls PreprocessorTrackerImpl's addMacroExpansionInstance function to 164 // do the rest of the work. The getMacroExpandedString function uses the 165 // preprocessor's getSpelling to convert tokens to strings using the 166 // information passed to the MacroExpands callback, and simply concatenates 167 // them. It makes recursive calls to itself to handle nested macro 168 // definitions, and also handles function-style macros. 169 // 170 // PreprocessorTrackerImpl's addMacroExpansionInstance function looks for 171 // an existing MacroExpansionTracker entry in its map of MacroExampleTracker 172 // objects. If none exists, it adds one with one MacroExpansionInstance and 173 // returns. If a MacroExpansionTracker object already exists, it looks for 174 // an existing MacroExpansionInstance object stored in the 175 // MacroExpansionTracker object, one that matches the macro expanded value 176 // and the macro definition location. If a matching MacroExpansionInstance 177 // object is found, it just adds the current HeaderInclusionPath object to 178 // it. If not found, it creates and stores a new MacroExpantionInstance 179 // object. The addMacroExpansionInstance function calls a couple of helper 180 // functions to get the pre-formatted location and source line strings for 181 // the macro reference and the macro definition stored as string handles. 182 // These helper functions use the current source manager from the 183 // preprocessor. This is done in advance at this point in time because the 184 // source manager doesn't exist at the time of the reporting. 185 // 186 // For conditional check, the PreprocessorCallbacks class overrides the 187 // PPCallbacks handlers for #if, #elif, #ifdef, and #ifndef. These handlers 188 // call the addConditionalExpansionInstance method of 189 // PreprocessorTrackerImpl. The process is similar to that of macros, but 190 // with some different data and error messages. A lookup is performed for 191 // the conditional, and if a ConditionalTracker object doesn't yet exist for 192 // the conditional, a new one is added, including adding a 193 // ConditionalExpansionInstance object to it to represent the condition 194 // expression state. If a ConditionalTracker for the conditional does 195 // exist, a lookup is made for a ConditionalExpansionInstance object 196 // matching the condition expression state. If one exists, a 197 // HeaderInclusionPath is added to it. Otherwise a new 198 // ConditionalExpansionInstance entry is made. If a ConditionalTracker 199 // has two ConditionalExpansionInstance objects, it means there was a 200 // conflict, meaning the conditional expression evaluated differently in 201 // one or more cases. 202 // 203 // After modularize has performed all the compilations, it enters a phase 204 // of error reporting. This new feature adds to this reporting phase calls 205 // to the PreprocessorTracker's reportInconsistentMacros and 206 // reportInconsistentConditionals functions. These functions walk the maps 207 // of MacroExpansionTracker's and ConditionalTracker's respectively. If 208 // any of these objects have more than one MacroExpansionInstance or 209 // ConditionalExpansionInstance objects, it formats and outputs an error 210 // message like the example shown previously, using the stored data. 211 // 212 // A potential issue is that there is some overlap between the #if/#elif 213 // conditional and macro reporting. I could disable the #if and #elif, 214 // leaving just the #ifdef and #ifndef, since these don't overlap. Or, 215 // to make clearer the separate reporting phases, I could add an output 216 // message marking the phases. 217 // 218 // Design and Implementation Details ('Extern "C/C++" {}' Or 219 // 'namespace {}') With Nested '#include' Checking) 220 // 221 // We override the InclusionDirective in PPCallbacks to record information 222 // about each '#include' directive encountered during preprocessing. 223 // We co-opt the PPItemKey class to store the information about each 224 // '#include' directive, including the source file name containing the 225 // directive, the name of the file being included, and the source line 226 // and column of the directive. We store these object in a vector, 227 // after first check to see if an entry already exists. 228 // 229 // Later, while the AST is being walked for other checks, we provide 230 // visit handlers for 'extern "C/C++" {}' and 'namespace (name) {}' 231 // blocks, checking to see if any '#include' directives occurred 232 // within the blocks, reporting errors if any found. 233 // 234 // Future Directions 235 // 236 // We probably should add options to disable any of the checks, in case 237 // there is some problem with them, or the messages get too verbose. 238 // 239 // With the map of all the macro and conditional expansion instances, 240 // it might be possible to add to the existing modularize error messages 241 // (the second part referring to definitions being different), attempting 242 // to tie them to the last macro conflict encountered with respect to the 243 // order of the code encountered. 244 // 245 //===--------------------------------------------------------------------===// 246 247 #include "clang/Lex/LexDiagnostic.h" 248 #include "PreprocessorTracker.h" 249 #include "clang/Lex/MacroArgs.h" 250 #include "clang/Lex/PPCallbacks.h" 251 #include "llvm/ADT/SmallSet.h" 252 #include "llvm/Support/StringPool.h" 253 #include "llvm/Support/raw_ostream.h" 254 #include "ModularizeUtilities.h" 255 256 namespace Modularize { 257 258 // Forwards. 259 class PreprocessorTrackerImpl; 260 261 // Some handle types 262 typedef llvm::PooledStringPtr StringHandle; 263 264 typedef int HeaderHandle; 265 const HeaderHandle HeaderHandleInvalid = -1; 266 267 typedef int InclusionPathHandle; 268 const InclusionPathHandle InclusionPathHandleInvalid = -1; 269 270 // Some utility functions. 271 272 // Get a "file:line:column" source location string. 273 static std::string getSourceLocationString(clang::Preprocessor &PP, 274 clang::SourceLocation Loc) { 275 if (Loc.isInvalid()) 276 return std::string("(none)"); 277 else 278 return Loc.printToString(PP.getSourceManager()); 279 } 280 281 // Get just the file name from a source location. 282 static std::string getSourceLocationFile(clang::Preprocessor &PP, 283 clang::SourceLocation Loc) { 284 std::string Source(getSourceLocationString(PP, Loc)); 285 size_t Offset = Source.find(':', 2); 286 if (Offset == std::string::npos) 287 return Source; 288 return Source.substr(0, Offset); 289 } 290 291 // Get just the line and column from a source location. 292 static void getSourceLocationLineAndColumn(clang::Preprocessor &PP, 293 clang::SourceLocation Loc, int &Line, 294 int &Column) { 295 clang::PresumedLoc PLoc = PP.getSourceManager().getPresumedLoc(Loc); 296 if (PLoc.isInvalid()) { 297 Line = 0; 298 Column = 0; 299 return; 300 } 301 Line = PLoc.getLine(); 302 Column = PLoc.getColumn(); 303 } 304 305 // Retrieve source snippet from file image. 306 std::string getSourceString(clang::Preprocessor &PP, clang::SourceRange Range) { 307 clang::SourceLocation BeginLoc = Range.getBegin(); 308 clang::SourceLocation EndLoc = Range.getEnd(); 309 const char *BeginPtr = PP.getSourceManager().getCharacterData(BeginLoc); 310 const char *EndPtr = PP.getSourceManager().getCharacterData(EndLoc); 311 size_t Length = EndPtr - BeginPtr; 312 return llvm::StringRef(BeginPtr, Length).trim().str(); 313 } 314 315 // Retrieve source line from file image given a location. 316 std::string getSourceLine(clang::Preprocessor &PP, clang::SourceLocation Loc) { 317 const llvm::MemoryBuffer *MemBuffer = 318 PP.getSourceManager().getBuffer(PP.getSourceManager().getFileID(Loc)); 319 const char *Buffer = MemBuffer->getBufferStart(); 320 const char *BufferEnd = MemBuffer->getBufferEnd(); 321 const char *BeginPtr = PP.getSourceManager().getCharacterData(Loc); 322 const char *EndPtr = BeginPtr; 323 while (BeginPtr > Buffer) { 324 if (*BeginPtr == '\n') { 325 BeginPtr++; 326 break; 327 } 328 BeginPtr--; 329 } 330 while (EndPtr < BufferEnd) { 331 if (*EndPtr == '\n') { 332 break; 333 } 334 EndPtr++; 335 } 336 size_t Length = EndPtr - BeginPtr; 337 return llvm::StringRef(BeginPtr, Length).str(); 338 } 339 340 // Retrieve source line from file image given a file ID and line number. 341 std::string getSourceLine(clang::Preprocessor &PP, clang::FileID FileID, 342 int Line) { 343 const llvm::MemoryBuffer *MemBuffer = PP.getSourceManager().getBuffer(FileID); 344 const char *Buffer = MemBuffer->getBufferStart(); 345 const char *BufferEnd = MemBuffer->getBufferEnd(); 346 const char *BeginPtr = Buffer; 347 const char *EndPtr = BufferEnd; 348 int LineCounter = 1; 349 if (Line == 1) 350 BeginPtr = Buffer; 351 else { 352 while (Buffer < BufferEnd) { 353 if (*Buffer == '\n') { 354 if (++LineCounter == Line) { 355 BeginPtr = Buffer++ + 1; 356 break; 357 } 358 } 359 Buffer++; 360 } 361 } 362 while (Buffer < BufferEnd) { 363 if (*Buffer == '\n') { 364 EndPtr = Buffer; 365 break; 366 } 367 Buffer++; 368 } 369 size_t Length = EndPtr - BeginPtr; 370 return llvm::StringRef(BeginPtr, Length).str(); 371 } 372 373 // Get the string for the Unexpanded macro instance. 374 // The soureRange is expected to end at the last token 375 // for the macro instance, which in the case of a function-style 376 // macro will be a ')', but for an object-style macro, it 377 // will be the macro name itself. 378 std::string getMacroUnexpandedString(clang::SourceRange Range, 379 clang::Preprocessor &PP, 380 llvm::StringRef MacroName, 381 const clang::MacroInfo *MI) { 382 clang::SourceLocation BeginLoc(Range.getBegin()); 383 const char *BeginPtr = PP.getSourceManager().getCharacterData(BeginLoc); 384 size_t Length; 385 std::string Unexpanded; 386 if (MI->isFunctionLike()) { 387 clang::SourceLocation EndLoc(Range.getEnd()); 388 const char *EndPtr = PP.getSourceManager().getCharacterData(EndLoc) + 1; 389 Length = (EndPtr - BeginPtr) + 1; // +1 is ')' width. 390 } else 391 Length = MacroName.size(); 392 return llvm::StringRef(BeginPtr, Length).trim().str(); 393 } 394 395 // Get the expansion for a macro instance, given the information 396 // provided by PPCallbacks. 397 // FIXME: This doesn't support function-style macro instances 398 // passed as arguments to another function-style macro. However, 399 // since it still expands the inner arguments, it still 400 // allows modularize to effectively work with respect to macro 401 // consistency checking, although it displays the incorrect 402 // expansion in error messages. 403 std::string getMacroExpandedString(clang::Preprocessor &PP, 404 llvm::StringRef MacroName, 405 const clang::MacroInfo *MI, 406 const clang::MacroArgs *Args) { 407 std::string Expanded; 408 // Walk over the macro Tokens. 409 typedef clang::MacroInfo::tokens_iterator Iter; 410 for (Iter I = MI->tokens_begin(), E = MI->tokens_end(); I != E; ++I) { 411 clang::IdentifierInfo *II = I->getIdentifierInfo(); 412 int ArgNo = (II && Args ? MI->getArgumentNum(II) : -1); 413 if (ArgNo == -1) { 414 // This isn't an argument, just add it. 415 if (II == nullptr) 416 Expanded += PP.getSpelling((*I)); // Not an identifier. 417 else { 418 // Token is for an identifier. 419 std::string Name = II->getName().str(); 420 // Check for nexted macro references. 421 clang::MacroInfo *MacroInfo = PP.getMacroInfo(II); 422 if (MacroInfo) 423 Expanded += getMacroExpandedString(PP, Name, MacroInfo, nullptr); 424 else 425 Expanded += Name; 426 } 427 continue; 428 } 429 // We get here if it's a function-style macro with arguments. 430 const clang::Token *ResultArgToks; 431 const clang::Token *ArgTok = Args->getUnexpArgument(ArgNo); 432 if (Args->ArgNeedsPreexpansion(ArgTok, PP)) 433 ResultArgToks = &(const_cast<clang::MacroArgs *>(Args)) 434 ->getPreExpArgument(ArgNo, MI, PP)[0]; 435 else 436 ResultArgToks = ArgTok; // Use non-preexpanded Tokens. 437 // If the arg token didn't expand into anything, ignore it. 438 if (ResultArgToks->is(clang::tok::eof)) 439 continue; 440 unsigned NumToks = clang::MacroArgs::getArgLength(ResultArgToks); 441 // Append the resulting argument expansions. 442 for (unsigned ArgumentIndex = 0; ArgumentIndex < NumToks; ++ArgumentIndex) { 443 const clang::Token &AT = ResultArgToks[ArgumentIndex]; 444 clang::IdentifierInfo *II = AT.getIdentifierInfo(); 445 if (II == nullptr) 446 Expanded += PP.getSpelling(AT); // Not an identifier. 447 else { 448 // It's an identifier. Check for further expansion. 449 std::string Name = II->getName().str(); 450 clang::MacroInfo *MacroInfo = PP.getMacroInfo(II); 451 if (MacroInfo) 452 Expanded += getMacroExpandedString(PP, Name, MacroInfo, nullptr); 453 else 454 Expanded += Name; 455 } 456 } 457 } 458 return Expanded; 459 } 460 461 // Get the string representing a vector of Tokens. 462 std::string 463 getTokensSpellingString(clang::Preprocessor &PP, 464 llvm::SmallVectorImpl<clang::Token> &Tokens) { 465 std::string Expanded; 466 // Walk over the macro Tokens. 467 typedef llvm::SmallVectorImpl<clang::Token>::iterator Iter; 468 for (Iter I = Tokens.begin(), E = Tokens.end(); I != E; ++I) 469 Expanded += PP.getSpelling(*I); // Not an identifier. 470 return llvm::StringRef(Expanded).trim().str(); 471 } 472 473 // Get the expansion for a macro instance, given the information 474 // provided by PPCallbacks. 475 std::string getExpandedString(clang::Preprocessor &PP, 476 llvm::StringRef MacroName, 477 const clang::MacroInfo *MI, 478 const clang::MacroArgs *Args) { 479 std::string Expanded; 480 // Walk over the macro Tokens. 481 typedef clang::MacroInfo::tokens_iterator Iter; 482 for (Iter I = MI->tokens_begin(), E = MI->tokens_end(); I != E; ++I) { 483 clang::IdentifierInfo *II = I->getIdentifierInfo(); 484 int ArgNo = (II && Args ? MI->getArgumentNum(II) : -1); 485 if (ArgNo == -1) { 486 // This isn't an argument, just add it. 487 if (II == nullptr) 488 Expanded += PP.getSpelling((*I)); // Not an identifier. 489 else { 490 // Token is for an identifier. 491 std::string Name = II->getName().str(); 492 // Check for nexted macro references. 493 clang::MacroInfo *MacroInfo = PP.getMacroInfo(II); 494 if (MacroInfo) 495 Expanded += getMacroExpandedString(PP, Name, MacroInfo, nullptr); 496 else 497 Expanded += Name; 498 } 499 continue; 500 } 501 // We get here if it's a function-style macro with arguments. 502 const clang::Token *ResultArgToks; 503 const clang::Token *ArgTok = Args->getUnexpArgument(ArgNo); 504 if (Args->ArgNeedsPreexpansion(ArgTok, PP)) 505 ResultArgToks = &(const_cast<clang::MacroArgs *>(Args)) 506 ->getPreExpArgument(ArgNo, MI, PP)[0]; 507 else 508 ResultArgToks = ArgTok; // Use non-preexpanded Tokens. 509 // If the arg token didn't expand into anything, ignore it. 510 if (ResultArgToks->is(clang::tok::eof)) 511 continue; 512 unsigned NumToks = clang::MacroArgs::getArgLength(ResultArgToks); 513 // Append the resulting argument expansions. 514 for (unsigned ArgumentIndex = 0; ArgumentIndex < NumToks; ++ArgumentIndex) { 515 const clang::Token &AT = ResultArgToks[ArgumentIndex]; 516 clang::IdentifierInfo *II = AT.getIdentifierInfo(); 517 if (II == nullptr) 518 Expanded += PP.getSpelling(AT); // Not an identifier. 519 else { 520 // It's an identifier. Check for further expansion. 521 std::string Name = II->getName().str(); 522 clang::MacroInfo *MacroInfo = PP.getMacroInfo(II); 523 if (MacroInfo) 524 Expanded += getMacroExpandedString(PP, Name, MacroInfo, nullptr); 525 else 526 Expanded += Name; 527 } 528 } 529 } 530 return Expanded; 531 } 532 533 // ConditionValueKind strings. 534 const char * 535 ConditionValueKindStrings[] = { 536 "(not evaluated)", "false", "true" 537 }; 538 539 bool operator<(const StringHandle &H1, const StringHandle &H2) { 540 const char *S1 = (H1 ? *H1 : ""); 541 const char *S2 = (H2 ? *H2 : ""); 542 int Diff = strcmp(S1, S2); 543 return Diff < 0; 544 } 545 bool operator>(const StringHandle &H1, const StringHandle &H2) { 546 const char *S1 = (H1 ? *H1 : ""); 547 const char *S2 = (H2 ? *H2 : ""); 548 int Diff = strcmp(S1, S2); 549 return Diff > 0; 550 } 551 552 // Preprocessor item key. 553 // 554 // This class represents a location in a source file, for use 555 // as a key representing a unique name/file/line/column quadruplet, 556 // which in this case is used to identify a macro expansion instance, 557 // but could be used for other things as well. 558 // The file is a header file handle, the line is a line number, 559 // and the column is a column number. 560 class PPItemKey { 561 public: 562 PPItemKey(clang::Preprocessor &PP, StringHandle Name, HeaderHandle File, 563 clang::SourceLocation Loc) 564 : Name(Name), File(File) { 565 getSourceLocationLineAndColumn(PP, Loc, Line, Column); 566 } 567 PPItemKey(StringHandle Name, HeaderHandle File, int Line, int Column) 568 : Name(Name), File(File), Line(Line), Column(Column) {} 569 PPItemKey(const PPItemKey &Other) 570 : Name(Other.Name), File(Other.File), Line(Other.Line), 571 Column(Other.Column) {} 572 PPItemKey() : File(HeaderHandleInvalid), Line(0), Column(0) {} 573 bool operator==(const PPItemKey &Other) const { 574 if (Name != Other.Name) 575 return false; 576 if (File != Other.File) 577 return false; 578 if (Line != Other.Line) 579 return false; 580 return Column == Other.Column; 581 } 582 bool operator<(const PPItemKey &Other) const { 583 if (Name < Other.Name) 584 return true; 585 else if (Name > Other.Name) 586 return false; 587 if (File < Other.File) 588 return true; 589 else if (File > Other.File) 590 return false; 591 if (Line < Other.Line) 592 return true; 593 else if (Line > Other.Line) 594 return false; 595 return Column < Other.Column; 596 } 597 StringHandle Name; 598 HeaderHandle File; 599 int Line; 600 int Column; 601 }; 602 603 // Header inclusion path. 604 class HeaderInclusionPath { 605 public: 606 HeaderInclusionPath(std::vector<HeaderHandle> HeaderInclusionPath) 607 : Path(HeaderInclusionPath) {} 608 HeaderInclusionPath(const HeaderInclusionPath &Other) : Path(Other.Path) {} 609 HeaderInclusionPath() {} 610 std::vector<HeaderHandle> Path; 611 }; 612 613 // Macro expansion instance. 614 // 615 // This class represents an instance of a macro expansion with a 616 // unique value. It also stores the unique header inclusion paths 617 // for use in telling the user the nested include path to the header. 618 class MacroExpansionInstance { 619 public: 620 MacroExpansionInstance(StringHandle MacroExpanded, 621 PPItemKey &DefinitionLocation, 622 StringHandle DefinitionSourceLine, 623 InclusionPathHandle H) 624 : MacroExpanded(MacroExpanded), DefinitionLocation(DefinitionLocation), 625 DefinitionSourceLine(DefinitionSourceLine) { 626 InclusionPathHandles.push_back(H); 627 } 628 MacroExpansionInstance() {} 629 630 // Check for the presence of a header inclusion path handle entry. 631 // Return false if not found. 632 bool haveInclusionPathHandle(InclusionPathHandle H) { 633 for (std::vector<InclusionPathHandle>::iterator 634 I = InclusionPathHandles.begin(), 635 E = InclusionPathHandles.end(); 636 I != E; ++I) { 637 if (*I == H) 638 return true; 639 } 640 return InclusionPathHandleInvalid; 641 } 642 // Add a new header inclusion path entry, if not already present. 643 void addInclusionPathHandle(InclusionPathHandle H) { 644 if (!haveInclusionPathHandle(H)) 645 InclusionPathHandles.push_back(H); 646 } 647 648 // A string representing the macro instance after preprocessing. 649 StringHandle MacroExpanded; 650 // A file/line/column triplet representing the macro definition location. 651 PPItemKey DefinitionLocation; 652 // A place to save the macro definition line string. 653 StringHandle DefinitionSourceLine; 654 // The header inclusion path handles for all the instances. 655 std::vector<InclusionPathHandle> InclusionPathHandles; 656 }; 657 658 // Macro expansion instance tracker. 659 // 660 // This class represents one macro expansion, keyed by a PPItemKey. 661 // It stores a string representing the macro reference in the source, 662 // and a list of ConditionalExpansionInstances objects representing 663 // the unique values the condition expands to in instances of the header. 664 class MacroExpansionTracker { 665 public: 666 MacroExpansionTracker(StringHandle MacroUnexpanded, 667 StringHandle MacroExpanded, 668 StringHandle InstanceSourceLine, 669 PPItemKey &DefinitionLocation, 670 StringHandle DefinitionSourceLine, 671 InclusionPathHandle InclusionPathHandle) 672 : MacroUnexpanded(MacroUnexpanded), 673 InstanceSourceLine(InstanceSourceLine) { 674 addMacroExpansionInstance(MacroExpanded, DefinitionLocation, 675 DefinitionSourceLine, InclusionPathHandle); 676 } 677 MacroExpansionTracker() {} 678 679 // Find a matching macro expansion instance. 680 MacroExpansionInstance * 681 findMacroExpansionInstance(StringHandle MacroExpanded, 682 PPItemKey &DefinitionLocation) { 683 for (std::vector<MacroExpansionInstance>::iterator 684 I = MacroExpansionInstances.begin(), 685 E = MacroExpansionInstances.end(); 686 I != E; ++I) { 687 if ((I->MacroExpanded == MacroExpanded) && 688 (I->DefinitionLocation == DefinitionLocation)) { 689 return &*I; // Found. 690 } 691 } 692 return nullptr; // Not found. 693 } 694 695 // Add a macro expansion instance. 696 void addMacroExpansionInstance(StringHandle MacroExpanded, 697 PPItemKey &DefinitionLocation, 698 StringHandle DefinitionSourceLine, 699 InclusionPathHandle InclusionPathHandle) { 700 MacroExpansionInstances.push_back( 701 MacroExpansionInstance(MacroExpanded, DefinitionLocation, 702 DefinitionSourceLine, InclusionPathHandle)); 703 } 704 705 // Return true if there is a mismatch. 706 bool hasMismatch() { return MacroExpansionInstances.size() > 1; } 707 708 // A string representing the macro instance without expansion. 709 StringHandle MacroUnexpanded; 710 // A place to save the macro instance source line string. 711 StringHandle InstanceSourceLine; 712 // The macro expansion instances. 713 // If all instances of the macro expansion expand to the same value, 714 // This vector will only have one instance. 715 std::vector<MacroExpansionInstance> MacroExpansionInstances; 716 }; 717 718 // Conditional expansion instance. 719 // 720 // This class represents an instance of a condition exoression result 721 // with a unique value. It also stores the unique header inclusion paths 722 // for use in telling the user the nested include path to the header. 723 class ConditionalExpansionInstance { 724 public: 725 ConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind ConditionValue, InclusionPathHandle H) 726 : ConditionValue(ConditionValue) { 727 InclusionPathHandles.push_back(H); 728 } 729 ConditionalExpansionInstance() {} 730 731 // Check for the presence of a header inclusion path handle entry. 732 // Return false if not found. 733 bool haveInclusionPathHandle(InclusionPathHandle H) { 734 for (std::vector<InclusionPathHandle>::iterator 735 I = InclusionPathHandles.begin(), 736 E = InclusionPathHandles.end(); 737 I != E; ++I) { 738 if (*I == H) 739 return true; 740 } 741 return InclusionPathHandleInvalid; 742 } 743 // Add a new header inclusion path entry, if not already present. 744 void addInclusionPathHandle(InclusionPathHandle H) { 745 if (!haveInclusionPathHandle(H)) 746 InclusionPathHandles.push_back(H); 747 } 748 749 // A flag representing the evaluated condition value. 750 clang::PPCallbacks::ConditionValueKind ConditionValue; 751 // The header inclusion path handles for all the instances. 752 std::vector<InclusionPathHandle> InclusionPathHandles; 753 }; 754 755 // Conditional directive instance tracker. 756 // 757 // This class represents one conditional directive, keyed by a PPItemKey. 758 // It stores a string representing the macro reference in the source, 759 // and a list of ConditionExpansionInstance objects representing 760 // the unique value the condition expression expands to in instances of 761 // the header. 762 class ConditionalTracker { 763 public: 764 ConditionalTracker(clang::tok::PPKeywordKind DirectiveKind, 765 clang::PPCallbacks::ConditionValueKind ConditionValue, 766 StringHandle ConditionUnexpanded, 767 InclusionPathHandle InclusionPathHandle) 768 : DirectiveKind(DirectiveKind), ConditionUnexpanded(ConditionUnexpanded) { 769 addConditionalExpansionInstance(ConditionValue, InclusionPathHandle); 770 } 771 ConditionalTracker() {} 772 773 // Find a matching condition expansion instance. 774 ConditionalExpansionInstance * 775 findConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind ConditionValue) { 776 for (std::vector<ConditionalExpansionInstance>::iterator 777 I = ConditionalExpansionInstances.begin(), 778 E = ConditionalExpansionInstances.end(); 779 I != E; ++I) { 780 if (I->ConditionValue == ConditionValue) { 781 return &*I; // Found. 782 } 783 } 784 return nullptr; // Not found. 785 } 786 787 // Add a conditional expansion instance. 788 void 789 addConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind ConditionValue, 790 InclusionPathHandle InclusionPathHandle) { 791 ConditionalExpansionInstances.push_back( 792 ConditionalExpansionInstance(ConditionValue, InclusionPathHandle)); 793 } 794 795 // Return true if there is a mismatch. 796 bool hasMismatch() { return ConditionalExpansionInstances.size() > 1; } 797 798 // The kind of directive. 799 clang::tok::PPKeywordKind DirectiveKind; 800 // A string representing the macro instance without expansion. 801 StringHandle ConditionUnexpanded; 802 // The condition expansion instances. 803 // If all instances of the conditional expression expand to the same value, 804 // This vector will only have one instance. 805 std::vector<ConditionalExpansionInstance> ConditionalExpansionInstances; 806 }; 807 808 // Preprocessor callbacks for modularize. 809 // 810 // This class derives from the Clang PPCallbacks class to track preprocessor 811 // actions, such as changing files and handling preprocessor directives and 812 // macro expansions. It has to figure out when a new header file is entered 813 // and left, as the provided handler is not particularly clear about it. 814 class PreprocessorCallbacks : public clang::PPCallbacks { 815 public: 816 PreprocessorCallbacks(PreprocessorTrackerImpl &ppTracker, 817 clang::Preprocessor &PP, llvm::StringRef rootHeaderFile) 818 : PPTracker(ppTracker), PP(PP), RootHeaderFile(rootHeaderFile) {} 819 ~PreprocessorCallbacks() {} 820 821 // Overridden handlers. 822 void InclusionDirective(clang::SourceLocation HashLoc, 823 const clang::Token &IncludeTok, 824 llvm::StringRef FileName, bool IsAngled, 825 clang::CharSourceRange FilenameRange, 826 const clang::FileEntry *File, 827 llvm::StringRef SearchPath, 828 llvm::StringRef RelativePath, 829 const clang::Module *Imported); 830 void FileChanged(clang::SourceLocation Loc, 831 clang::PPCallbacks::FileChangeReason Reason, 832 clang::SrcMgr::CharacteristicKind FileType, 833 clang::FileID PrevFID = clang::FileID()); 834 void MacroExpands(const clang::Token &MacroNameTok, 835 const clang::MacroDirective *MD, clang::SourceRange Range, 836 const clang::MacroArgs *Args); 837 void Defined(const clang::Token &MacroNameTok, 838 const clang::MacroDirective *MD, clang::SourceRange Range); 839 void If(clang::SourceLocation Loc, clang::SourceRange ConditionRange, 840 clang::PPCallbacks::ConditionValueKind ConditionResult); 841 void Elif(clang::SourceLocation Loc, clang::SourceRange ConditionRange, 842 clang::PPCallbacks::ConditionValueKind ConditionResult, clang::SourceLocation IfLoc); 843 void Ifdef(clang::SourceLocation Loc, const clang::Token &MacroNameTok, 844 const clang::MacroDirective *MD); 845 void Ifndef(clang::SourceLocation Loc, const clang::Token &MacroNameTok, 846 const clang::MacroDirective *MD); 847 848 private: 849 PreprocessorTrackerImpl &PPTracker; 850 clang::Preprocessor &PP; 851 std::string RootHeaderFile; 852 }; 853 854 // Preprocessor macro expansion item map types. 855 typedef std::map<PPItemKey, MacroExpansionTracker> MacroExpansionMap; 856 typedef std::map<PPItemKey, MacroExpansionTracker>::iterator 857 MacroExpansionMapIter; 858 859 // Preprocessor conditional expansion item map types. 860 typedef std::map<PPItemKey, ConditionalTracker> ConditionalExpansionMap; 861 typedef std::map<PPItemKey, ConditionalTracker>::iterator 862 ConditionalExpansionMapIter; 863 864 // Preprocessor tracker for modularize. 865 // 866 // This class stores information about all the headers processed in the 867 // course of running modularize. 868 class PreprocessorTrackerImpl : public PreprocessorTracker { 869 public: 870 PreprocessorTrackerImpl(llvm::SmallVector<std::string, 32> &Headers, 871 bool DoBlockCheckHeaderListOnly) 872 : BlockCheckHeaderListOnly(DoBlockCheckHeaderListOnly), 873 CurrentInclusionPathHandle(InclusionPathHandleInvalid), 874 InNestedHeader(false) { 875 // Use canonical header path representation. 876 for (llvm::ArrayRef<std::string>::iterator I = Headers.begin(), 877 E = Headers.end(); 878 I != E; ++I) { 879 HeaderList.push_back(getCanonicalPath(*I)); 880 } 881 } 882 883 ~PreprocessorTrackerImpl() {} 884 885 // Handle entering a preprocessing session. 886 void handlePreprocessorEntry(clang::Preprocessor &PP, 887 llvm::StringRef rootHeaderFile) { 888 HeadersInThisCompile.clear(); 889 assert((HeaderStack.size() == 0) && "Header stack should be empty."); 890 pushHeaderHandle(addHeader(rootHeaderFile)); 891 PP.addPPCallbacks(llvm::make_unique<PreprocessorCallbacks>(*this, PP, 892 rootHeaderFile)); 893 } 894 // Handle exiting a preprocessing session. 895 void handlePreprocessorExit() { HeaderStack.clear(); } 896 897 // Handle include directive. 898 // This function is called every time an include directive is seen by the 899 // preprocessor, for the purpose of later checking for 'extern "" {}' or 900 // "namespace {}" blocks containing #include directives. 901 void handleIncludeDirective(llvm::StringRef DirectivePath, int DirectiveLine, 902 int DirectiveColumn, llvm::StringRef TargetPath) { 903 // If it's not a header in the header list, ignore it with respect to 904 // the check. 905 if (BlockCheckHeaderListOnly && !isHeaderListHeader(TargetPath)) 906 return; 907 HeaderHandle CurrentHeaderHandle = findHeaderHandle(DirectivePath); 908 StringHandle IncludeHeaderHandle = addString(TargetPath); 909 for (std::vector<PPItemKey>::const_iterator I = IncludeDirectives.begin(), 910 E = IncludeDirectives.end(); 911 I != E; ++I) { 912 // If we already have an entry for this directive, return now. 913 if ((I->File == CurrentHeaderHandle) && (I->Line == DirectiveLine)) 914 return; 915 } 916 PPItemKey IncludeDirectiveItem(IncludeHeaderHandle, CurrentHeaderHandle, 917 DirectiveLine, DirectiveColumn); 918 IncludeDirectives.push_back(IncludeDirectiveItem); 919 } 920 921 // Check for include directives within the given source line range. 922 // Report errors if any found. Returns true if no include directives 923 // found in block. 924 bool checkForIncludesInBlock(clang::Preprocessor &PP, 925 clang::SourceRange BlockSourceRange, 926 const char *BlockIdentifierMessage, 927 llvm::raw_ostream &OS) { 928 clang::SourceLocation BlockStartLoc = BlockSourceRange.getBegin(); 929 clang::SourceLocation BlockEndLoc = BlockSourceRange.getEnd(); 930 // Use block location to get FileID of both the include directive 931 // and block statement. 932 clang::FileID FileID = PP.getSourceManager().getFileID(BlockStartLoc); 933 std::string SourcePath = getSourceLocationFile(PP, BlockStartLoc); 934 SourcePath = ModularizeUtilities::getCanonicalPath(SourcePath); 935 HeaderHandle SourceHandle = findHeaderHandle(SourcePath); 936 if (SourceHandle == -1) 937 return true; 938 int BlockStartLine, BlockStartColumn, BlockEndLine, BlockEndColumn; 939 bool returnValue = true; 940 getSourceLocationLineAndColumn(PP, BlockStartLoc, BlockStartLine, 941 BlockStartColumn); 942 getSourceLocationLineAndColumn(PP, BlockEndLoc, BlockEndLine, 943 BlockEndColumn); 944 for (std::vector<PPItemKey>::const_iterator I = IncludeDirectives.begin(), 945 E = IncludeDirectives.end(); 946 I != E; ++I) { 947 // If we find an entry within the block, report an error. 948 if ((I->File == SourceHandle) && (I->Line >= BlockStartLine) && 949 (I->Line < BlockEndLine)) { 950 returnValue = false; 951 OS << SourcePath << ":" << I->Line << ":" << I->Column << ":\n"; 952 OS << getSourceLine(PP, FileID, I->Line) << "\n"; 953 if (I->Column > 0) 954 OS << std::string(I->Column - 1, ' ') << "^\n"; 955 OS << "error: Include directive within " << BlockIdentifierMessage 956 << ".\n"; 957 OS << SourcePath << ":" << BlockStartLine << ":" << BlockStartColumn 958 << ":\n"; 959 OS << getSourceLine(PP, BlockStartLoc) << "\n"; 960 if (BlockStartColumn > 0) 961 OS << std::string(BlockStartColumn - 1, ' ') << "^\n"; 962 OS << "The \"" << BlockIdentifierMessage << "\" block is here.\n"; 963 } 964 } 965 return returnValue; 966 } 967 968 // Handle entering a header source file. 969 void handleHeaderEntry(clang::Preprocessor &PP, llvm::StringRef HeaderPath) { 970 // Ignore <built-in> and <command-line> to reduce message clutter. 971 if (HeaderPath.startswith("<")) 972 return; 973 HeaderHandle H = addHeader(HeaderPath); 974 if (H != getCurrentHeaderHandle()) 975 pushHeaderHandle(H); 976 // Check for nested header. 977 if (!InNestedHeader) 978 InNestedHeader = !HeadersInThisCompile.insert(H).second; 979 } 980 981 // Handle exiting a header source file. 982 void handleHeaderExit(llvm::StringRef HeaderPath) { 983 // Ignore <built-in> and <command-line> to reduce message clutter. 984 if (HeaderPath.startswith("<")) 985 return; 986 HeaderHandle H = findHeaderHandle(HeaderPath); 987 HeaderHandle TH; 988 if (isHeaderHandleInStack(H)) { 989 do { 990 TH = getCurrentHeaderHandle(); 991 popHeaderHandle(); 992 } while ((TH != H) && (HeaderStack.size() != 0)); 993 } 994 InNestedHeader = false; 995 } 996 997 // Lookup/add string. 998 StringHandle addString(llvm::StringRef Str) { return Strings.intern(Str); } 999 1000 // Convert to a canonical path. 1001 std::string getCanonicalPath(llvm::StringRef path) const { 1002 std::string CanonicalPath(path); 1003 std::replace(CanonicalPath.begin(), CanonicalPath.end(), '\\', '/'); 1004 return CanonicalPath; 1005 } 1006 1007 // Return true if the given header is in the header list. 1008 bool isHeaderListHeader(llvm::StringRef HeaderPath) const { 1009 std::string CanonicalPath = getCanonicalPath(HeaderPath); 1010 for (llvm::ArrayRef<std::string>::iterator I = HeaderList.begin(), 1011 E = HeaderList.end(); 1012 I != E; ++I) { 1013 if (*I == CanonicalPath) 1014 return true; 1015 } 1016 return false; 1017 } 1018 1019 // Get the handle of a header file entry. 1020 // Return HeaderHandleInvalid if not found. 1021 HeaderHandle findHeaderHandle(llvm::StringRef HeaderPath) const { 1022 std::string CanonicalPath = getCanonicalPath(HeaderPath); 1023 HeaderHandle H = 0; 1024 for (std::vector<StringHandle>::const_iterator I = HeaderPaths.begin(), 1025 E = HeaderPaths.end(); 1026 I != E; ++I, ++H) { 1027 if (**I == CanonicalPath) 1028 return H; 1029 } 1030 return HeaderHandleInvalid; 1031 } 1032 1033 // Add a new header file entry, or return existing handle. 1034 // Return the header handle. 1035 HeaderHandle addHeader(llvm::StringRef HeaderPath) { 1036 std::string CanonicalPath = getCanonicalPath(HeaderPath); 1037 HeaderHandle H = findHeaderHandle(CanonicalPath); 1038 if (H == HeaderHandleInvalid) { 1039 H = HeaderPaths.size(); 1040 HeaderPaths.push_back(addString(CanonicalPath)); 1041 } 1042 return H; 1043 } 1044 1045 // Return a header file path string given its handle. 1046 StringHandle getHeaderFilePath(HeaderHandle H) const { 1047 if ((H >= 0) && (H < (HeaderHandle)HeaderPaths.size())) 1048 return HeaderPaths[H]; 1049 return StringHandle(); 1050 } 1051 1052 // Returns a handle to the inclusion path. 1053 InclusionPathHandle pushHeaderHandle(HeaderHandle H) { 1054 HeaderStack.push_back(H); 1055 return CurrentInclusionPathHandle = addInclusionPathHandle(HeaderStack); 1056 } 1057 // Pops the last header handle from the stack; 1058 void popHeaderHandle() { 1059 // assert((HeaderStack.size() != 0) && "Header stack already empty."); 1060 if (HeaderStack.size() != 0) { 1061 HeaderStack.pop_back(); 1062 CurrentInclusionPathHandle = addInclusionPathHandle(HeaderStack); 1063 } 1064 } 1065 // Get the top handle on the header stack. 1066 HeaderHandle getCurrentHeaderHandle() const { 1067 if (HeaderStack.size() != 0) 1068 return HeaderStack.back(); 1069 return HeaderHandleInvalid; 1070 } 1071 1072 // Check for presence of header handle in the header stack. 1073 bool isHeaderHandleInStack(HeaderHandle H) const { 1074 for (std::vector<HeaderHandle>::const_iterator I = HeaderStack.begin(), 1075 E = HeaderStack.end(); 1076 I != E; ++I) { 1077 if (*I == H) 1078 return true; 1079 } 1080 return false; 1081 } 1082 1083 // Get the handle of a header inclusion path entry. 1084 // Return InclusionPathHandleInvalid if not found. 1085 InclusionPathHandle 1086 findInclusionPathHandle(const std::vector<HeaderHandle> &Path) const { 1087 InclusionPathHandle H = 0; 1088 for (std::vector<HeaderInclusionPath>::const_iterator 1089 I = InclusionPaths.begin(), 1090 E = InclusionPaths.end(); 1091 I != E; ++I, ++H) { 1092 if (I->Path == Path) 1093 return H; 1094 } 1095 return HeaderHandleInvalid; 1096 } 1097 // Add a new header inclusion path entry, or return existing handle. 1098 // Return the header inclusion path entry handle. 1099 InclusionPathHandle 1100 addInclusionPathHandle(const std::vector<HeaderHandle> &Path) { 1101 InclusionPathHandle H = findInclusionPathHandle(Path); 1102 if (H == HeaderHandleInvalid) { 1103 H = InclusionPaths.size(); 1104 InclusionPaths.push_back(HeaderInclusionPath(Path)); 1105 } 1106 return H; 1107 } 1108 // Return the current inclusion path handle. 1109 InclusionPathHandle getCurrentInclusionPathHandle() const { 1110 return CurrentInclusionPathHandle; 1111 } 1112 1113 // Return an inclusion path given its handle. 1114 const std::vector<HeaderHandle> & 1115 getInclusionPath(InclusionPathHandle H) const { 1116 if ((H >= 0) && (H <= (InclusionPathHandle)InclusionPaths.size())) 1117 return InclusionPaths[H].Path; 1118 static std::vector<HeaderHandle> Empty; 1119 return Empty; 1120 } 1121 1122 // Add a macro expansion instance. 1123 void addMacroExpansionInstance(clang::Preprocessor &PP, HeaderHandle H, 1124 clang::SourceLocation InstanceLoc, 1125 clang::SourceLocation DefinitionLoc, 1126 clang::IdentifierInfo *II, 1127 llvm::StringRef MacroUnexpanded, 1128 llvm::StringRef MacroExpanded, 1129 InclusionPathHandle InclusionPathHandle) { 1130 if (InNestedHeader) 1131 return; 1132 StringHandle MacroName = addString(II->getName()); 1133 PPItemKey InstanceKey(PP, MacroName, H, InstanceLoc); 1134 PPItemKey DefinitionKey(PP, MacroName, H, DefinitionLoc); 1135 MacroExpansionMapIter I = MacroExpansions.find(InstanceKey); 1136 // If existing instance of expansion not found, add one. 1137 if (I == MacroExpansions.end()) { 1138 std::string InstanceSourceLine = 1139 getSourceLocationString(PP, InstanceLoc) + ":\n" + 1140 getSourceLine(PP, InstanceLoc) + "\n"; 1141 std::string DefinitionSourceLine = 1142 getSourceLocationString(PP, DefinitionLoc) + ":\n" + 1143 getSourceLine(PP, DefinitionLoc) + "\n"; 1144 MacroExpansions[InstanceKey] = MacroExpansionTracker( 1145 addString(MacroUnexpanded), addString(MacroExpanded), 1146 addString(InstanceSourceLine), DefinitionKey, 1147 addString(DefinitionSourceLine), InclusionPathHandle); 1148 } else { 1149 // We've seen the macro before. Get its tracker. 1150 MacroExpansionTracker &CondTracker = I->second; 1151 // Look up an existing instance value for the macro. 1152 MacroExpansionInstance *MacroInfo = 1153 CondTracker.findMacroExpansionInstance(addString(MacroExpanded), 1154 DefinitionKey); 1155 // If found, just add the inclusion path to the instance. 1156 if (MacroInfo) 1157 MacroInfo->addInclusionPathHandle(InclusionPathHandle); 1158 else { 1159 // Otherwise add a new instance with the unique value. 1160 std::string DefinitionSourceLine = 1161 getSourceLocationString(PP, DefinitionLoc) + ":\n" + 1162 getSourceLine(PP, DefinitionLoc) + "\n"; 1163 CondTracker.addMacroExpansionInstance( 1164 addString(MacroExpanded), DefinitionKey, 1165 addString(DefinitionSourceLine), InclusionPathHandle); 1166 } 1167 } 1168 } 1169 1170 // Add a conditional expansion instance. 1171 void 1172 addConditionalExpansionInstance(clang::Preprocessor &PP, HeaderHandle H, 1173 clang::SourceLocation InstanceLoc, 1174 clang::tok::PPKeywordKind DirectiveKind, 1175 clang::PPCallbacks::ConditionValueKind ConditionValue, 1176 llvm::StringRef ConditionUnexpanded, 1177 InclusionPathHandle InclusionPathHandle) { 1178 // Ignore header guards, assuming the header guard is the only conditional. 1179 if (InNestedHeader) 1180 return; 1181 StringHandle ConditionUnexpandedHandle(addString(ConditionUnexpanded)); 1182 PPItemKey InstanceKey(PP, ConditionUnexpandedHandle, H, InstanceLoc); 1183 ConditionalExpansionMapIter I = ConditionalExpansions.find(InstanceKey); 1184 // If existing instance of condition not found, add one. 1185 if (I == ConditionalExpansions.end()) { 1186 std::string InstanceSourceLine = 1187 getSourceLocationString(PP, InstanceLoc) + ":\n" + 1188 getSourceLine(PP, InstanceLoc) + "\n"; 1189 ConditionalExpansions[InstanceKey] = 1190 ConditionalTracker(DirectiveKind, ConditionValue, 1191 ConditionUnexpandedHandle, InclusionPathHandle); 1192 } else { 1193 // We've seen the conditional before. Get its tracker. 1194 ConditionalTracker &CondTracker = I->second; 1195 // Look up an existing instance value for the condition. 1196 ConditionalExpansionInstance *MacroInfo = 1197 CondTracker.findConditionalExpansionInstance(ConditionValue); 1198 // If found, just add the inclusion path to the instance. 1199 if (MacroInfo) 1200 MacroInfo->addInclusionPathHandle(InclusionPathHandle); 1201 else { 1202 // Otherwise add a new instance with the unique value. 1203 CondTracker.addConditionalExpansionInstance(ConditionValue, 1204 InclusionPathHandle); 1205 } 1206 } 1207 } 1208 1209 // Report on inconsistent macro instances. 1210 // Returns true if any mismatches. 1211 bool reportInconsistentMacros(llvm::raw_ostream &OS) { 1212 bool ReturnValue = false; 1213 // Walk all the macro expansion trackers in the map. 1214 for (MacroExpansionMapIter I = MacroExpansions.begin(), 1215 E = MacroExpansions.end(); 1216 I != E; ++I) { 1217 const PPItemKey &ItemKey = I->first; 1218 MacroExpansionTracker &MacroExpTracker = I->second; 1219 // If no mismatch (only one instance value) continue. 1220 if (!MacroExpTracker.hasMismatch()) 1221 continue; 1222 // Tell caller we found one or more errors. 1223 ReturnValue = true; 1224 // Start the error message. 1225 OS << *MacroExpTracker.InstanceSourceLine; 1226 if (ItemKey.Column > 0) 1227 OS << std::string(ItemKey.Column - 1, ' ') << "^\n"; 1228 OS << "error: Macro instance '" << *MacroExpTracker.MacroUnexpanded 1229 << "' has different values in this header, depending on how it was " 1230 "included.\n"; 1231 // Walk all the instances. 1232 for (std::vector<MacroExpansionInstance>::iterator 1233 IMT = MacroExpTracker.MacroExpansionInstances.begin(), 1234 EMT = MacroExpTracker.MacroExpansionInstances.end(); 1235 IMT != EMT; ++IMT) { 1236 MacroExpansionInstance &MacroInfo = *IMT; 1237 OS << " '" << *MacroExpTracker.MacroUnexpanded << "' expanded to: '" 1238 << *MacroInfo.MacroExpanded 1239 << "' with respect to these inclusion paths:\n"; 1240 // Walk all the inclusion path hierarchies. 1241 for (std::vector<InclusionPathHandle>::iterator 1242 IIP = MacroInfo.InclusionPathHandles.begin(), 1243 EIP = MacroInfo.InclusionPathHandles.end(); 1244 IIP != EIP; ++IIP) { 1245 const std::vector<HeaderHandle> &ip = getInclusionPath(*IIP); 1246 int Count = (int)ip.size(); 1247 for (int Index = 0; Index < Count; ++Index) { 1248 HeaderHandle H = ip[Index]; 1249 OS << std::string((Index * 2) + 4, ' ') << *getHeaderFilePath(H) 1250 << "\n"; 1251 } 1252 } 1253 // For a macro that wasn't defined, we flag it by using the 1254 // instance location. 1255 // If there is a definition... 1256 if (MacroInfo.DefinitionLocation.Line != ItemKey.Line) { 1257 OS << *MacroInfo.DefinitionSourceLine; 1258 if (MacroInfo.DefinitionLocation.Column > 0) 1259 OS << std::string(MacroInfo.DefinitionLocation.Column - 1, ' ') 1260 << "^\n"; 1261 OS << "Macro defined here.\n"; 1262 } else 1263 OS << "(no macro definition)" 1264 << "\n"; 1265 } 1266 } 1267 return ReturnValue; 1268 } 1269 1270 // Report on inconsistent conditional instances. 1271 // Returns true if any mismatches. 1272 bool reportInconsistentConditionals(llvm::raw_ostream &OS) { 1273 bool ReturnValue = false; 1274 // Walk all the conditional trackers in the map. 1275 for (ConditionalExpansionMapIter I = ConditionalExpansions.begin(), 1276 E = ConditionalExpansions.end(); 1277 I != E; ++I) { 1278 const PPItemKey &ItemKey = I->first; 1279 ConditionalTracker &CondTracker = I->second; 1280 if (!CondTracker.hasMismatch()) 1281 continue; 1282 // Tell caller we found one or more errors. 1283 ReturnValue = true; 1284 // Start the error message. 1285 OS << *HeaderPaths[ItemKey.File] << ":" << ItemKey.Line << ":" 1286 << ItemKey.Column << "\n"; 1287 OS << "#" << getDirectiveSpelling(CondTracker.DirectiveKind) << " " 1288 << *CondTracker.ConditionUnexpanded << "\n"; 1289 OS << "^\n"; 1290 OS << "error: Conditional expression instance '" 1291 << *CondTracker.ConditionUnexpanded 1292 << "' has different values in this header, depending on how it was " 1293 "included.\n"; 1294 // Walk all the instances. 1295 for (std::vector<ConditionalExpansionInstance>::iterator 1296 IMT = CondTracker.ConditionalExpansionInstances.begin(), 1297 EMT = CondTracker.ConditionalExpansionInstances.end(); 1298 IMT != EMT; ++IMT) { 1299 ConditionalExpansionInstance &MacroInfo = *IMT; 1300 OS << " '" << *CondTracker.ConditionUnexpanded << "' expanded to: '" 1301 << ConditionValueKindStrings[MacroInfo.ConditionValue] 1302 << "' with respect to these inclusion paths:\n"; 1303 // Walk all the inclusion path hierarchies. 1304 for (std::vector<InclusionPathHandle>::iterator 1305 IIP = MacroInfo.InclusionPathHandles.begin(), 1306 EIP = MacroInfo.InclusionPathHandles.end(); 1307 IIP != EIP; ++IIP) { 1308 const std::vector<HeaderHandle> &ip = getInclusionPath(*IIP); 1309 int Count = (int)ip.size(); 1310 for (int Index = 0; Index < Count; ++Index) { 1311 HeaderHandle H = ip[Index]; 1312 OS << std::string((Index * 2) + 4, ' ') << *getHeaderFilePath(H) 1313 << "\n"; 1314 } 1315 } 1316 } 1317 } 1318 return ReturnValue; 1319 } 1320 1321 // Get directive spelling. 1322 static const char *getDirectiveSpelling(clang::tok::PPKeywordKind kind) { 1323 switch (kind) { 1324 case clang::tok::pp_if: 1325 return "if"; 1326 case clang::tok::pp_elif: 1327 return "elif"; 1328 case clang::tok::pp_ifdef: 1329 return "ifdef"; 1330 case clang::tok::pp_ifndef: 1331 return "ifndef"; 1332 default: 1333 return "(unknown)"; 1334 } 1335 } 1336 1337 private: 1338 llvm::SmallVector<std::string, 32> HeaderList; 1339 // Only do extern, namespace check for headers in HeaderList. 1340 bool BlockCheckHeaderListOnly; 1341 llvm::StringPool Strings; 1342 std::vector<StringHandle> HeaderPaths; 1343 std::vector<HeaderHandle> HeaderStack; 1344 std::vector<HeaderInclusionPath> InclusionPaths; 1345 InclusionPathHandle CurrentInclusionPathHandle; 1346 llvm::SmallSet<HeaderHandle, 128> HeadersInThisCompile; 1347 std::vector<PPItemKey> IncludeDirectives; 1348 MacroExpansionMap MacroExpansions; 1349 ConditionalExpansionMap ConditionalExpansions; 1350 bool InNestedHeader; 1351 }; 1352 1353 // PreprocessorTracker functions. 1354 1355 // PreprocessorTracker desctructor. 1356 PreprocessorTracker::~PreprocessorTracker() {} 1357 1358 // Create instance of PreprocessorTracker. 1359 PreprocessorTracker *PreprocessorTracker::create( 1360 llvm::SmallVector<std::string, 32> &Headers, 1361 bool DoBlockCheckHeaderListOnly) { 1362 return new PreprocessorTrackerImpl(Headers, DoBlockCheckHeaderListOnly); 1363 } 1364 1365 // Preprocessor callbacks for modularize. 1366 1367 // Handle include directive. 1368 void PreprocessorCallbacks::InclusionDirective( 1369 clang::SourceLocation HashLoc, const clang::Token &IncludeTok, 1370 llvm::StringRef FileName, bool IsAngled, 1371 clang::CharSourceRange FilenameRange, const clang::FileEntry *File, 1372 llvm::StringRef SearchPath, llvm::StringRef RelativePath, 1373 const clang::Module *Imported) { 1374 int DirectiveLine, DirectiveColumn; 1375 std::string HeaderPath = getSourceLocationFile(PP, HashLoc); 1376 getSourceLocationLineAndColumn(PP, HashLoc, DirectiveLine, DirectiveColumn); 1377 PPTracker.handleIncludeDirective(HeaderPath, DirectiveLine, DirectiveColumn, 1378 FileName); 1379 } 1380 1381 // Handle file entry/exit. 1382 void PreprocessorCallbacks::FileChanged( 1383 clang::SourceLocation Loc, clang::PPCallbacks::FileChangeReason Reason, 1384 clang::SrcMgr::CharacteristicKind FileType, clang::FileID PrevFID) { 1385 switch (Reason) { 1386 case EnterFile: 1387 PPTracker.handleHeaderEntry(PP, getSourceLocationFile(PP, Loc)); 1388 break; 1389 case ExitFile: { 1390 const clang::FileEntry *F = 1391 PP.getSourceManager().getFileEntryForID(PrevFID); 1392 if (F) 1393 PPTracker.handleHeaderExit(F->getName()); 1394 } break; 1395 case SystemHeaderPragma: 1396 case RenameFile: 1397 break; 1398 } 1399 } 1400 1401 // Handle macro expansion. 1402 void PreprocessorCallbacks::MacroExpands(const clang::Token &MacroNameTok, 1403 const clang::MacroDirective *MD, 1404 clang::SourceRange Range, 1405 const clang::MacroArgs *Args) { 1406 clang::SourceLocation Loc = Range.getBegin(); 1407 // Ignore macro argument expansions. 1408 if (!Loc.isFileID()) 1409 return; 1410 clang::IdentifierInfo *II = MacroNameTok.getIdentifierInfo(); 1411 const clang::MacroInfo *MI = PP.getMacroInfo(II); 1412 std::string MacroName = II->getName().str(); 1413 std::string Unexpanded(getMacroUnexpandedString(Range, PP, MacroName, MI)); 1414 std::string Expanded(getMacroExpandedString(PP, MacroName, MI, Args)); 1415 PPTracker.addMacroExpansionInstance( 1416 PP, PPTracker.getCurrentHeaderHandle(), Loc, MI->getDefinitionLoc(), II, 1417 Unexpanded, Expanded, PPTracker.getCurrentInclusionPathHandle()); 1418 } 1419 1420 void PreprocessorCallbacks::Defined(const clang::Token &MacroNameTok, 1421 const clang::MacroDirective *MD, 1422 clang::SourceRange Range) { 1423 clang::SourceLocation Loc(Range.getBegin()); 1424 clang::IdentifierInfo *II = MacroNameTok.getIdentifierInfo(); 1425 const clang::MacroInfo *MI = PP.getMacroInfo(II); 1426 std::string MacroName = II->getName().str(); 1427 std::string Unexpanded(getSourceString(PP, Range)); 1428 PPTracker.addMacroExpansionInstance( 1429 PP, PPTracker.getCurrentHeaderHandle(), Loc, 1430 (MI ? MI->getDefinitionLoc() : Loc), II, Unexpanded, 1431 (MI ? "true" : "false"), PPTracker.getCurrentInclusionPathHandle()); 1432 } 1433 1434 void PreprocessorCallbacks::If(clang::SourceLocation Loc, 1435 clang::SourceRange ConditionRange, 1436 clang::PPCallbacks::ConditionValueKind ConditionResult) { 1437 std::string Unexpanded(getSourceString(PP, ConditionRange)); 1438 PPTracker.addConditionalExpansionInstance( 1439 PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_if, 1440 ConditionResult, Unexpanded, PPTracker.getCurrentInclusionPathHandle()); 1441 } 1442 1443 void PreprocessorCallbacks::Elif(clang::SourceLocation Loc, 1444 clang::SourceRange ConditionRange, 1445 clang::PPCallbacks::ConditionValueKind ConditionResult, 1446 clang::SourceLocation IfLoc) { 1447 std::string Unexpanded(getSourceString(PP, ConditionRange)); 1448 PPTracker.addConditionalExpansionInstance( 1449 PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_elif, 1450 ConditionResult, Unexpanded, PPTracker.getCurrentInclusionPathHandle()); 1451 } 1452 1453 void PreprocessorCallbacks::Ifdef(clang::SourceLocation Loc, 1454 const clang::Token &MacroNameTok, 1455 const clang::MacroDirective *MD) { 1456 clang::PPCallbacks::ConditionValueKind IsDefined = 1457 (MD ? clang::PPCallbacks::CVK_True : clang::PPCallbacks::CVK_False ); 1458 PPTracker.addConditionalExpansionInstance( 1459 PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_ifdef, 1460 IsDefined, PP.getSpelling(MacroNameTok), 1461 PPTracker.getCurrentInclusionPathHandle()); 1462 } 1463 1464 void PreprocessorCallbacks::Ifndef(clang::SourceLocation Loc, 1465 const clang::Token &MacroNameTok, 1466 const clang::MacroDirective *MD) { 1467 clang::PPCallbacks::ConditionValueKind IsNotDefined = 1468 (!MD ? clang::PPCallbacks::CVK_True : clang::PPCallbacks::CVK_False ); 1469 PPTracker.addConditionalExpansionInstance( 1470 PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_ifndef, 1471 IsNotDefined, PP.getSpelling(MacroNameTok), 1472 PPTracker.getCurrentInclusionPathHandle()); 1473 } 1474 } // end namespace Modularize 1475