clang-tools 3.8.0

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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