clang-tools  8.0.0svn
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 
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->getParameterNum(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, 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 *
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) {
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 (auto I = InclusionPathHandles.begin(), E = InclusionPathHandles.end();
562  I != E; ++I) {
563  if (*I == H)
564  return true;
565  }
567  }
568  // Add a new header inclusion path entry, if not already present.
569  void addInclusionPathHandle(InclusionPathHandle H) {
570  if (!haveInclusionPathHandle(H))
571  InclusionPathHandles.push_back(H);
572  }
573 
574  // A string representing the macro instance after preprocessing.
575  StringHandle MacroExpanded;
576  // A file/line/column triplet representing the macro definition location.
578  // A place to save the macro definition line string.
579  StringHandle DefinitionSourceLine;
580  // The header inclusion path handles for all the instances.
581  std::vector<InclusionPathHandle> InclusionPathHandles;
582 };
583 
584 // Macro expansion instance tracker.
585 //
586 // This class represents one macro expansion, keyed by a PPItemKey.
587 // It stores a string representing the macro reference in the source,
588 // and a list of ConditionalExpansionInstances objects representing
589 // the unique values the condition expands to in instances of the header.
590 class MacroExpansionTracker {
591 public:
592  MacroExpansionTracker(StringHandle MacroUnexpanded,
593  StringHandle MacroExpanded,
594  StringHandle InstanceSourceLine,
595  PPItemKey &DefinitionLocation,
596  StringHandle DefinitionSourceLine,
597  InclusionPathHandle InclusionPathHandle)
598  : MacroUnexpanded(MacroUnexpanded),
599  InstanceSourceLine(InstanceSourceLine) {
600  addMacroExpansionInstance(MacroExpanded, DefinitionLocation,
601  DefinitionSourceLine, InclusionPathHandle);
602  }
603  MacroExpansionTracker() {}
604 
605  // Find a matching macro expansion instance.
606  MacroExpansionInstance *
607  findMacroExpansionInstance(StringHandle MacroExpanded,
608  PPItemKey &DefinitionLocation) {
609  for (auto I = MacroExpansionInstances.begin(),
610  E = MacroExpansionInstances.end();
611  I != E; ++I) {
612  if ((I->MacroExpanded == MacroExpanded) &&
613  (I->DefinitionLocation == DefinitionLocation)) {
614  return &*I; // Found.
615  }
616  }
617  return nullptr; // Not found.
618  }
619 
620  // Add a macro expansion instance.
621  void addMacroExpansionInstance(StringHandle MacroExpanded,
622  PPItemKey &DefinitionLocation,
623  StringHandle DefinitionSourceLine,
624  InclusionPathHandle InclusionPathHandle) {
625  MacroExpansionInstances.push_back(
626  MacroExpansionInstance(MacroExpanded, DefinitionLocation,
627  DefinitionSourceLine, InclusionPathHandle));
628  }
629 
630  // Return true if there is a mismatch.
631  bool hasMismatch() { return MacroExpansionInstances.size() > 1; }
632 
633  // A string representing the macro instance without expansion.
634  StringHandle MacroUnexpanded;
635  // A place to save the macro instance source line string.
636  StringHandle InstanceSourceLine;
637  // The macro expansion instances.
638  // If all instances of the macro expansion expand to the same value,
639  // This vector will only have one instance.
640  std::vector<MacroExpansionInstance> MacroExpansionInstances;
641 };
642 
643 // Conditional expansion instance.
644 //
645 // This class represents an instance of a condition exoression result
646 // with a unique value. It also stores the unique header inclusion paths
647 // for use in telling the user the nested include path to the header.
648 class ConditionalExpansionInstance {
649 public:
650  ConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind ConditionValue, InclusionPathHandle H)
651  : ConditionValue(ConditionValue) {
652  InclusionPathHandles.push_back(H);
653  }
654  ConditionalExpansionInstance() {}
655 
656  // Check for the presence of a header inclusion path handle entry.
657  // Return false if not found.
658  bool haveInclusionPathHandle(InclusionPathHandle H) {
659  for (auto I = InclusionPathHandles.begin(), E = InclusionPathHandles.end();
660  I != E; ++I) {
661  if (*I == H)
662  return true;
663  }
665  }
666  // Add a new header inclusion path entry, if not already present.
667  void addInclusionPathHandle(InclusionPathHandle H) {
668  if (!haveInclusionPathHandle(H))
669  InclusionPathHandles.push_back(H);
670  }
671 
672  // A flag representing the evaluated condition value.
673  clang::PPCallbacks::ConditionValueKind ConditionValue;
674  // The header inclusion path handles for all the instances.
675  std::vector<InclusionPathHandle> InclusionPathHandles;
676 };
677 
678 // Conditional directive instance tracker.
679 //
680 // This class represents one conditional directive, keyed by a PPItemKey.
681 // It stores a string representing the macro reference in the source,
682 // and a list of ConditionExpansionInstance objects representing
683 // the unique value the condition expression expands to in instances of
684 // the header.
685 class ConditionalTracker {
686 public:
687  ConditionalTracker(clang::tok::PPKeywordKind DirectiveKind,
688  clang::PPCallbacks::ConditionValueKind ConditionValue,
689  StringHandle ConditionUnexpanded,
690  InclusionPathHandle InclusionPathHandle)
691  : DirectiveKind(DirectiveKind), ConditionUnexpanded(ConditionUnexpanded) {
692  addConditionalExpansionInstance(ConditionValue, InclusionPathHandle);
693  }
694  ConditionalTracker() {}
695 
696  // Find a matching condition expansion instance.
697  ConditionalExpansionInstance *
698  findConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind ConditionValue) {
699  for (auto I = ConditionalExpansionInstances.begin(),
701  I != E; ++I) {
702  if (I->ConditionValue == ConditionValue) {
703  return &*I; // Found.
704  }
705  }
706  return nullptr; // Not found.
707  }
708 
709  // Add a conditional expansion instance.
710  void
711  addConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind ConditionValue,
712  InclusionPathHandle InclusionPathHandle) {
714  ConditionalExpansionInstance(ConditionValue, InclusionPathHandle));
715  }
716 
717  // Return true if there is a mismatch.
718  bool hasMismatch() { return ConditionalExpansionInstances.size() > 1; }
719 
720  // The kind of directive.
721  clang::tok::PPKeywordKind DirectiveKind;
722  // A string representing the macro instance without expansion.
723  StringHandle ConditionUnexpanded;
724  // The condition expansion instances.
725  // If all instances of the conditional expression expand to the same value,
726  // This vector will only have one instance.
727  std::vector<ConditionalExpansionInstance> ConditionalExpansionInstances;
728 };
729 
730 class PreprocessorTrackerImpl;
731 
732 // Preprocessor callbacks for modularize.
733 //
734 // This class derives from the Clang PPCallbacks class to track preprocessor
735 // actions, such as changing files and handling preprocessor directives and
736 // macro expansions. It has to figure out when a new header file is entered
737 // and left, as the provided handler is not particularly clear about it.
738 class PreprocessorCallbacks : public clang::PPCallbacks {
739 public:
740  PreprocessorCallbacks(PreprocessorTrackerImpl &ppTracker,
741  clang::Preprocessor &PP, llvm::StringRef rootHeaderFile)
742  : PPTracker(ppTracker), PP(PP), RootHeaderFile(rootHeaderFile) {}
743  ~PreprocessorCallbacks() override {}
744 
745  // Overridden handlers.
746  void InclusionDirective(clang::SourceLocation HashLoc,
747  const clang::Token &IncludeTok,
748  llvm::StringRef FileName, bool IsAngled,
749  clang::CharSourceRange FilenameRange,
750  const clang::FileEntry *File,
751  llvm::StringRef SearchPath,
752  llvm::StringRef RelativePath,
753  const clang::Module *Imported,
754  clang::SrcMgr::CharacteristicKind FileType) override;
755  void FileChanged(clang::SourceLocation Loc,
756  clang::PPCallbacks::FileChangeReason Reason,
757  clang::SrcMgr::CharacteristicKind FileType,
758  clang::FileID PrevFID = clang::FileID()) override;
759  void MacroExpands(const clang::Token &MacroNameTok,
760  const clang::MacroDefinition &MD, clang::SourceRange Range,
761  const clang::MacroArgs *Args) override;
762  void Defined(const clang::Token &MacroNameTok,
763  const clang::MacroDefinition &MD,
764  clang::SourceRange Range) override;
765  void If(clang::SourceLocation Loc, clang::SourceRange ConditionRange,
766  clang::PPCallbacks::ConditionValueKind ConditionResult) override;
767  void Elif(clang::SourceLocation Loc, clang::SourceRange ConditionRange,
768  clang::PPCallbacks::ConditionValueKind ConditionResult,
769  clang::SourceLocation IfLoc) override;
770  void Ifdef(clang::SourceLocation Loc, const clang::Token &MacroNameTok,
771  const clang::MacroDefinition &MD) override;
772  void Ifndef(clang::SourceLocation Loc, const clang::Token &MacroNameTok,
773  const clang::MacroDefinition &MD) override;
774 
775 private:
776  PreprocessorTrackerImpl &PPTracker;
777  clang::Preprocessor &PP;
778  std::string RootHeaderFile;
779 };
780 
781 // Preprocessor macro expansion item map types.
782 typedef std::map<PPItemKey, MacroExpansionTracker> MacroExpansionMap;
783 typedef std::map<PPItemKey, MacroExpansionTracker>::iterator
784 MacroExpansionMapIter;
785 
786 // Preprocessor conditional expansion item map types.
787 typedef std::map<PPItemKey, ConditionalTracker> ConditionalExpansionMap;
788 typedef std::map<PPItemKey, ConditionalTracker>::iterator
789 ConditionalExpansionMapIter;
790 
791 // Preprocessor tracker for modularize.
792 //
793 // This class stores information about all the headers processed in the
794 // course of running modularize.
795 class PreprocessorTrackerImpl : public PreprocessorTracker {
796 public:
797  PreprocessorTrackerImpl(llvm::SmallVector<std::string, 32> &Headers,
798  bool DoBlockCheckHeaderListOnly)
799  : BlockCheckHeaderListOnly(DoBlockCheckHeaderListOnly),
800  CurrentInclusionPathHandle(InclusionPathHandleInvalid),
801  InNestedHeader(false) {
802  // Use canonical header path representation.
803  for (llvm::ArrayRef<std::string>::iterator I = Headers.begin(),
804  E = Headers.end();
805  I != E; ++I) {
806  HeaderList.push_back(getCanonicalPath(*I));
807  }
808  }
809 
810  ~PreprocessorTrackerImpl() override {}
811 
812  // Handle entering a preprocessing session.
813  void handlePreprocessorEntry(clang::Preprocessor &PP,
814  llvm::StringRef rootHeaderFile) override {
815  HeadersInThisCompile.clear();
816  assert((HeaderStack.size() == 0) && "Header stack should be empty.");
817  pushHeaderHandle(addHeader(rootHeaderFile));
818  PP.addPPCallbacks(llvm::make_unique<PreprocessorCallbacks>(*this, PP,
819  rootHeaderFile));
820  }
821  // Handle exiting a preprocessing session.
822  void handlePreprocessorExit() override { HeaderStack.clear(); }
823 
824  // Handle include directive.
825  // This function is called every time an include directive is seen by the
826  // preprocessor, for the purpose of later checking for 'extern "" {}' or
827  // "namespace {}" blocks containing #include directives.
828  void handleIncludeDirective(llvm::StringRef DirectivePath, int DirectiveLine,
829  int DirectiveColumn,
830  llvm::StringRef TargetPath) override {
831  // If it's not a header in the header list, ignore it with respect to
832  // the check.
833  if (BlockCheckHeaderListOnly && !isHeaderListHeader(TargetPath))
834  return;
835  HeaderHandle CurrentHeaderHandle = findHeaderHandle(DirectivePath);
836  StringHandle IncludeHeaderHandle = addString(TargetPath);
837  for (std::vector<PPItemKey>::const_iterator I = IncludeDirectives.begin(),
838  E = IncludeDirectives.end();
839  I != E; ++I) {
840  // If we already have an entry for this directive, return now.
841  if ((I->File == CurrentHeaderHandle) && (I->Line == DirectiveLine))
842  return;
843  }
844  PPItemKey IncludeDirectiveItem(IncludeHeaderHandle, CurrentHeaderHandle,
845  DirectiveLine, DirectiveColumn);
846  IncludeDirectives.push_back(IncludeDirectiveItem);
847  }
848 
849  // Check for include directives within the given source line range.
850  // Report errors if any found. Returns true if no include directives
851  // found in block.
852  bool checkForIncludesInBlock(clang::Preprocessor &PP,
853  clang::SourceRange BlockSourceRange,
854  const char *BlockIdentifierMessage,
855  llvm::raw_ostream &OS) override {
856  clang::SourceLocation BlockStartLoc = BlockSourceRange.getBegin();
857  clang::SourceLocation BlockEndLoc = BlockSourceRange.getEnd();
858  // Use block location to get FileID of both the include directive
859  // and block statement.
860  clang::FileID FileID = PP.getSourceManager().getFileID(BlockStartLoc);
861  std::string SourcePath = getSourceLocationFile(PP, BlockStartLoc);
862  SourcePath = ModularizeUtilities::getCanonicalPath(SourcePath);
863  HeaderHandle SourceHandle = findHeaderHandle(SourcePath);
864  if (SourceHandle == -1)
865  return true;
866  int BlockStartLine, BlockStartColumn, BlockEndLine, BlockEndColumn;
867  bool returnValue = true;
868  getSourceLocationLineAndColumn(PP, BlockStartLoc, BlockStartLine,
869  BlockStartColumn);
870  getSourceLocationLineAndColumn(PP, BlockEndLoc, BlockEndLine,
871  BlockEndColumn);
872  for (std::vector<PPItemKey>::const_iterator I = IncludeDirectives.begin(),
873  E = IncludeDirectives.end();
874  I != E; ++I) {
875  // If we find an entry within the block, report an error.
876  if ((I->File == SourceHandle) && (I->Line >= BlockStartLine) &&
877  (I->Line < BlockEndLine)) {
878  returnValue = false;
879  OS << SourcePath << ":" << I->Line << ":" << I->Column << ":\n";
880  OS << getSourceLine(PP, FileID, I->Line) << "\n";
881  if (I->Column > 0)
882  OS << std::string(I->Column - 1, ' ') << "^\n";
883  OS << "error: Include directive within " << BlockIdentifierMessage
884  << ".\n";
885  OS << SourcePath << ":" << BlockStartLine << ":" << BlockStartColumn
886  << ":\n";
887  OS << getSourceLine(PP, BlockStartLoc) << "\n";
888  if (BlockStartColumn > 0)
889  OS << std::string(BlockStartColumn - 1, ' ') << "^\n";
890  OS << "The \"" << BlockIdentifierMessage << "\" block is here.\n";
891  }
892  }
893  return returnValue;
894  }
895 
896  // Handle entering a header source file.
897  void handleHeaderEntry(clang::Preprocessor &PP, llvm::StringRef HeaderPath) {
898  // Ignore <built-in> and <command-line> to reduce message clutter.
899  if (HeaderPath.startswith("<"))
900  return;
901  HeaderHandle H = addHeader(HeaderPath);
902  if (H != getCurrentHeaderHandle())
903  pushHeaderHandle(H);
904  // Check for nested header.
905  if (!InNestedHeader)
906  InNestedHeader = !HeadersInThisCompile.insert(H).second;
907  }
908 
909  // Handle exiting a header source file.
910  void handleHeaderExit(llvm::StringRef HeaderPath) {
911  // Ignore <built-in> and <command-line> to reduce message clutter.
912  if (HeaderPath.startswith("<"))
913  return;
914  HeaderHandle H = findHeaderHandle(HeaderPath);
915  HeaderHandle TH;
916  if (isHeaderHandleInStack(H)) {
917  do {
918  TH = getCurrentHeaderHandle();
919  popHeaderHandle();
920  } while ((TH != H) && (HeaderStack.size() != 0));
921  }
922  InNestedHeader = false;
923  }
924 
925  // Lookup/add string.
926  StringHandle addString(llvm::StringRef Str) { return Strings.intern(Str); }
927 
928  // Convert to a canonical path.
929  std::string getCanonicalPath(llvm::StringRef path) const {
930  std::string CanonicalPath(path);
931  std::replace(CanonicalPath.begin(), CanonicalPath.end(), '\\', '/');
932  return CanonicalPath;
933  }
934 
935  // Return true if the given header is in the header list.
936  bool isHeaderListHeader(llvm::StringRef HeaderPath) const {
937  std::string CanonicalPath = getCanonicalPath(HeaderPath);
938  for (llvm::ArrayRef<std::string>::iterator I = HeaderList.begin(),
939  E = HeaderList.end();
940  I != E; ++I) {
941  if (*I == CanonicalPath)
942  return true;
943  }
944  return false;
945  }
946 
947  // Get the handle of a header file entry.
948  // Return HeaderHandleInvalid if not found.
949  HeaderHandle findHeaderHandle(llvm::StringRef HeaderPath) const {
950  std::string CanonicalPath = getCanonicalPath(HeaderPath);
951  HeaderHandle H = 0;
952  for (auto I = HeaderPaths.begin(), E = HeaderPaths.end(); I != E;
953  ++I, ++H) {
954  if (**I == CanonicalPath)
955  return H;
956  }
957  return HeaderHandleInvalid;
958  }
959 
960  // Add a new header file entry, or return existing handle.
961  // Return the header handle.
962  HeaderHandle addHeader(llvm::StringRef HeaderPath) {
963  std::string CanonicalPath = getCanonicalPath(HeaderPath);
964  HeaderHandle H = findHeaderHandle(CanonicalPath);
965  if (H == HeaderHandleInvalid) {
966  H = HeaderPaths.size();
967  HeaderPaths.push_back(addString(CanonicalPath));
968  }
969  return H;
970  }
971 
972  // Return a header file path string given its handle.
973  StringHandle getHeaderFilePath(HeaderHandle H) const {
974  if ((H >= 0) && (H < (HeaderHandle)HeaderPaths.size()))
975  return HeaderPaths[H];
976  return StringHandle();
977  }
978 
979  // Returns a handle to the inclusion path.
980  InclusionPathHandle pushHeaderHandle(HeaderHandle H) {
981  HeaderStack.push_back(H);
982  return CurrentInclusionPathHandle = addInclusionPathHandle(HeaderStack);
983  }
984  // Pops the last header handle from the stack;
985  void popHeaderHandle() {
986  // assert((HeaderStack.size() != 0) && "Header stack already empty.");
987  if (HeaderStack.size() != 0) {
988  HeaderStack.pop_back();
989  CurrentInclusionPathHandle = addInclusionPathHandle(HeaderStack);
990  }
991  }
992  // Get the top handle on the header stack.
993  HeaderHandle getCurrentHeaderHandle() const {
994  if (HeaderStack.size() != 0)
995  return HeaderStack.back();
996  return HeaderHandleInvalid;
997  }
998 
999  // Check for presence of header handle in the header stack.
1000  bool isHeaderHandleInStack(HeaderHandle H) const {
1001  for (auto I = HeaderStack.begin(), E = HeaderStack.end(); I != E; ++I) {
1002  if (*I == H)
1003  return true;
1004  }
1005  return false;
1006  }
1007 
1008  // Get the handle of a header inclusion path entry.
1009  // Return InclusionPathHandleInvalid if not found.
1010  InclusionPathHandle
1011  findInclusionPathHandle(const std::vector<HeaderHandle> &Path) const {
1012  InclusionPathHandle H = 0;
1013  for (auto I = InclusionPaths.begin(), E = InclusionPaths.end(); I != E;
1014  ++I, ++H) {
1015  if (I->Path == Path)
1016  return H;
1017  }
1018  return HeaderHandleInvalid;
1019  }
1020  // Add a new header inclusion path entry, or return existing handle.
1021  // Return the header inclusion path entry handle.
1022  InclusionPathHandle
1023  addInclusionPathHandle(const std::vector<HeaderHandle> &Path) {
1024  InclusionPathHandle H = findInclusionPathHandle(Path);
1025  if (H == HeaderHandleInvalid) {
1026  H = InclusionPaths.size();
1027  InclusionPaths.push_back(HeaderInclusionPath(Path));
1028  }
1029  return H;
1030  }
1031  // Return the current inclusion path handle.
1032  InclusionPathHandle getCurrentInclusionPathHandle() const {
1033  return CurrentInclusionPathHandle;
1034  }
1035 
1036  // Return an inclusion path given its handle.
1037  const std::vector<HeaderHandle> &
1038  getInclusionPath(InclusionPathHandle H) const {
1039  if ((H >= 0) && (H <= (InclusionPathHandle)InclusionPaths.size()))
1040  return InclusionPaths[H].Path;
1041  static std::vector<HeaderHandle> Empty;
1042  return Empty;
1043  }
1044 
1045  // Add a macro expansion instance.
1046  void addMacroExpansionInstance(clang::Preprocessor &PP, HeaderHandle H,
1047  clang::SourceLocation InstanceLoc,
1048  clang::SourceLocation DefinitionLoc,
1049  clang::IdentifierInfo *II,
1050  llvm::StringRef MacroUnexpanded,
1051  llvm::StringRef MacroExpanded,
1052  InclusionPathHandle InclusionPathHandle) {
1053  if (InNestedHeader)
1054  return;
1055  StringHandle MacroName = addString(II->getName());
1056  PPItemKey InstanceKey(PP, MacroName, H, InstanceLoc);
1057  PPItemKey DefinitionKey(PP, MacroName, H, DefinitionLoc);
1058  auto I = MacroExpansions.find(InstanceKey);
1059  // If existing instance of expansion not found, add one.
1060  if (I == MacroExpansions.end()) {
1061  std::string InstanceSourceLine =
1062  getSourceLocationString(PP, InstanceLoc) + ":\n" +
1063  getSourceLine(PP, InstanceLoc) + "\n";
1064  std::string DefinitionSourceLine =
1065  getSourceLocationString(PP, DefinitionLoc) + ":\n" +
1066  getSourceLine(PP, DefinitionLoc) + "\n";
1067  MacroExpansions[InstanceKey] = MacroExpansionTracker(
1068  addString(MacroUnexpanded), addString(MacroExpanded),
1069  addString(InstanceSourceLine), DefinitionKey,
1070  addString(DefinitionSourceLine), InclusionPathHandle);
1071  } else {
1072  // We've seen the macro before. Get its tracker.
1073  MacroExpansionTracker &CondTracker = I->second;
1074  // Look up an existing instance value for the macro.
1075  MacroExpansionInstance *MacroInfo =
1076  CondTracker.findMacroExpansionInstance(addString(MacroExpanded),
1077  DefinitionKey);
1078  // If found, just add the inclusion path to the instance.
1079  if (MacroInfo)
1080  MacroInfo->addInclusionPathHandle(InclusionPathHandle);
1081  else {
1082  // Otherwise add a new instance with the unique value.
1083  std::string DefinitionSourceLine =
1084  getSourceLocationString(PP, DefinitionLoc) + ":\n" +
1085  getSourceLine(PP, DefinitionLoc) + "\n";
1086  CondTracker.addMacroExpansionInstance(
1087  addString(MacroExpanded), DefinitionKey,
1088  addString(DefinitionSourceLine), InclusionPathHandle);
1089  }
1090  }
1091  }
1092 
1093  // Add a conditional expansion instance.
1094  void
1095  addConditionalExpansionInstance(clang::Preprocessor &PP, HeaderHandle H,
1096  clang::SourceLocation InstanceLoc,
1097  clang::tok::PPKeywordKind DirectiveKind,
1098  clang::PPCallbacks::ConditionValueKind ConditionValue,
1099  llvm::StringRef ConditionUnexpanded,
1100  InclusionPathHandle InclusionPathHandle) {
1101  // Ignore header guards, assuming the header guard is the only conditional.
1102  if (InNestedHeader)
1103  return;
1104  StringHandle ConditionUnexpandedHandle(addString(ConditionUnexpanded));
1105  PPItemKey InstanceKey(PP, ConditionUnexpandedHandle, H, InstanceLoc);
1106  auto I = ConditionalExpansions.find(InstanceKey);
1107  // If existing instance of condition not found, add one.
1108  if (I == ConditionalExpansions.end()) {
1109  std::string InstanceSourceLine =
1110  getSourceLocationString(PP, InstanceLoc) + ":\n" +
1111  getSourceLine(PP, InstanceLoc) + "\n";
1112  ConditionalExpansions[InstanceKey] =
1113  ConditionalTracker(DirectiveKind, ConditionValue,
1114  ConditionUnexpandedHandle, InclusionPathHandle);
1115  } else {
1116  // We've seen the conditional before. Get its tracker.
1117  ConditionalTracker &CondTracker = I->second;
1118  // Look up an existing instance value for the condition.
1119  ConditionalExpansionInstance *MacroInfo =
1120  CondTracker.findConditionalExpansionInstance(ConditionValue);
1121  // If found, just add the inclusion path to the instance.
1122  if (MacroInfo)
1123  MacroInfo->addInclusionPathHandle(InclusionPathHandle);
1124  else {
1125  // Otherwise add a new instance with the unique value.
1126  CondTracker.addConditionalExpansionInstance(ConditionValue,
1127  InclusionPathHandle);
1128  }
1129  }
1130  }
1131 
1132  // Report on inconsistent macro instances.
1133  // Returns true if any mismatches.
1134  bool reportInconsistentMacros(llvm::raw_ostream &OS) override {
1135  bool ReturnValue = false;
1136  // Walk all the macro expansion trackers in the map.
1137  for (auto I = MacroExpansions.begin(), E = MacroExpansions.end(); I != E;
1138  ++I) {
1139  const PPItemKey &ItemKey = I->first;
1140  MacroExpansionTracker &MacroExpTracker = I->second;
1141  // If no mismatch (only one instance value) continue.
1142  if (!MacroExpTracker.hasMismatch())
1143  continue;
1144  // Tell caller we found one or more errors.
1145  ReturnValue = true;
1146  // Start the error message.
1147  OS << *MacroExpTracker.InstanceSourceLine;
1148  if (ItemKey.Column > 0)
1149  OS << std::string(ItemKey.Column - 1, ' ') << "^\n";
1150  OS << "error: Macro instance '" << *MacroExpTracker.MacroUnexpanded
1151  << "' has different values in this header, depending on how it was "
1152  "included.\n";
1153  // Walk all the instances.
1154  for (auto IMT = MacroExpTracker.MacroExpansionInstances.begin(),
1155  EMT = MacroExpTracker.MacroExpansionInstances.end();
1156  IMT != EMT; ++IMT) {
1157  MacroExpansionInstance &MacroInfo = *IMT;
1158  OS << " '" << *MacroExpTracker.MacroUnexpanded << "' expanded to: '"
1159  << *MacroInfo.MacroExpanded
1160  << "' with respect to these inclusion paths:\n";
1161  // Walk all the inclusion path hierarchies.
1162  for (auto IIP = MacroInfo.InclusionPathHandles.begin(),
1163  EIP = MacroInfo.InclusionPathHandles.end();
1164  IIP != EIP; ++IIP) {
1165  const std::vector<HeaderHandle> &ip = getInclusionPath(*IIP);
1166  auto Count = (int)ip.size();
1167  for (int Index = 0; Index < Count; ++Index) {
1168  HeaderHandle H = ip[Index];
1169  OS << std::string((Index * 2) + 4, ' ') << *getHeaderFilePath(H)
1170  << "\n";
1171  }
1172  }
1173  // For a macro that wasn't defined, we flag it by using the
1174  // instance location.
1175  // If there is a definition...
1176  if (MacroInfo.DefinitionLocation.Line != ItemKey.Line) {
1177  OS << *MacroInfo.DefinitionSourceLine;
1178  if (MacroInfo.DefinitionLocation.Column > 0)
1179  OS << std::string(MacroInfo.DefinitionLocation.Column - 1, ' ')
1180  << "^\n";
1181  OS << "Macro defined here.\n";
1182  } else
1183  OS << "(no macro definition)"
1184  << "\n";
1185  }
1186  }
1187  return ReturnValue;
1188  }
1189 
1190  // Report on inconsistent conditional instances.
1191  // Returns true if any mismatches.
1192  bool reportInconsistentConditionals(llvm::raw_ostream &OS) override {
1193  bool ReturnValue = false;
1194  // Walk all the conditional trackers in the map.
1195  for (auto I = ConditionalExpansions.begin(),
1196  E = ConditionalExpansions.end();
1197  I != E; ++I) {
1198  const PPItemKey &ItemKey = I->first;
1199  ConditionalTracker &CondTracker = I->second;
1200  if (!CondTracker.hasMismatch())
1201  continue;
1202  // Tell caller we found one or more errors.
1203  ReturnValue = true;
1204  // Start the error message.
1205  OS << *HeaderPaths[ItemKey.File] << ":" << ItemKey.Line << ":"
1206  << ItemKey.Column << "\n";
1207  OS << "#" << getDirectiveSpelling(CondTracker.DirectiveKind) << " "
1208  << *CondTracker.ConditionUnexpanded << "\n";
1209  OS << "^\n";
1210  OS << "error: Conditional expression instance '"
1211  << *CondTracker.ConditionUnexpanded
1212  << "' has different values in this header, depending on how it was "
1213  "included.\n";
1214  // Walk all the instances.
1215  for (auto IMT = CondTracker.ConditionalExpansionInstances.begin(),
1216  EMT = CondTracker.ConditionalExpansionInstances.end();
1217  IMT != EMT; ++IMT) {
1218  ConditionalExpansionInstance &MacroInfo = *IMT;
1219  OS << " '" << *CondTracker.ConditionUnexpanded << "' expanded to: '"
1220  << ConditionValueKindStrings[MacroInfo.ConditionValue]
1221  << "' with respect to these inclusion paths:\n";
1222  // Walk all the inclusion path hierarchies.
1223  for (auto IIP = MacroInfo.InclusionPathHandles.begin(),
1224  EIP = MacroInfo.InclusionPathHandles.end();
1225  IIP != EIP; ++IIP) {
1226  const std::vector<HeaderHandle> &ip = getInclusionPath(*IIP);
1227  auto Count = (int)ip.size();
1228  for (int Index = 0; Index < Count; ++Index) {
1229  HeaderHandle H = ip[Index];
1230  OS << std::string((Index * 2) + 4, ' ') << *getHeaderFilePath(H)
1231  << "\n";
1232  }
1233  }
1234  }
1235  }
1236  return ReturnValue;
1237  }
1238 
1239  // Get directive spelling.
1240  static const char *getDirectiveSpelling(clang::tok::PPKeywordKind kind) {
1241  switch (kind) {
1242  case clang::tok::pp_if:
1243  return "if";
1244  case clang::tok::pp_elif:
1245  return "elif";
1246  case clang::tok::pp_ifdef:
1247  return "ifdef";
1248  case clang::tok::pp_ifndef:
1249  return "ifndef";
1250  default:
1251  return "(unknown)";
1252  }
1253  }
1254 
1255 private:
1256  llvm::SmallVector<std::string, 32> HeaderList;
1257  // Only do extern, namespace check for headers in HeaderList.
1259  llvm::StringPool Strings;
1260  std::vector<StringHandle> HeaderPaths;
1261  std::vector<HeaderHandle> HeaderStack;
1262  std::vector<HeaderInclusionPath> InclusionPaths;
1263  InclusionPathHandle CurrentInclusionPathHandle;
1264  llvm::SmallSet<HeaderHandle, 32> HeadersInThisCompile;
1265  std::vector<PPItemKey> IncludeDirectives;
1266  MacroExpansionMap MacroExpansions;
1267  ConditionalExpansionMap ConditionalExpansions;
1268  bool InNestedHeader;
1269 };
1270 
1271 } // namespace
1272 
1273 // PreprocessorTracker functions.
1274 
1275 // PreprocessorTracker desctructor.
1277 
1278 // Create instance of PreprocessorTracker.
1280  llvm::SmallVector<std::string, 32> &Headers,
1281  bool DoBlockCheckHeaderListOnly) {
1282  return new PreprocessorTrackerImpl(Headers, DoBlockCheckHeaderListOnly);
1283 }
1284 
1285 // Preprocessor callbacks for modularize.
1286 
1287 // Handle include directive.
1288 void PreprocessorCallbacks::InclusionDirective(
1289  clang::SourceLocation HashLoc, const clang::Token &IncludeTok,
1290  llvm::StringRef FileName, bool IsAngled,
1291  clang::CharSourceRange FilenameRange, const clang::FileEntry *File,
1292  llvm::StringRef SearchPath, llvm::StringRef RelativePath,
1293  const clang::Module *Imported, clang::SrcMgr::CharacteristicKind FileType) {
1294  int DirectiveLine, DirectiveColumn;
1295  std::string HeaderPath = getSourceLocationFile(PP, HashLoc);
1296  getSourceLocationLineAndColumn(PP, HashLoc, DirectiveLine, DirectiveColumn);
1297  PPTracker.handleIncludeDirective(HeaderPath, DirectiveLine, DirectiveColumn,
1298  FileName);
1299 }
1300 
1301 // Handle file entry/exit.
1302 void PreprocessorCallbacks::FileChanged(
1303  clang::SourceLocation Loc, clang::PPCallbacks::FileChangeReason Reason,
1304  clang::SrcMgr::CharacteristicKind FileType, clang::FileID PrevFID) {
1305  switch (Reason) {
1306  case EnterFile:
1307  PPTracker.handleHeaderEntry(PP, getSourceLocationFile(PP, Loc));
1308  break;
1309  case ExitFile: {
1310  const clang::FileEntry *F =
1311  PP.getSourceManager().getFileEntryForID(PrevFID);
1312  if (F)
1313  PPTracker.handleHeaderExit(F->getName());
1314  } break;
1315  case SystemHeaderPragma:
1316  case RenameFile:
1317  break;
1318  }
1319 }
1320 
1321 // Handle macro expansion.
1322 void PreprocessorCallbacks::MacroExpands(const clang::Token &MacroNameTok,
1323  const clang::MacroDefinition &MD,
1324  clang::SourceRange Range,
1325  const clang::MacroArgs *Args) {
1326  clang::SourceLocation Loc = Range.getBegin();
1327  // Ignore macro argument expansions.
1328  if (!Loc.isFileID())
1329  return;
1330  clang::IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
1331  const clang::MacroInfo *MI = MD.getMacroInfo();
1332  std::string MacroName = II->getName().str();
1333  std::string Unexpanded(getMacroUnexpandedString(Range, PP, MacroName, MI));
1334  std::string Expanded(getMacroExpandedString(PP, MacroName, MI, Args));
1335  PPTracker.addMacroExpansionInstance(
1336  PP, PPTracker.getCurrentHeaderHandle(), Loc, MI->getDefinitionLoc(), II,
1337  Unexpanded, Expanded, PPTracker.getCurrentInclusionPathHandle());
1338 }
1339 
1340 void PreprocessorCallbacks::Defined(const clang::Token &MacroNameTok,
1341  const clang::MacroDefinition &MD,
1342  clang::SourceRange Range) {
1343  clang::SourceLocation Loc(Range.getBegin());
1344  clang::IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
1345  const clang::MacroInfo *MI = MD.getMacroInfo();
1346  std::string MacroName = II->getName().str();
1347  std::string Unexpanded(getSourceString(PP, Range));
1348  PPTracker.addMacroExpansionInstance(
1349  PP, PPTracker.getCurrentHeaderHandle(), Loc,
1350  (MI ? MI->getDefinitionLoc() : Loc), II, Unexpanded,
1351  (MI ? "true" : "false"), PPTracker.getCurrentInclusionPathHandle());
1352 }
1353 
1354 void PreprocessorCallbacks::If(clang::SourceLocation Loc,
1355  clang::SourceRange ConditionRange,
1356  clang::PPCallbacks::ConditionValueKind ConditionResult) {
1357  std::string Unexpanded(getSourceString(PP, ConditionRange));
1358  PPTracker.addConditionalExpansionInstance(
1359  PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_if,
1360  ConditionResult, Unexpanded, PPTracker.getCurrentInclusionPathHandle());
1361 }
1362 
1363 void PreprocessorCallbacks::Elif(clang::SourceLocation Loc,
1364  clang::SourceRange ConditionRange,
1365  clang::PPCallbacks::ConditionValueKind ConditionResult,
1366  clang::SourceLocation IfLoc) {
1367  std::string Unexpanded(getSourceString(PP, ConditionRange));
1368  PPTracker.addConditionalExpansionInstance(
1369  PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_elif,
1370  ConditionResult, Unexpanded, PPTracker.getCurrentInclusionPathHandle());
1371 }
1372 
1373 void PreprocessorCallbacks::Ifdef(clang::SourceLocation Loc,
1374  const clang::Token &MacroNameTok,
1375  const clang::MacroDefinition &MD) {
1376  clang::PPCallbacks::ConditionValueKind IsDefined =
1377  (MD ? clang::PPCallbacks::CVK_True : clang::PPCallbacks::CVK_False );
1378  PPTracker.addConditionalExpansionInstance(
1379  PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_ifdef,
1380  IsDefined, PP.getSpelling(MacroNameTok),
1381  PPTracker.getCurrentInclusionPathHandle());
1382 }
1383 
1384 void PreprocessorCallbacks::Ifndef(clang::SourceLocation Loc,
1385  const clang::Token &MacroNameTok,
1386  const clang::MacroDefinition &MD) {
1387  clang::PPCallbacks::ConditionValueKind IsNotDefined =
1388  (!MD ? clang::PPCallbacks::CVK_True : clang::PPCallbacks::CVK_False );
1389  PPTracker.addConditionalExpansionInstance(
1390  PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_ifndef,
1391  IsNotDefined, PP.getSpelling(MacroNameTok),
1392  PPTracker.getCurrentInclusionPathHandle());
1393 }
1394 } // end namespace Modularize
StringHandle DefinitionSourceLine
SourceLocation Loc
&#39;#&#39; location in the include directive
StringHandle InstanceSourceLine
static std::string getCanonicalPath(llvm::StringRef FilePath)
Convert header path to canonical form.
static std::string getSourceString(clang::Preprocessor &PP, clang::SourceRange Range)
StringHandle Name
HeaderHandle File
bool operator==(const SymbolLocation::Position &L, const SymbolLocation::Position &R)
Definition: Index.h:51
int Column
static void getSourceLocationLineAndColumn(clang::Preprocessor &PP, clang::SourceLocation Loc, int &Line, int &Column)
const HeaderHandle HeaderHandleInvalid
std::vector< HeaderHandle > Path
static std::string getSourceLocationFile(clang::Preprocessor &PP, clang::SourceLocation Loc)
ModularizeUtilities class definition.
static std::string getMacroUnexpandedString(clang::SourceRange Range, clang::Preprocessor &PP, llvm::StringRef MacroName, const clang::MacroInfo *MI)
clang::tok::PPKeywordKind DirectiveKind
bool operator<(const SymbolLocation::Position &L, const SymbolLocation::Position &R)
Definition: Index.h:55
StringHandle MacroUnexpanded
static cl::opt< bool > BlockCheckHeaderListOnly("block-check-header-list-only", cl::init(false), cl::desc("Only warn if #include directives are inside extern or namespace" " blocks if the included header is in the header list."))
const InclusionPathHandle InclusionPathHandleInvalid
StringHandle MacroExpanded
std::vector< MacroExpansionInstance > MacroExpansionInstances
bool IsAngled
true if this was an include with angle brackets
std::vector< StringRef > Strings
static std::string getSourceLine(clang::Preprocessor &PP, clang::SourceLocation Loc)
StringHandle ConditionUnexpanded
PathRef FileName
std::vector< InclusionPathHandle > InclusionPathHandles
clang::PPCallbacks::ConditionValueKind ConditionValue
static PreprocessorTracker * create(llvm::SmallVector< std::string, 32 > &Headers, bool DoBlockCheckHeaderListOnly)
PPItemKey DefinitionLocation
static const char *const ConditionValueKindStrings[]
static GeneratorRegistry::Add< MDGenerator > MD(MDGenerator::Format, "Generator for MD output.")
CharSourceRange Range
SourceRange for the file name.
Macro expansions and preprocessor conditional consistency checker.
static std::string getSourceLocationString(clang::Preprocessor &PP, clang::SourceLocation Loc)
static std::string getMacroExpandedString(clang::Preprocessor &PP, llvm::StringRef MacroName, const clang::MacroInfo *MI, const clang::MacroArgs *Args)
Preprocessor tracker for modularize.
std::vector< ConditionalExpansionInstance > ConditionalExpansionInstances
llvm::PooledStringPtr StringHandle