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