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 255 namespace Modularize { 256 257 // Forwards. 258 class PreprocessorTrackerImpl; 259 260 // Some handle types 261 typedef llvm::PooledStringPtr StringHandle; 262 263 typedef int HeaderHandle; 264 const HeaderHandle HeaderHandleInvalid = -1; 265 266 typedef int InclusionPathHandle; 267 const InclusionPathHandle InclusionPathHandleInvalid = -1; 268 269 // Some utility functions. 270 271 // Get a "file:line:column" source location string. 272 static std::string getSourceLocationString(clang::Preprocessor &PP, 273 clang::SourceLocation Loc) { 274 if (Loc.isInvalid()) 275 return std::string("(none)"); 276 else 277 return Loc.printToString(PP.getSourceManager()); 278 } 279 280 // Get just the file name from a source location. 281 static std::string getSourceLocationFile(clang::Preprocessor &PP, 282 clang::SourceLocation Loc) { 283 std::string Source(getSourceLocationString(PP, Loc)); 284 size_t Offset = Source.find(':', 2); 285 if (Offset == std::string::npos) 286 return Source; 287 return Source.substr(0, Offset); 288 } 289 290 // Get just the line and column from a source location. 291 static void getSourceLocationLineAndColumn(clang::Preprocessor &PP, 292 clang::SourceLocation Loc, int &Line, 293 int &Column) { 294 clang::PresumedLoc PLoc = PP.getSourceManager().getPresumedLoc(Loc); 295 if (PLoc.isInvalid()) { 296 Line = 0; 297 Column = 0; 298 return; 299 } 300 Line = PLoc.getLine(); 301 Column = PLoc.getColumn(); 302 } 303 304 // Retrieve source snippet from file image. 305 std::string getSourceString(clang::Preprocessor &PP, clang::SourceRange Range) { 306 clang::SourceLocation BeginLoc = Range.getBegin(); 307 clang::SourceLocation EndLoc = Range.getEnd(); 308 const char *BeginPtr = PP.getSourceManager().getCharacterData(BeginLoc); 309 const char *EndPtr = PP.getSourceManager().getCharacterData(EndLoc); 310 size_t Length = EndPtr - BeginPtr; 311 return llvm::StringRef(BeginPtr, Length).trim().str(); 312 } 313 314 // Retrieve source line from file image given a location. 315 std::string getSourceLine(clang::Preprocessor &PP, clang::SourceLocation Loc) { 316 const llvm::MemoryBuffer *MemBuffer = 317 PP.getSourceManager().getBuffer(PP.getSourceManager().getFileID(Loc)); 318 const char *Buffer = MemBuffer->getBufferStart(); 319 const char *BufferEnd = MemBuffer->getBufferEnd(); 320 const char *BeginPtr = PP.getSourceManager().getCharacterData(Loc); 321 const char *EndPtr = BeginPtr; 322 while (BeginPtr > Buffer) { 323 if (*BeginPtr == '\n') { 324 BeginPtr++; 325 break; 326 } 327 BeginPtr--; 328 } 329 while (EndPtr < BufferEnd) { 330 if (*EndPtr == '\n') { 331 break; 332 } 333 EndPtr++; 334 } 335 size_t Length = EndPtr - BeginPtr; 336 return llvm::StringRef(BeginPtr, Length).str(); 337 } 338 339 // Retrieve source line from file image given a file ID and line number. 340 std::string getSourceLine(clang::Preprocessor &PP, clang::FileID FileID, 341 int Line) { 342 const llvm::MemoryBuffer *MemBuffer = PP.getSourceManager().getBuffer(FileID); 343 const char *Buffer = MemBuffer->getBufferStart(); 344 const char *BufferEnd = MemBuffer->getBufferEnd(); 345 const char *BeginPtr = Buffer; 346 const char *EndPtr = BufferEnd; 347 int LineCounter = 1; 348 if (Line == 1) 349 BeginPtr = Buffer; 350 else { 351 while (Buffer < BufferEnd) { 352 if (*Buffer == '\n') { 353 if (++LineCounter == Line) { 354 BeginPtr = Buffer++ + 1; 355 break; 356 } 357 } 358 Buffer++; 359 } 360 } 361 while (Buffer < BufferEnd) { 362 if (*Buffer == '\n') { 363 EndPtr = Buffer; 364 break; 365 } 366 Buffer++; 367 } 368 size_t Length = EndPtr - BeginPtr; 369 return llvm::StringRef(BeginPtr, Length).str(); 370 } 371 372 // Get the string for the Unexpanded macro instance. 373 // The soureRange is expected to end at the last token 374 // for the macro instance, which in the case of a function-style 375 // macro will be a ')', but for an object-style macro, it 376 // will be the macro name itself. 377 std::string getMacroUnexpandedString(clang::SourceRange Range, 378 clang::Preprocessor &PP, 379 llvm::StringRef MacroName, 380 const clang::MacroInfo *MI) { 381 clang::SourceLocation BeginLoc(Range.getBegin()); 382 const char *BeginPtr = PP.getSourceManager().getCharacterData(BeginLoc); 383 size_t Length; 384 std::string Unexpanded; 385 if (MI->isFunctionLike()) { 386 clang::SourceLocation EndLoc(Range.getEnd()); 387 const char *EndPtr = PP.getSourceManager().getCharacterData(EndLoc) + 1; 388 Length = (EndPtr - BeginPtr) + 1; // +1 is ')' width. 389 } else 390 Length = MacroName.size(); 391 return llvm::StringRef(BeginPtr, Length).trim().str(); 392 } 393 394 // Get the expansion for a macro instance, given the information 395 // provided by PPCallbacks. 396 // FIXME: This doesn't support function-style macro instances 397 // passed as arguments to another function-style macro. However, 398 // since it still expands the inner arguments, it still 399 // allows modularize to effectively work with respect to macro 400 // consistency checking, although it displays the incorrect 401 // expansion in error messages. 402 std::string getMacroExpandedString(clang::Preprocessor &PP, 403 llvm::StringRef MacroName, 404 const clang::MacroInfo *MI, 405 const clang::MacroArgs *Args) { 406 std::string Expanded; 407 // Walk over the macro Tokens. 408 typedef clang::MacroInfo::tokens_iterator Iter; 409 for (Iter I = MI->tokens_begin(), E = MI->tokens_end(); I != E; ++I) { 410 clang::IdentifierInfo *II = I->getIdentifierInfo(); 411 int ArgNo = (II && Args ? MI->getArgumentNum(II) : -1); 412 if (ArgNo == -1) { 413 // This isn't an argument, just add it. 414 if (II == NULL) 415 Expanded += PP.getSpelling((*I)); // Not an identifier. 416 else { 417 // Token is for an identifier. 418 std::string Name = II->getName().str(); 419 // Check for nexted macro references. 420 clang::MacroInfo *MacroInfo = PP.getMacroInfo(II); 421 if (MacroInfo != NULL) 422 Expanded += getMacroExpandedString(PP, Name, MacroInfo, NULL); 423 else 424 Expanded += Name; 425 } 426 continue; 427 } 428 // We get here if it's a function-style macro with arguments. 429 const clang::Token *ResultArgToks; 430 const clang::Token *ArgTok = Args->getUnexpArgument(ArgNo); 431 if (Args->ArgNeedsPreexpansion(ArgTok, PP)) 432 ResultArgToks = &(const_cast<clang::MacroArgs *>(Args)) 433 ->getPreExpArgument(ArgNo, MI, PP)[0]; 434 else 435 ResultArgToks = ArgTok; // Use non-preexpanded Tokens. 436 // If the arg token didn't expand into anything, ignore it. 437 if (ResultArgToks->is(clang::tok::eof)) 438 continue; 439 unsigned NumToks = clang::MacroArgs::getArgLength(ResultArgToks); 440 // Append the resulting argument expansions. 441 for (unsigned ArgumentIndex = 0; ArgumentIndex < NumToks; ++ArgumentIndex) { 442 const clang::Token &AT = ResultArgToks[ArgumentIndex]; 443 clang::IdentifierInfo *II = AT.getIdentifierInfo(); 444 if (II == NULL) 445 Expanded += PP.getSpelling(AT); // Not an identifier. 446 else { 447 // It's an identifier. Check for further expansion. 448 std::string Name = II->getName().str(); 449 clang::MacroInfo *MacroInfo = PP.getMacroInfo(II); 450 if (MacroInfo != NULL) 451 Expanded += getMacroExpandedString(PP, Name, MacroInfo, NULL); 452 else 453 Expanded += Name; 454 } 455 } 456 } 457 return Expanded; 458 } 459 460 // Get the string representing a vector of Tokens. 461 std::string 462 getTokensSpellingString(clang::Preprocessor &PP, 463 llvm::SmallVectorImpl<clang::Token> &Tokens) { 464 std::string Expanded; 465 // Walk over the macro Tokens. 466 typedef llvm::SmallVectorImpl<clang::Token>::iterator Iter; 467 for (Iter I = Tokens.begin(), E = Tokens.end(); I != E; ++I) 468 Expanded += PP.getSpelling(*I); // Not an identifier. 469 return llvm::StringRef(Expanded).trim().str(); 470 } 471 472 // Get the expansion for a macro instance, given the information 473 // provided by PPCallbacks. 474 std::string getExpandedString(clang::Preprocessor &PP, 475 llvm::StringRef MacroName, 476 const clang::MacroInfo *MI, 477 const clang::MacroArgs *Args) { 478 std::string Expanded; 479 // Walk over the macro Tokens. 480 typedef clang::MacroInfo::tokens_iterator Iter; 481 for (Iter I = MI->tokens_begin(), E = MI->tokens_end(); I != E; ++I) { 482 clang::IdentifierInfo *II = I->getIdentifierInfo(); 483 int ArgNo = (II && Args ? MI->getArgumentNum(II) : -1); 484 if (ArgNo == -1) { 485 // This isn't an argument, just add it. 486 if (II == NULL) 487 Expanded += PP.getSpelling((*I)); // Not an identifier. 488 else { 489 // Token is for an identifier. 490 std::string Name = II->getName().str(); 491 // Check for nexted macro references. 492 clang::MacroInfo *MacroInfo = PP.getMacroInfo(II); 493 if (MacroInfo != NULL) 494 Expanded += getMacroExpandedString(PP, Name, MacroInfo, NULL); 495 else 496 Expanded += Name; 497 } 498 continue; 499 } 500 // We get here if it's a function-style macro with arguments. 501 const clang::Token *ResultArgToks; 502 const clang::Token *ArgTok = Args->getUnexpArgument(ArgNo); 503 if (Args->ArgNeedsPreexpansion(ArgTok, PP)) 504 ResultArgToks = &(const_cast<clang::MacroArgs *>(Args)) 505 ->getPreExpArgument(ArgNo, MI, PP)[0]; 506 else 507 ResultArgToks = ArgTok; // Use non-preexpanded Tokens. 508 // If the arg token didn't expand into anything, ignore it. 509 if (ResultArgToks->is(clang::tok::eof)) 510 continue; 511 unsigned NumToks = clang::MacroArgs::getArgLength(ResultArgToks); 512 // Append the resulting argument expansions. 513 for (unsigned ArgumentIndex = 0; ArgumentIndex < NumToks; ++ArgumentIndex) { 514 const clang::Token &AT = ResultArgToks[ArgumentIndex]; 515 clang::IdentifierInfo *II = AT.getIdentifierInfo(); 516 if (II == NULL) 517 Expanded += PP.getSpelling(AT); // Not an identifier. 518 else { 519 // It's an identifier. Check for further expansion. 520 std::string Name = II->getName().str(); 521 clang::MacroInfo *MacroInfo = PP.getMacroInfo(II); 522 if (MacroInfo != NULL) 523 Expanded += getMacroExpandedString(PP, Name, MacroInfo, NULL); 524 else 525 Expanded += Name; 526 } 527 } 528 } 529 return Expanded; 530 } 531 532 // ConditionValueKind strings. 533 const char * 534 ConditionValueKindStrings[] = { 535 "(not evaluated)", "false", "true" 536 }; 537 538 // We need some operator overloads for string handles. 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 bool operator<(const StringHandle &H1, const StringHandle &H2) { 552 const char *S1 = (H1 ? *H1 : ""); 553 const char *S2 = (H2 ? *H2 : ""); 554 int Diff = strcmp(S1, S2); 555 return Diff < 0; 556 } 557 bool operator>(const StringHandle &H1, const StringHandle &H2) { 558 const char *S1 = (H1 ? *H1 : ""); 559 const char *S2 = (H2 ? *H2 : ""); 560 int Diff = strcmp(S1, S2); 561 return Diff > 0; 562 } 563 564 // Preprocessor item key. 565 // 566 // This class represents a location in a source file, for use 567 // as a key representing a unique name/file/line/column quadruplet, 568 // which in this case is used to identify a macro expansion instance, 569 // but could be used for other things as well. 570 // The file is a header file handle, the line is a line number, 571 // and the column is a column number. 572 class PPItemKey { 573 public: 574 PPItemKey(clang::Preprocessor &PP, StringHandle Name, HeaderHandle File, 575 clang::SourceLocation Loc) 576 : Name(Name), File(File) { 577 getSourceLocationLineAndColumn(PP, Loc, Line, Column); 578 } 579 PPItemKey(StringHandle Name, HeaderHandle File, int Line, int Column) 580 : Name(Name), File(File), Line(Line), Column(Column) {} 581 PPItemKey(const PPItemKey &Other) 582 : Name(Other.Name), File(Other.File), Line(Other.Line), 583 Column(Other.Column) {} 584 PPItemKey() : File(HeaderHandleInvalid), Line(0), Column(0) {} 585 bool operator==(const PPItemKey &Other) const { 586 if (Name != Other.Name) 587 return false; 588 if (File != Other.File) 589 return false; 590 if (Line != Other.Line) 591 return false; 592 return Column == Other.Column; 593 } 594 bool operator<(const PPItemKey &Other) const { 595 if (Name < Other.Name) 596 return true; 597 else if (Name > Other.Name) 598 return false; 599 if (File < Other.File) 600 return true; 601 else if (File > Other.File) 602 return false; 603 if (Line < Other.Line) 604 return true; 605 else if (Line > Other.Line) 606 return false; 607 return Column < Other.Column; 608 } 609 StringHandle Name; 610 HeaderHandle File; 611 int Line; 612 int Column; 613 }; 614 615 // Header inclusion path. 616 class HeaderInclusionPath { 617 public: 618 HeaderInclusionPath(std::vector<HeaderHandle> HeaderInclusionPath) 619 : Path(HeaderInclusionPath) {} 620 HeaderInclusionPath(const HeaderInclusionPath &Other) : Path(Other.Path) {} 621 HeaderInclusionPath() {} 622 std::vector<HeaderHandle> Path; 623 }; 624 625 // Macro expansion instance. 626 // 627 // This class represents an instance of a macro expansion with a 628 // unique value. It also stores the unique header inclusion paths 629 // for use in telling the user the nested include path to the header. 630 class MacroExpansionInstance { 631 public: 632 MacroExpansionInstance(StringHandle MacroExpanded, 633 PPItemKey &DefinitionLocation, 634 StringHandle DefinitionSourceLine, 635 InclusionPathHandle H) 636 : MacroExpanded(MacroExpanded), DefinitionLocation(DefinitionLocation), 637 DefinitionSourceLine(DefinitionSourceLine) { 638 InclusionPathHandles.push_back(H); 639 } 640 MacroExpansionInstance() {} 641 642 // Check for the presence of a header inclusion path handle entry. 643 // Return false if not found. 644 bool haveInclusionPathHandle(InclusionPathHandle H) { 645 for (std::vector<InclusionPathHandle>::iterator 646 I = InclusionPathHandles.begin(), 647 E = InclusionPathHandles.end(); 648 I != E; ++I) { 649 if (*I == H) 650 return true; 651 } 652 return InclusionPathHandleInvalid; 653 } 654 // Add a new header inclusion path entry, if not already present. 655 void addInclusionPathHandle(InclusionPathHandle H) { 656 if (!haveInclusionPathHandle(H)) 657 InclusionPathHandles.push_back(H); 658 } 659 660 // A string representing the macro instance after preprocessing. 661 StringHandle MacroExpanded; 662 // A file/line/column triplet representing the macro definition location. 663 PPItemKey DefinitionLocation; 664 // A place to save the macro definition line string. 665 StringHandle DefinitionSourceLine; 666 // The header inclusion path handles for all the instances. 667 std::vector<InclusionPathHandle> InclusionPathHandles; 668 }; 669 670 // Macro expansion instance tracker. 671 // 672 // This class represents one macro expansion, keyed by a PPItemKey. 673 // It stores a string representing the macro reference in the source, 674 // and a list of ConditionalExpansionInstances objects representing 675 // the unique values the condition expands to in instances of the header. 676 class MacroExpansionTracker { 677 public: 678 MacroExpansionTracker(StringHandle MacroUnexpanded, 679 StringHandle MacroExpanded, 680 StringHandle InstanceSourceLine, 681 PPItemKey &DefinitionLocation, 682 StringHandle DefinitionSourceLine, 683 InclusionPathHandle InclusionPathHandle) 684 : MacroUnexpanded(MacroUnexpanded), 685 InstanceSourceLine(InstanceSourceLine) { 686 addMacroExpansionInstance(MacroExpanded, DefinitionLocation, 687 DefinitionSourceLine, InclusionPathHandle); 688 } 689 MacroExpansionTracker() {} 690 691 // Find a matching macro expansion instance. 692 MacroExpansionInstance * 693 findMacroExpansionInstance(StringHandle MacroExpanded, 694 PPItemKey &DefinitionLocation) { 695 for (std::vector<MacroExpansionInstance>::iterator 696 I = MacroExpansionInstances.begin(), 697 E = MacroExpansionInstances.end(); 698 I != E; ++I) { 699 if ((I->MacroExpanded == MacroExpanded) && 700 (I->DefinitionLocation == DefinitionLocation)) { 701 return &*I; // Found. 702 } 703 } 704 return NULL; // Not found. 705 } 706 707 // Add a macro expansion instance. 708 void addMacroExpansionInstance(StringHandle MacroExpanded, 709 PPItemKey &DefinitionLocation, 710 StringHandle DefinitionSourceLine, 711 InclusionPathHandle InclusionPathHandle) { 712 MacroExpansionInstances.push_back( 713 MacroExpansionInstance(MacroExpanded, DefinitionLocation, 714 DefinitionSourceLine, InclusionPathHandle)); 715 } 716 717 // Return true if there is a mismatch. 718 bool hasMismatch() { return MacroExpansionInstances.size() > 1; } 719 720 // A string representing the macro instance without expansion. 721 StringHandle MacroUnexpanded; 722 // A place to save the macro instance source line string. 723 StringHandle InstanceSourceLine; 724 // The macro expansion instances. 725 // If all instances of the macro expansion expand to the same value, 726 // This vector will only have one instance. 727 std::vector<MacroExpansionInstance> MacroExpansionInstances; 728 }; 729 730 // Conditional expansion instance. 731 // 732 // This class represents an instance of a condition exoression result 733 // with a unique value. It also stores the unique header inclusion paths 734 // for use in telling the user the nested include path to the header. 735 class ConditionalExpansionInstance { 736 public: 737 ConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind ConditionValue, InclusionPathHandle H) 738 : ConditionValue(ConditionValue) { 739 InclusionPathHandles.push_back(H); 740 } 741 ConditionalExpansionInstance() {} 742 743 // Check for the presence of a header inclusion path handle entry. 744 // Return false if not found. 745 bool haveInclusionPathHandle(InclusionPathHandle H) { 746 for (std::vector<InclusionPathHandle>::iterator 747 I = InclusionPathHandles.begin(), 748 E = InclusionPathHandles.end(); 749 I != E; ++I) { 750 if (*I == H) 751 return true; 752 } 753 return InclusionPathHandleInvalid; 754 } 755 // Add a new header inclusion path entry, if not already present. 756 void addInclusionPathHandle(InclusionPathHandle H) { 757 if (!haveInclusionPathHandle(H)) 758 InclusionPathHandles.push_back(H); 759 } 760 761 // A flag representing the evaluated condition value. 762 clang::PPCallbacks::ConditionValueKind ConditionValue; 763 // The header inclusion path handles for all the instances. 764 std::vector<InclusionPathHandle> InclusionPathHandles; 765 }; 766 767 // Conditional directive instance tracker. 768 // 769 // This class represents one conditional directive, keyed by a PPItemKey. 770 // It stores a string representing the macro reference in the source, 771 // and a list of ConditionExpansionInstance objects representing 772 // the unique value the condition expression expands to in instances of 773 // the header. 774 class ConditionalTracker { 775 public: 776 ConditionalTracker(clang::tok::PPKeywordKind DirectiveKind, 777 clang::PPCallbacks::ConditionValueKind ConditionValue, 778 StringHandle ConditionUnexpanded, 779 InclusionPathHandle InclusionPathHandle) 780 : DirectiveKind(DirectiveKind), ConditionUnexpanded(ConditionUnexpanded) { 781 addConditionalExpansionInstance(ConditionValue, InclusionPathHandle); 782 } 783 ConditionalTracker() {} 784 785 // Find a matching condition expansion instance. 786 ConditionalExpansionInstance * 787 findConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind ConditionValue) { 788 for (std::vector<ConditionalExpansionInstance>::iterator 789 I = ConditionalExpansionInstances.begin(), 790 E = ConditionalExpansionInstances.end(); 791 I != E; ++I) { 792 if (I->ConditionValue == ConditionValue) { 793 return &*I; // Found. 794 } 795 } 796 return NULL; // Not found. 797 } 798 799 // Add a conditional expansion instance. 800 void 801 addConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind ConditionValue, 802 InclusionPathHandle InclusionPathHandle) { 803 ConditionalExpansionInstances.push_back( 804 ConditionalExpansionInstance(ConditionValue, InclusionPathHandle)); 805 } 806 807 // Return true if there is a mismatch. 808 bool hasMismatch() { return ConditionalExpansionInstances.size() > 1; } 809 810 // The kind of directive. 811 clang::tok::PPKeywordKind DirectiveKind; 812 // A string representing the macro instance without expansion. 813 StringHandle ConditionUnexpanded; 814 // The condition expansion instances. 815 // If all instances of the conditional expression expand to the same value, 816 // This vector will only have one instance. 817 std::vector<ConditionalExpansionInstance> ConditionalExpansionInstances; 818 }; 819 820 // Preprocessor callbacks for modularize. 821 // 822 // This class derives from the Clang PPCallbacks class to track preprocessor 823 // actions, such as changing files and handling preprocessor directives and 824 // macro expansions. It has to figure out when a new header file is entered 825 // and left, as the provided handler is not particularly clear about it. 826 class PreprocessorCallbacks : public clang::PPCallbacks { 827 public: 828 PreprocessorCallbacks(PreprocessorTrackerImpl &ppTracker, 829 clang::Preprocessor &PP, llvm::StringRef rootHeaderFile) 830 : PPTracker(ppTracker), PP(PP), RootHeaderFile(rootHeaderFile) {} 831 ~PreprocessorCallbacks() {} 832 833 // Overridden handlers. 834 void InclusionDirective(clang::SourceLocation HashLoc, 835 const clang::Token &IncludeTok, 836 llvm::StringRef FileName, bool IsAngled, 837 clang::CharSourceRange FilenameRange, 838 const clang::FileEntry *File, 839 llvm::StringRef SearchPath, 840 llvm::StringRef RelativePath, 841 const clang::Module *Imported); 842 void FileChanged(clang::SourceLocation Loc, 843 clang::PPCallbacks::FileChangeReason Reason, 844 clang::SrcMgr::CharacteristicKind FileType, 845 clang::FileID PrevFID = clang::FileID()); 846 void MacroExpands(const clang::Token &MacroNameTok, 847 const clang::MacroDirective *MD, clang::SourceRange Range, 848 const clang::MacroArgs *Args); 849 void Defined(const clang::Token &MacroNameTok, 850 const clang::MacroDirective *MD, clang::SourceRange Range); 851 void If(clang::SourceLocation Loc, clang::SourceRange ConditionRange, 852 clang::PPCallbacks::ConditionValueKind ConditionResult); 853 void Elif(clang::SourceLocation Loc, clang::SourceRange ConditionRange, 854 clang::PPCallbacks::ConditionValueKind ConditionResult, clang::SourceLocation IfLoc); 855 void Ifdef(clang::SourceLocation Loc, const clang::Token &MacroNameTok, 856 const clang::MacroDirective *MD); 857 void Ifndef(clang::SourceLocation Loc, const clang::Token &MacroNameTok, 858 const clang::MacroDirective *MD); 859 860 private: 861 PreprocessorTrackerImpl &PPTracker; 862 clang::Preprocessor &PP; 863 std::string RootHeaderFile; 864 }; 865 866 // Preprocessor macro expansion item map types. 867 typedef std::map<PPItemKey, MacroExpansionTracker> MacroExpansionMap; 868 typedef std::map<PPItemKey, MacroExpansionTracker>::iterator 869 MacroExpansionMapIter; 870 871 // Preprocessor conditional expansion item map types. 872 typedef std::map<PPItemKey, ConditionalTracker> ConditionalExpansionMap; 873 typedef std::map<PPItemKey, ConditionalTracker>::iterator 874 ConditionalExpansionMapIter; 875 876 // Preprocessor tracker for modularize. 877 // 878 // This class stores information about all the headers processed in the 879 // course of running modularize. 880 class PreprocessorTrackerImpl : public PreprocessorTracker { 881 public: 882 PreprocessorTrackerImpl() 883 : CurrentInclusionPathHandle(InclusionPathHandleInvalid), 884 InNestedHeader(false) {} 885 ~PreprocessorTrackerImpl() {} 886 887 // Handle entering a preprocessing session. 888 void handlePreprocessorEntry(clang::Preprocessor &PP, 889 llvm::StringRef rootHeaderFile) { 890 HeadersInThisCompile.clear(); 891 assert((HeaderStack.size() == 0) && "Header stack should be empty."); 892 pushHeaderHandle(addHeader(rootHeaderFile)); 893 PP.addPPCallbacks(new PreprocessorCallbacks(*this, PP, rootHeaderFile)); 894 } 895 // Handle exiting a preprocessing session. 896 void handlePreprocessorExit() { HeaderStack.clear(); } 897 898 // Handle include directive. 899 // This function is called every time an include directive is seen by the 900 // preprocessor, for the purpose of later checking for 'extern "" {}' or 901 // "namespace {}" blocks containing #include directives. 902 void handleIncludeDirective(llvm::StringRef DirectivePath, int DirectiveLine, 903 int DirectiveColumn, llvm::StringRef TargetPath) { 904 HeaderHandle CurrentHeaderHandle = findHeaderHandle(DirectivePath); 905 StringHandle IncludeHeaderHandle = addString(TargetPath); 906 for (std::vector<PPItemKey>::const_iterator I = IncludeDirectives.begin(), 907 E = IncludeDirectives.end(); 908 I != E; ++I) { 909 // If we already have an entry for this directive, return now. 910 if ((I->File == CurrentHeaderHandle) && (I->Line == DirectiveLine)) 911 return; 912 } 913 PPItemKey IncludeDirectiveItem(IncludeHeaderHandle, CurrentHeaderHandle, 914 DirectiveLine, DirectiveColumn); 915 IncludeDirectives.push_back(IncludeDirectiveItem); 916 } 917 918 // Check for include directives within the given source line range. 919 // Report errors if any found. Returns true if no include directives 920 // found in block. 921 bool checkForIncludesInBlock(clang::Preprocessor &PP, 922 clang::SourceRange BlockSourceRange, 923 const char *BlockIdentifierMessage, 924 llvm::raw_ostream &OS) { 925 clang::SourceLocation BlockStartLoc = BlockSourceRange.getBegin(); 926 clang::SourceLocation BlockEndLoc = BlockSourceRange.getEnd(); 927 // Use block location to get FileID of both the include directive 928 // and block statement. 929 clang::FileID FileID = PP.getSourceManager().getFileID(BlockStartLoc); 930 std::string SourcePath = getSourceLocationFile(PP, BlockStartLoc); 931 HeaderHandle SourceHandle = findHeaderHandle(SourcePath); 932 int BlockStartLine, BlockStartColumn, BlockEndLine, BlockEndColumn; 933 bool returnValue = true; 934 getSourceLocationLineAndColumn(PP, BlockStartLoc, BlockStartLine, 935 BlockStartColumn); 936 getSourceLocationLineAndColumn(PP, BlockEndLoc, BlockEndLine, 937 BlockEndColumn); 938 for (std::vector<PPItemKey>::const_iterator I = IncludeDirectives.begin(), 939 E = IncludeDirectives.end(); 940 I != E; ++I) { 941 // If we find an entry within the block, report an error. 942 if ((I->File == SourceHandle) && (I->Line >= BlockStartLine) && 943 (I->Line < BlockEndLine)) { 944 returnValue = false; 945 OS << SourcePath << ":" << I->Line << ":" << I->Column << ":\n"; 946 OS << getSourceLine(PP, FileID, I->Line) << "\n"; 947 if (I->Column > 0) 948 OS << std::string(I->Column - 1, ' ') << "^\n"; 949 OS << "error: Include directive within " << BlockIdentifierMessage 950 << ".\n"; 951 OS << SourcePath << ":" << BlockStartLine << ":" << BlockStartColumn 952 << ":\n"; 953 OS << getSourceLine(PP, BlockStartLoc) << "\n"; 954 if (BlockStartColumn > 0) 955 OS << std::string(BlockStartColumn - 1, ' ') << "^\n"; 956 OS << "The \"" << BlockIdentifierMessage << "\" block is here.\n"; 957 } 958 } 959 return returnValue; 960 } 961 962 // Handle entering a header source file. 963 void handleHeaderEntry(clang::Preprocessor &PP, llvm::StringRef HeaderPath) { 964 // Ignore <built-in> and <command-line> to reduce message clutter. 965 if (HeaderPath.startswith("<")) 966 return; 967 HeaderHandle H = addHeader(HeaderPath); 968 if (H != getCurrentHeaderHandle()) 969 pushHeaderHandle(H); 970 // Check for nested header. 971 if (!InNestedHeader) 972 InNestedHeader = !HeadersInThisCompile.insert(H); 973 } 974 // Handle exiting a header source file. 975 void handleHeaderExit(llvm::StringRef HeaderPath) { 976 // Ignore <built-in> and <command-line> to reduce message clutter. 977 if (HeaderPath.startswith("<")) 978 return; 979 HeaderHandle H = findHeaderHandle(HeaderPath); 980 if (isHeaderHandleInStack(H)) { 981 while ((H != getCurrentHeaderHandle()) && (HeaderStack.size() != 0)) 982 popHeaderHandle(); 983 } 984 InNestedHeader = false; 985 } 986 987 // Lookup/add string. 988 StringHandle addString(llvm::StringRef Str) { return Strings.intern(Str); } 989 990 // Get the handle of a header file entry. 991 // Return HeaderHandleInvalid if not found. 992 HeaderHandle findHeaderHandle(llvm::StringRef HeaderPath) const { 993 std::string CanonicalPath(HeaderPath); 994 std::replace(CanonicalPath.begin(), CanonicalPath.end(), '\\', '/'); 995 HeaderHandle H = 0; 996 for (std::vector<StringHandle>::const_iterator I = HeaderPaths.begin(), 997 E = HeaderPaths.end(); 998 I != E; ++I, ++H) { 999 if (**I == CanonicalPath) 1000 return H; 1001 } 1002 return HeaderHandleInvalid; 1003 } 1004 1005 // Add a new header file entry, or return existing handle. 1006 // Return the header handle. 1007 HeaderHandle addHeader(llvm::StringRef HeaderPath) { 1008 std::string CanonicalPath(HeaderPath); 1009 std::replace(CanonicalPath.begin(), CanonicalPath.end(), '\\', '/'); 1010 HeaderHandle H = findHeaderHandle(CanonicalPath); 1011 if (H == HeaderHandleInvalid) { 1012 H = HeaderPaths.size(); 1013 HeaderPaths.push_back(addString(CanonicalPath)); 1014 } 1015 return H; 1016 } 1017 1018 // Return a header file path string given its handle. 1019 StringHandle getHeaderFilePath(HeaderHandle H) const { 1020 if ((H >= 0) && (H < (HeaderHandle)HeaderPaths.size())) 1021 return HeaderPaths[H]; 1022 return StringHandle(); 1023 } 1024 1025 // Returns a handle to the inclusion path. 1026 InclusionPathHandle pushHeaderHandle(HeaderHandle H) { 1027 HeaderStack.push_back(H); 1028 return CurrentInclusionPathHandle = addInclusionPathHandle(HeaderStack); 1029 } 1030 // Pops the last header handle from the stack; 1031 void popHeaderHandle() { 1032 // assert((HeaderStack.size() != 0) && "Header stack already empty."); 1033 if (HeaderStack.size() != 0) { 1034 HeaderStack.pop_back(); 1035 CurrentInclusionPathHandle = addInclusionPathHandle(HeaderStack); 1036 } 1037 } 1038 // Get the top handle on the header stack. 1039 HeaderHandle getCurrentHeaderHandle() const { 1040 if (HeaderStack.size() != 0) 1041 return HeaderStack.back(); 1042 return HeaderHandleInvalid; 1043 } 1044 1045 // Check for presence of header handle in the header stack. 1046 bool isHeaderHandleInStack(HeaderHandle H) const { 1047 for (std::vector<HeaderHandle>::const_iterator I = HeaderStack.begin(), 1048 E = HeaderStack.end(); 1049 I != E; ++I) { 1050 if (*I == H) 1051 return true; 1052 } 1053 return false; 1054 } 1055 1056 // Get the handle of a header inclusion path entry. 1057 // Return InclusionPathHandleInvalid if not found. 1058 InclusionPathHandle 1059 findInclusionPathHandle(const std::vector<HeaderHandle> &Path) const { 1060 InclusionPathHandle H = 0; 1061 for (std::vector<HeaderInclusionPath>::const_iterator 1062 I = InclusionPaths.begin(), 1063 E = InclusionPaths.end(); 1064 I != E; ++I, ++H) { 1065 if (I->Path == Path) 1066 return H; 1067 } 1068 return HeaderHandleInvalid; 1069 } 1070 // Add a new header inclusion path entry, or return existing handle. 1071 // Return the header inclusion path entry handle. 1072 InclusionPathHandle 1073 addInclusionPathHandle(const std::vector<HeaderHandle> &Path) { 1074 InclusionPathHandle H = findInclusionPathHandle(Path); 1075 if (H == HeaderHandleInvalid) { 1076 H = InclusionPaths.size(); 1077 InclusionPaths.push_back(HeaderInclusionPath(Path)); 1078 } 1079 return H; 1080 } 1081 // Return the current inclusion path handle. 1082 InclusionPathHandle getCurrentInclusionPathHandle() const { 1083 return CurrentInclusionPathHandle; 1084 } 1085 1086 // Return an inclusion path given its handle. 1087 const std::vector<HeaderHandle> & 1088 getInclusionPath(InclusionPathHandle H) const { 1089 if ((H >= 0) && (H <= (InclusionPathHandle)InclusionPaths.size())) 1090 return InclusionPaths[H].Path; 1091 static std::vector<HeaderHandle> Empty; 1092 return Empty; 1093 } 1094 1095 // Add a macro expansion instance. 1096 void addMacroExpansionInstance(clang::Preprocessor &PP, HeaderHandle H, 1097 clang::SourceLocation InstanceLoc, 1098 clang::SourceLocation DefinitionLoc, 1099 clang::IdentifierInfo *II, 1100 llvm::StringRef MacroUnexpanded, 1101 llvm::StringRef MacroExpanded, 1102 InclusionPathHandle InclusionPathHandle) { 1103 if (InNestedHeader) 1104 return; 1105 StringHandle MacroName = addString(II->getName()); 1106 PPItemKey InstanceKey(PP, MacroName, H, InstanceLoc); 1107 PPItemKey DefinitionKey(PP, MacroName, H, DefinitionLoc); 1108 MacroExpansionMapIter I = MacroExpansions.find(InstanceKey); 1109 // If existing instance of expansion not found, add one. 1110 if (I == MacroExpansions.end()) { 1111 std::string InstanceSourceLine = 1112 getSourceLocationString(PP, InstanceLoc) + ":\n" + 1113 getSourceLine(PP, InstanceLoc) + "\n"; 1114 std::string DefinitionSourceLine = 1115 getSourceLocationString(PP, DefinitionLoc) + ":\n" + 1116 getSourceLine(PP, DefinitionLoc) + "\n"; 1117 MacroExpansions[InstanceKey] = MacroExpansionTracker( 1118 addString(MacroUnexpanded), addString(MacroExpanded), 1119 addString(InstanceSourceLine), DefinitionKey, 1120 addString(DefinitionSourceLine), InclusionPathHandle); 1121 } else { 1122 // We've seen the macro before. Get its tracker. 1123 MacroExpansionTracker &CondTracker = I->second; 1124 // Look up an existing instance value for the macro. 1125 MacroExpansionInstance *MacroInfo = 1126 CondTracker.findMacroExpansionInstance(addString(MacroExpanded), 1127 DefinitionKey); 1128 // If found, just add the inclusion path to the instance. 1129 if (MacroInfo != NULL) 1130 MacroInfo->addInclusionPathHandle(InclusionPathHandle); 1131 else { 1132 // Otherwise add a new instance with the unique value. 1133 std::string DefinitionSourceLine = 1134 getSourceLocationString(PP, DefinitionLoc) + ":\n" + 1135 getSourceLine(PP, DefinitionLoc) + "\n"; 1136 CondTracker.addMacroExpansionInstance( 1137 addString(MacroExpanded), DefinitionKey, 1138 addString(DefinitionSourceLine), InclusionPathHandle); 1139 } 1140 } 1141 } 1142 1143 // Add a conditional expansion instance. 1144 void 1145 addConditionalExpansionInstance(clang::Preprocessor &PP, HeaderHandle H, 1146 clang::SourceLocation InstanceLoc, 1147 clang::tok::PPKeywordKind DirectiveKind, 1148 clang::PPCallbacks::ConditionValueKind ConditionValue, 1149 llvm::StringRef ConditionUnexpanded, 1150 InclusionPathHandle InclusionPathHandle) { 1151 // Ignore header guards, assuming the header guard is the only conditional. 1152 if (InNestedHeader) 1153 return; 1154 StringHandle ConditionUnexpandedHandle(addString(ConditionUnexpanded)); 1155 PPItemKey InstanceKey(PP, ConditionUnexpandedHandle, H, InstanceLoc); 1156 ConditionalExpansionMapIter I = ConditionalExpansions.find(InstanceKey); 1157 // If existing instance of condition not found, add one. 1158 if (I == ConditionalExpansions.end()) { 1159 std::string InstanceSourceLine = 1160 getSourceLocationString(PP, InstanceLoc) + ":\n" + 1161 getSourceLine(PP, InstanceLoc) + "\n"; 1162 ConditionalExpansions[InstanceKey] = 1163 ConditionalTracker(DirectiveKind, ConditionValue, 1164 ConditionUnexpandedHandle, InclusionPathHandle); 1165 } else { 1166 // We've seen the conditional before. Get its tracker. 1167 ConditionalTracker &CondTracker = I->second; 1168 // Look up an existing instance value for the condition. 1169 ConditionalExpansionInstance *MacroInfo = 1170 CondTracker.findConditionalExpansionInstance(ConditionValue); 1171 // If found, just add the inclusion path to the instance. 1172 if (MacroInfo != NULL) 1173 MacroInfo->addInclusionPathHandle(InclusionPathHandle); 1174 else { 1175 // Otherwise add a new instance with the unique value. 1176 CondTracker.addConditionalExpansionInstance(ConditionValue, 1177 InclusionPathHandle); 1178 } 1179 } 1180 } 1181 1182 // Report on inconsistent macro instances. 1183 // Returns true if any mismatches. 1184 bool reportInconsistentMacros(llvm::raw_ostream &OS) { 1185 bool ReturnValue = false; 1186 // Walk all the macro expansion trackers in the map. 1187 for (MacroExpansionMapIter I = MacroExpansions.begin(), 1188 E = MacroExpansions.end(); 1189 I != E; ++I) { 1190 const PPItemKey &ItemKey = I->first; 1191 MacroExpansionTracker &MacroExpTracker = I->second; 1192 // If no mismatch (only one instance value) continue. 1193 if (!MacroExpTracker.hasMismatch()) 1194 continue; 1195 // Tell caller we found one or more errors. 1196 ReturnValue = true; 1197 // Start the error message. 1198 OS << *MacroExpTracker.InstanceSourceLine; 1199 if (ItemKey.Column > 0) 1200 OS << std::string(ItemKey.Column - 1, ' ') << "^\n"; 1201 OS << "error: Macro instance '" << *MacroExpTracker.MacroUnexpanded 1202 << "' has different values in this header, depending on how it was " 1203 "included.\n"; 1204 // Walk all the instances. 1205 for (std::vector<MacroExpansionInstance>::iterator 1206 IMT = MacroExpTracker.MacroExpansionInstances.begin(), 1207 EMT = MacroExpTracker.MacroExpansionInstances.end(); 1208 IMT != EMT; ++IMT) { 1209 MacroExpansionInstance &MacroInfo = *IMT; 1210 OS << " '" << *MacroExpTracker.MacroUnexpanded << "' expanded to: '" 1211 << *MacroInfo.MacroExpanded 1212 << "' with respect to these inclusion paths:\n"; 1213 // Walk all the inclusion path hierarchies. 1214 for (std::vector<InclusionPathHandle>::iterator 1215 IIP = MacroInfo.InclusionPathHandles.begin(), 1216 EIP = MacroInfo.InclusionPathHandles.end(); 1217 IIP != EIP; ++IIP) { 1218 const std::vector<HeaderHandle> &ip = getInclusionPath(*IIP); 1219 int Count = (int)ip.size(); 1220 for (int Index = 0; Index < Count; ++Index) { 1221 HeaderHandle H = ip[Index]; 1222 OS << std::string((Index * 2) + 4, ' ') << *getHeaderFilePath(H) 1223 << "\n"; 1224 } 1225 } 1226 // For a macro that wasn't defined, we flag it by using the 1227 // instance location. 1228 // If there is a definition... 1229 if (MacroInfo.DefinitionLocation.Line != ItemKey.Line) { 1230 OS << *MacroInfo.DefinitionSourceLine; 1231 if (MacroInfo.DefinitionLocation.Column > 0) 1232 OS << std::string(MacroInfo.DefinitionLocation.Column - 1, ' ') 1233 << "^\n"; 1234 OS << "Macro defined here.\n"; 1235 } else 1236 OS << "(no macro definition)" 1237 << "\n"; 1238 } 1239 } 1240 return ReturnValue; 1241 } 1242 1243 // Report on inconsistent conditional instances. 1244 // Returns true if any mismatches. 1245 bool reportInconsistentConditionals(llvm::raw_ostream &OS) { 1246 bool ReturnValue = false; 1247 // Walk all the conditional trackers in the map. 1248 for (ConditionalExpansionMapIter I = ConditionalExpansions.begin(), 1249 E = ConditionalExpansions.end(); 1250 I != E; ++I) { 1251 const PPItemKey &ItemKey = I->first; 1252 ConditionalTracker &CondTracker = I->second; 1253 if (!CondTracker.hasMismatch()) 1254 continue; 1255 // Tell caller we found one or more errors. 1256 ReturnValue = true; 1257 // Start the error message. 1258 OS << *HeaderPaths[ItemKey.File] << ":" << ItemKey.Line << ":" 1259 << ItemKey.Column << "\n"; 1260 OS << "#" << getDirectiveSpelling(CondTracker.DirectiveKind) << " " 1261 << *CondTracker.ConditionUnexpanded << "\n"; 1262 OS << "^\n"; 1263 OS << "error: Conditional expression instance '" 1264 << *CondTracker.ConditionUnexpanded 1265 << "' has different values in this header, depending on how it was " 1266 "included.\n"; 1267 // Walk all the instances. 1268 for (std::vector<ConditionalExpansionInstance>::iterator 1269 IMT = CondTracker.ConditionalExpansionInstances.begin(), 1270 EMT = CondTracker.ConditionalExpansionInstances.end(); 1271 IMT != EMT; ++IMT) { 1272 ConditionalExpansionInstance &MacroInfo = *IMT; 1273 OS << " '" << *CondTracker.ConditionUnexpanded << "' expanded to: '" 1274 << ConditionValueKindStrings[MacroInfo.ConditionValue] 1275 << "' with respect to these inclusion paths:\n"; 1276 // Walk all the inclusion path hierarchies. 1277 for (std::vector<InclusionPathHandle>::iterator 1278 IIP = MacroInfo.InclusionPathHandles.begin(), 1279 EIP = MacroInfo.InclusionPathHandles.end(); 1280 IIP != EIP; ++IIP) { 1281 const std::vector<HeaderHandle> &ip = getInclusionPath(*IIP); 1282 int Count = (int)ip.size(); 1283 for (int Index = 0; Index < Count; ++Index) { 1284 HeaderHandle H = ip[Index]; 1285 OS << std::string((Index * 2) + 4, ' ') << *getHeaderFilePath(H) 1286 << "\n"; 1287 } 1288 } 1289 } 1290 } 1291 return ReturnValue; 1292 } 1293 1294 // Get directive spelling. 1295 static const char *getDirectiveSpelling(clang::tok::PPKeywordKind kind) { 1296 switch (kind) { 1297 case clang::tok::pp_if: 1298 return "if"; 1299 case clang::tok::pp_elif: 1300 return "elif"; 1301 case clang::tok::pp_ifdef: 1302 return "ifdef"; 1303 case clang::tok::pp_ifndef: 1304 return "ifndef"; 1305 default: 1306 return "(unknown)"; 1307 } 1308 } 1309 1310 private: 1311 llvm::StringPool Strings; 1312 std::vector<StringHandle> HeaderPaths; 1313 std::vector<HeaderHandle> HeaderStack; 1314 std::vector<HeaderInclusionPath> InclusionPaths; 1315 InclusionPathHandle CurrentInclusionPathHandle; 1316 llvm::SmallSet<HeaderHandle, 128> HeadersInThisCompile; 1317 std::vector<PPItemKey> IncludeDirectives; 1318 MacroExpansionMap MacroExpansions; 1319 ConditionalExpansionMap ConditionalExpansions; 1320 bool InNestedHeader; 1321 }; 1322 1323 // PreprocessorTracker functions. 1324 1325 // PreprocessorTracker desctructor. 1326 PreprocessorTracker::~PreprocessorTracker() {} 1327 1328 // Create instance of PreprocessorTracker. 1329 PreprocessorTracker *PreprocessorTracker::create() { 1330 return new PreprocessorTrackerImpl(); 1331 } 1332 1333 // Preprocessor callbacks for modularize. 1334 1335 // Handle include directive. 1336 void PreprocessorCallbacks::InclusionDirective( 1337 clang::SourceLocation HashLoc, const clang::Token &IncludeTok, 1338 llvm::StringRef FileName, bool IsAngled, 1339 clang::CharSourceRange FilenameRange, const clang::FileEntry *File, 1340 llvm::StringRef SearchPath, llvm::StringRef RelativePath, 1341 const clang::Module *Imported) { 1342 int DirectiveLine, DirectiveColumn; 1343 std::string HeaderPath = getSourceLocationFile(PP, HashLoc); 1344 getSourceLocationLineAndColumn(PP, HashLoc, DirectiveLine, DirectiveColumn); 1345 PPTracker.handleIncludeDirective(HeaderPath, DirectiveLine, DirectiveColumn, 1346 FileName); 1347 } 1348 1349 // Handle file entry/exit. 1350 void PreprocessorCallbacks::FileChanged( 1351 clang::SourceLocation Loc, clang::PPCallbacks::FileChangeReason Reason, 1352 clang::SrcMgr::CharacteristicKind FileType, clang::FileID PrevFID) { 1353 switch (Reason) { 1354 case EnterFile: 1355 PPTracker.handleHeaderEntry(PP, getSourceLocationFile(PP, Loc)); 1356 break; 1357 case ExitFile: { 1358 const clang::FileEntry *F = 1359 PP.getSourceManager().getFileEntryForID(PrevFID); 1360 if (F != NULL) 1361 PPTracker.handleHeaderExit(F->getName()); 1362 } break; 1363 case SystemHeaderPragma: 1364 case RenameFile: 1365 break; 1366 } 1367 } 1368 1369 // Handle macro expansion. 1370 void PreprocessorCallbacks::MacroExpands(const clang::Token &MacroNameTok, 1371 const clang::MacroDirective *MD, 1372 clang::SourceRange Range, 1373 const clang::MacroArgs *Args) { 1374 clang::SourceLocation Loc = Range.getBegin(); 1375 // Ignore macro argument expansions. 1376 if (!Loc.isFileID()) 1377 return; 1378 clang::IdentifierInfo *II = MacroNameTok.getIdentifierInfo(); 1379 const clang::MacroInfo *MI = PP.getMacroInfo(II); 1380 std::string MacroName = II->getName().str(); 1381 std::string Unexpanded(getMacroUnexpandedString(Range, PP, MacroName, MI)); 1382 std::string Expanded(getMacroExpandedString(PP, MacroName, MI, Args)); 1383 PPTracker.addMacroExpansionInstance( 1384 PP, PPTracker.getCurrentHeaderHandle(), Loc, MI->getDefinitionLoc(), II, 1385 Unexpanded, Expanded, PPTracker.getCurrentInclusionPathHandle()); 1386 } 1387 1388 void PreprocessorCallbacks::Defined(const clang::Token &MacroNameTok, 1389 const clang::MacroDirective *MD, 1390 clang::SourceRange Range) { 1391 clang::SourceLocation Loc(Range.getBegin()); 1392 clang::IdentifierInfo *II = MacroNameTok.getIdentifierInfo(); 1393 const clang::MacroInfo *MI = PP.getMacroInfo(II); 1394 std::string MacroName = II->getName().str(); 1395 std::string Unexpanded(getSourceString(PP, Range)); 1396 PPTracker.addMacroExpansionInstance( 1397 PP, PPTracker.getCurrentHeaderHandle(), Loc, 1398 (MI ? MI->getDefinitionLoc() : Loc), II, Unexpanded, 1399 (MI ? "true" : "false"), PPTracker.getCurrentInclusionPathHandle()); 1400 } 1401 1402 void PreprocessorCallbacks::If(clang::SourceLocation Loc, 1403 clang::SourceRange ConditionRange, 1404 clang::PPCallbacks::ConditionValueKind ConditionResult) { 1405 std::string Unexpanded(getSourceString(PP, ConditionRange)); 1406 PPTracker.addConditionalExpansionInstance( 1407 PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_if, 1408 ConditionResult, Unexpanded, PPTracker.getCurrentInclusionPathHandle()); 1409 } 1410 1411 void PreprocessorCallbacks::Elif(clang::SourceLocation Loc, 1412 clang::SourceRange ConditionRange, 1413 clang::PPCallbacks::ConditionValueKind ConditionResult, 1414 clang::SourceLocation IfLoc) { 1415 std::string Unexpanded(getSourceString(PP, ConditionRange)); 1416 PPTracker.addConditionalExpansionInstance( 1417 PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_elif, 1418 ConditionResult, Unexpanded, PPTracker.getCurrentInclusionPathHandle()); 1419 } 1420 1421 void PreprocessorCallbacks::Ifdef(clang::SourceLocation Loc, 1422 const clang::Token &MacroNameTok, 1423 const clang::MacroDirective *MD) { 1424 clang::PPCallbacks::ConditionValueKind IsDefined = 1425 (MD != 0 ? clang::PPCallbacks::CVK_True : clang::PPCallbacks::CVK_False ); 1426 PPTracker.addConditionalExpansionInstance( 1427 PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_ifdef, 1428 IsDefined, PP.getSpelling(MacroNameTok), 1429 PPTracker.getCurrentInclusionPathHandle()); 1430 } 1431 1432 void PreprocessorCallbacks::Ifndef(clang::SourceLocation Loc, 1433 const clang::Token &MacroNameTok, 1434 const clang::MacroDirective *MD) { 1435 clang::PPCallbacks::ConditionValueKind IsNotDefined = 1436 (MD == 0 ? clang::PPCallbacks::CVK_True : clang::PPCallbacks::CVK_False ); 1437 PPTracker.addConditionalExpansionInstance( 1438 PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_ifndef, 1439 IsNotDefined, PP.getSpelling(MacroNameTok), 1440 PPTracker.getCurrentInclusionPathHandle()); 1441 } 1442 } // end namespace Modularize 1443