blob: 6cb34c7b25a481cd87609a837fc716511b558071 [file] [log] [blame]
John Thompson7c6e79f32013-07-29 19:07:00 +00001//===--- PreprocessorTracker.cpp - Preprocessor tracking -*- C++ -*------===//
John Thompson94faa4d2013-07-26 23:56:42 +00002//
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//
John Thompson7c6e79f32013-07-29 19:07:00 +00008//===--------------------------------------------------------------------===//
9//
John Thompson74083922013-09-18 18:19:43 +000010// The Basic Idea (Macro and Conditional Checking)
John Thompson94faa4d2013-07-26 23:56:42 +000011//
12// Basically we install a PPCallbacks-derived object to track preprocessor
13// activity, namely when a header file is entered/exited, when a macro
John Thompson7c6e79f32013-07-29 19:07:00 +000014// is expanded, when "defined" is used, and when #if, #elif, #ifdef,
15// and #ifndef are used. We save the state of macro and "defined"
John Thompson94faa4d2013-07-26 23:56:42 +000016// expressions in a map, keyed on a name/file/line/column quadruple.
John Thompson7c6e79f32013-07-29 19:07:00 +000017// The map entries store the different states (values) that a macro expansion,
18// "defined" expression, or condition expression has in the course of
John Thompson94faa4d2013-07-26 23:56:42 +000019// 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
John Thompson7c6e79f32013-07-29 19:07:00 +000021// or "defined" expression evaluates to the same value, which is the
John Thompson94faa4d2013-07-26 23:56:42 +000022// 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,
John Thompson7c6e79f32013-07-29 19:07:00 +000027// 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.
John Thompson94faa4d2013-07-26 23:56:42 +000051//
John Thompson74083922013-09-18 18:19:43 +000052// 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)
John Thompson94faa4d2013-07-26 23:56:42 +000063//
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
John Thompson7c6e79f32013-07-29 19:07:00 +000067// expansions, use of "defined" expressions, and #if, #elif, #ifdef, and
John Thompson94faa4d2013-07-26 23:56:42 +000068// #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
John Thompson7c6e79f32013-07-29 19:07:00 +000077// of a "defined" expression in a header file. It stores a handle to a
John Thompson94faa4d2013-07-26 23:56:42 +000078// 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
John Thompsoncc2e2912013-09-03 18:44:11 +000089// values that represents the hierarchies of include files for each case
John Thompson94faa4d2013-07-26 23:56:42 +000090// 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
John Thompson7c6e79f32013-07-29 19:07:00 +0000101// InclusionPathHandle representing that case's include file hierarchy
John Thompson94faa4d2013-07-26 23:56:42 +0000102// 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
John Thompson7c6e79f32013-07-29 19:07:00 +0000119// headers, which is just a vector of StringHandle's for the header file
John Thompson94faa4d2013-07-26 23:56:42 +0000120// paths. A HeaderHandle abstracts a reference to a header, and is simply
121// the index of the stored header file path.
122//
John Thompson7c6e79f32013-07-29 19:07:00 +0000123// A HeaderInclusionPath class abstracts a unique hierarchy of header file
John Thompson94faa4d2013-07-26 23:56:42 +0000124// 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
John Thompson7c6e79f32013-07-29 19:07:00 +0000130// MacroExpansionInstance object stores a vector of these handles so that
John Thompson94faa4d2013-07-26 23:56:42 +0000131// 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
John Thompson7c6e79f32013-07-29 19:07:00 +0000145// PreprocessorTracker's handleNewPreprocessorEntry function, which sets
John Thompson94faa4d2013-07-26 23:56:42 +0000146// up a PreprocessorCallbacks object for the preprocessor. At the end of
John Thompson7c6e79f32013-07-29 19:07:00 +0000147// the compilation instance, the PreprocessorTracker's
John Thompson94faa4d2013-07-26 23:56:42 +0000148// 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
John Thompson7c6e79f32013-07-29 19:07:00 +0000153// header during #include directives). It calls PreprocessorTracker's
John Thompson94faa4d2013-07-26 23:56:42 +0000154// 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
John Thompson7c6e79f32013-07-29 19:07:00 +0000163// then calls PreprocessorTrackerImpl's addMacroExpansionInstance function to
John Thompson94faa4d2013-07-26 23:56:42 +0000164// do the rest of the work. The getMacroExpandedString function uses the
John Thompson7c6e79f32013-07-29 19:07:00 +0000165// preprocessor's getSpelling to convert tokens to strings using the
John Thompson94faa4d2013-07-26 23:56:42 +0000166// 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//
John Thompson7c6e79f32013-07-29 19:07:00 +0000170// PreprocessorTrackerImpl's addMacroExpansionInstance function looks for
John Thompson94faa4d2013-07-26 23:56:42 +0000171// 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
John Thompson7c6e79f32013-07-29 19:07:00 +0000184// source manager doesn't exist at the time of the reporting.
John Thompson94faa4d2013-07-26 23:56:42 +0000185//
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
John Thompson7c6e79f32013-07-29 19:07:00 +0000191// the conditional, and if a ConditionalTracker object doesn't yet exist for
John Thompson94faa4d2013-07-26 23:56:42 +0000192// 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.
John Thompsoncc2e2912013-09-03 18:44:11 +0000202//
John Thompson94faa4d2013-07-26 23:56:42 +0000203// After modularize has performed all the compilations, it enters a phase
204// of error reporting. This new feature adds to this reporting phase calls
John Thompson7c6e79f32013-07-29 19:07:00 +0000205// to the PreprocessorTracker's reportInconsistentMacros and
John Thompson94faa4d2013-07-26 23:56:42 +0000206// reportInconsistentConditionals functions. These functions walk the maps
John Thompson7c6e79f32013-07-29 19:07:00 +0000207// of MacroExpansionTracker's and ConditionalTracker's respectively. If
John Thompson94faa4d2013-07-26 23:56:42 +0000208// 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,
John Thompson7c6e79f32013-07-29 19:07:00 +0000214// leaving just the #ifdef and #ifndef, since these don't overlap. Or,
John Thompson94faa4d2013-07-26 23:56:42 +0000215// to make clearer the separate reporting phases, I could add an output
216// message marking the phases.
217//
John Thompson74083922013-09-18 18:19:43 +0000218// 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//
John Thompson94faa4d2013-07-26 23:56:42 +0000234// 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"
Chandler Carruth85e6e872014-01-07 20:05:01 +0000248#include "PreprocessorTracker.h"
John Thompson94faa4d2013-07-26 23:56:42 +0000249#include "clang/Lex/MacroArgs.h"
250#include "clang/Lex/PPCallbacks.h"
John Thompson4ed963a2013-08-07 18:49:47 +0000251#include "llvm/ADT/SmallSet.h"
Chandler Carruth85e6e872014-01-07 20:05:01 +0000252#include "llvm/Support/StringPool.h"
253#include "llvm/Support/raw_ostream.h"
John Thompsonb70ecf62015-02-26 19:31:10 +0000254#include "ModularizeUtilities.h"
John Thompson94faa4d2013-07-26 23:56:42 +0000255
256namespace Modularize {
257
John Thompson94faa4d2013-07-26 23:56:42 +0000258// Some handle types
259typedef llvm::PooledStringPtr StringHandle;
260
261typedef int HeaderHandle;
262const HeaderHandle HeaderHandleInvalid = -1;
263
264typedef int InclusionPathHandle;
265const InclusionPathHandle InclusionPathHandleInvalid = -1;
266
267// Some utility functions.
268
269// Get a "file:line:column" source location string.
270static 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.
279static 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.
289static 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.
Benjamin Kramere7103712015-03-23 12:49:15 +0000303static std::string getSourceString(clang::Preprocessor &PP,
304 clang::SourceRange Range) {
John Thompson94faa4d2013-07-26 23:56:42 +0000305 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
John Thompson74083922013-09-18 18:19:43 +0000313// Retrieve source line from file image given a location.
Benjamin Kramere7103712015-03-23 12:49:15 +0000314static std::string getSourceLine(clang::Preprocessor &PP,
315 clang::SourceLocation Loc) {
John Thompson94faa4d2013-07-26 23:56:42 +0000316 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
John Thompson74083922013-09-18 18:19:43 +0000339// Retrieve source line from file image given a file ID and line number.
Benjamin Kramere7103712015-03-23 12:49:15 +0000340static std::string getSourceLine(clang::Preprocessor &PP, clang::FileID FileID,
341 int Line) {
John Thompson74083922013-09-18 18:19:43 +0000342 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
John Thompson94faa4d2013-07-26 23:56:42 +0000372// 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.
Benjamin Kramere7103712015-03-23 12:49:15 +0000377static std::string getMacroUnexpandedString(clang::SourceRange Range,
378 clang::Preprocessor &PP,
379 llvm::StringRef MacroName,
380 const clang::MacroInfo *MI) {
John Thompson94faa4d2013-07-26 23:56:42 +0000381 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.
John Thompson91555bd2013-08-09 00:22:20 +0000396// 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.
Benjamin Kramere7103712015-03-23 12:49:15 +0000402static std::string getMacroExpandedString(clang::Preprocessor &PP,
403 llvm::StringRef MacroName,
404 const clang::MacroInfo *MI,
405 const clang::MacroArgs *Args) {
John Thompson94faa4d2013-07-26 23:56:42 +0000406 std::string Expanded;
407 // Walk over the macro Tokens.
Daniel Marjamaki89ec7232015-05-11 08:26:25 +0000408 for (const auto &T : MI->tokens()) {
409 clang::IdentifierInfo *II = T.getIdentifierInfo();
Faisal Valicb8e01a2017-07-17 17:20:57 +0000410 int ArgNo = (II && Args ? MI->getParameterNum(II) : -1);
John Thompson94faa4d2013-07-26 23:56:42 +0000411 if (ArgNo == -1) {
412 // This isn't an argument, just add it.
Craig Topperf61be9c2014-06-09 02:03:06 +0000413 if (II == nullptr)
Daniel Marjamaki89ec7232015-05-11 08:26:25 +0000414 Expanded += PP.getSpelling(T); // Not an identifier.
John Thompson94faa4d2013-07-26 23:56:42 +0000415 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);
John Thompsonfcf3f472015-05-06 18:39:15 +0000420 if (MacroInfo && (Name != MacroName))
Craig Topperf61be9c2014-06-09 02:03:06 +0000421 Expanded += getMacroExpandedString(PP, Name, MacroInfo, nullptr);
John Thompson94faa4d2013-07-26 23:56:42 +0000422 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))
Faisal Valia8e84622017-09-30 14:36:00 +0000432 ->getPreExpArgument(ArgNo, PP)[0];
John Thompson94faa4d2013-07-26 23:56:42 +0000433 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();
Craig Topperf61be9c2014-06-09 02:03:06 +0000443 if (II == nullptr)
John Thompson94faa4d2013-07-26 23:56:42 +0000444 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);
Craig Topperf61be9c2014-06-09 02:03:06 +0000449 if (MacroInfo)
450 Expanded += getMacroExpandedString(PP, Name, MacroInfo, nullptr);
John Thompson94faa4d2013-07-26 23:56:42 +0000451 else
452 Expanded += Name;
453 }
454 }
455 }
456 return Expanded;
457}
458
Benjamin Kramere7103712015-03-23 12:49:15 +0000459namespace {
John Thompson94faa4d2013-07-26 23:56:42 +0000460
John Thompson87f9fef2013-12-07 08:41:15 +0000461// ConditionValueKind strings.
462const char *
463ConditionValueKindStrings[] = {
464 "(not evaluated)", "false", "true"
465};
466
John Thompson94faa4d2013-07-26 23:56:42 +0000467bool 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}
473bool 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.
488class PPItemKey {
489public:
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.
532class HeaderInclusionPath {
533public:
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
John Thompson7c6e79f32013-07-29 19:07:00 +0000545// for use in telling the user the nested include path to the header.
John Thompson94faa4d2013-07-26 23:56:42 +0000546class MacroExpansionInstance {
547public:
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) {
Piotr Padlewski08124b12016-12-14 15:29:23 +0000561 for (auto I = InclusionPathHandles.begin(), E = InclusionPathHandles.end();
John Thompson94faa4d2013-07-26 23:56:42 +0000562 I != E; ++I) {
563 if (*I == H)
564 return true;
565 }
566 return InclusionPathHandleInvalid;
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.
577 PPItemKey DefinitionLocation;
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
John Thompson7c6e79f32013-07-29 19:07:00 +0000589// the unique values the condition expands to in instances of the header.
John Thompson94faa4d2013-07-26 23:56:42 +0000590class MacroExpansionTracker {
591public:
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) {
Piotr Padlewski08124b12016-12-14 15:29:23 +0000609 for (auto I = MacroExpansionInstances.begin(),
610 E = MacroExpansionInstances.end();
John Thompson94faa4d2013-07-26 23:56:42 +0000611 I != E; ++I) {
612 if ((I->MacroExpanded == MacroExpanded) &&
613 (I->DefinitionLocation == DefinitionLocation)) {
614 return &*I; // Found.
615 }
616 }
Craig Topperf61be9c2014-06-09 02:03:06 +0000617 return nullptr; // Not found.
John Thompson94faa4d2013-07-26 23:56:42 +0000618 }
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//
John Thompson7c6e79f32013-07-29 19:07:00 +0000645// 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.
John Thompson94faa4d2013-07-26 23:56:42 +0000648class ConditionalExpansionInstance {
649public:
John Thompson87f9fef2013-12-07 08:41:15 +0000650 ConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind ConditionValue, InclusionPathHandle H)
John Thompson94faa4d2013-07-26 23:56:42 +0000651 : 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) {
Piotr Padlewski08124b12016-12-14 15:29:23 +0000659 for (auto I = InclusionPathHandles.begin(), E = InclusionPathHandles.end();
John Thompson94faa4d2013-07-26 23:56:42 +0000660 I != E; ++I) {
661 if (*I == H)
662 return true;
663 }
664 return InclusionPathHandleInvalid;
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.
John Thompson87f9fef2013-12-07 08:41:15 +0000673 clang::PPCallbacks::ConditionValueKind ConditionValue;
John Thompson94faa4d2013-07-26 23:56:42 +0000674 // 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,
John Thompson7c6e79f32013-07-29 19:07:00 +0000682// and a list of ConditionExpansionInstance objects representing
683// the unique value the condition expression expands to in instances of
684// the header.
John Thompson94faa4d2013-07-26 23:56:42 +0000685class ConditionalTracker {
686public:
687 ConditionalTracker(clang::tok::PPKeywordKind DirectiveKind,
John Thompson87f9fef2013-12-07 08:41:15 +0000688 clang::PPCallbacks::ConditionValueKind ConditionValue,
689 StringHandle ConditionUnexpanded,
John Thompson94faa4d2013-07-26 23:56:42 +0000690 InclusionPathHandle InclusionPathHandle)
691 : DirectiveKind(DirectiveKind), ConditionUnexpanded(ConditionUnexpanded) {
692 addConditionalExpansionInstance(ConditionValue, InclusionPathHandle);
693 }
694 ConditionalTracker() {}
695
696 // Find a matching condition expansion instance.
697 ConditionalExpansionInstance *
John Thompson87f9fef2013-12-07 08:41:15 +0000698 findConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind ConditionValue) {
Piotr Padlewski08124b12016-12-14 15:29:23 +0000699 for (auto I = ConditionalExpansionInstances.begin(),
700 E = ConditionalExpansionInstances.end();
John Thompson94faa4d2013-07-26 23:56:42 +0000701 I != E; ++I) {
702 if (I->ConditionValue == ConditionValue) {
703 return &*I; // Found.
704 }
705 }
Craig Topperf61be9c2014-06-09 02:03:06 +0000706 return nullptr; // Not found.
John Thompson94faa4d2013-07-26 23:56:42 +0000707 }
708
709 // Add a conditional expansion instance.
710 void
John Thompson87f9fef2013-12-07 08:41:15 +0000711 addConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind ConditionValue,
John Thompson94faa4d2013-07-26 23:56:42 +0000712 InclusionPathHandle InclusionPathHandle) {
713 ConditionalExpansionInstances.push_back(
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
Benjamin Kramere7103712015-03-23 12:49:15 +0000730class PreprocessorTrackerImpl;
731
John Thompson94faa4d2013-07-26 23:56:42 +0000732// 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.
738class PreprocessorCallbacks : public clang::PPCallbacks {
739public:
740 PreprocessorCallbacks(PreprocessorTrackerImpl &ppTracker,
741 clang::Preprocessor &PP, llvm::StringRef rootHeaderFile)
742 : PPTracker(ppTracker), PP(PP), RootHeaderFile(rootHeaderFile) {}
David Blaikiee04a3da2015-10-20 21:45:52 +0000743 ~PreprocessorCallbacks() override {}
John Thompson94faa4d2013-07-26 23:56:42 +0000744
745 // Overridden handlers.
John Thompson74083922013-09-18 18:19:43 +0000746 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,
Julie Hockett546943f2018-05-10 19:13:14 +0000753 const clang::Module *Imported,
754 clang::SrcMgr::CharacteristicKind FileType) override;
John Thompson94faa4d2013-07-26 23:56:42 +0000755 void FileChanged(clang::SourceLocation Loc,
756 clang::PPCallbacks::FileChangeReason Reason,
757 clang::SrcMgr::CharacteristicKind FileType,
Alexander Kornienko87638f62015-04-11 07:59:33 +0000758 clang::FileID PrevFID = clang::FileID()) override;
John Thompson94faa4d2013-07-26 23:56:42 +0000759 void MacroExpands(const clang::Token &MacroNameTok,
Richard Smith33de8562015-05-04 03:15:55 +0000760 const clang::MacroDefinition &MD, clang::SourceRange Range,
Alexander Kornienko87638f62015-04-11 07:59:33 +0000761 const clang::MacroArgs *Args) override;
John Thompson94faa4d2013-07-26 23:56:42 +0000762 void Defined(const clang::Token &MacroNameTok,
Richard Smith33de8562015-05-04 03:15:55 +0000763 const clang::MacroDefinition &MD,
Alexander Kornienko87638f62015-04-11 07:59:33 +0000764 clang::SourceRange Range) override;
John Thompson94faa4d2013-07-26 23:56:42 +0000765 void If(clang::SourceLocation Loc, clang::SourceRange ConditionRange,
Alexander Kornienko87638f62015-04-11 07:59:33 +0000766 clang::PPCallbacks::ConditionValueKind ConditionResult) override;
John Thompson94faa4d2013-07-26 23:56:42 +0000767 void Elif(clang::SourceLocation Loc, clang::SourceRange ConditionRange,
Alexander Kornienko87638f62015-04-11 07:59:33 +0000768 clang::PPCallbacks::ConditionValueKind ConditionResult,
769 clang::SourceLocation IfLoc) override;
John Thompson94faa4d2013-07-26 23:56:42 +0000770 void Ifdef(clang::SourceLocation Loc, const clang::Token &MacroNameTok,
Richard Smith33de8562015-05-04 03:15:55 +0000771 const clang::MacroDefinition &MD) override;
John Thompson94faa4d2013-07-26 23:56:42 +0000772 void Ifndef(clang::SourceLocation Loc, const clang::Token &MacroNameTok,
Richard Smith33de8562015-05-04 03:15:55 +0000773 const clang::MacroDefinition &MD) override;
John Thompson94faa4d2013-07-26 23:56:42 +0000774
775private:
776 PreprocessorTrackerImpl &PPTracker;
777 clang::Preprocessor &PP;
778 std::string RootHeaderFile;
779};
780
781// Preprocessor macro expansion item map types.
782typedef std::map<PPItemKey, MacroExpansionTracker> MacroExpansionMap;
783typedef std::map<PPItemKey, MacroExpansionTracker>::iterator
784MacroExpansionMapIter;
785
786// Preprocessor conditional expansion item map types.
787typedef std::map<PPItemKey, ConditionalTracker> ConditionalExpansionMap;
788typedef std::map<PPItemKey, ConditionalTracker>::iterator
789ConditionalExpansionMapIter;
790
791// Preprocessor tracker for modularize.
792//
793// This class stores information about all the headers processed in the
794// course of running modularize.
795class PreprocessorTrackerImpl : public PreprocessorTracker {
796public:
John Thompsonecd3b042015-02-11 16:58:36 +0000797 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
David Blaikiee04a3da2015-10-20 21:45:52 +0000810 ~PreprocessorTrackerImpl() override {}
John Thompson94faa4d2013-07-26 23:56:42 +0000811
812 // Handle entering a preprocessing session.
813 void handlePreprocessorEntry(clang::Preprocessor &PP,
Alexander Kornienko87638f62015-04-11 07:59:33 +0000814 llvm::StringRef rootHeaderFile) override {
John Thompson4ed963a2013-08-07 18:49:47 +0000815 HeadersInThisCompile.clear();
John Thompson94faa4d2013-07-26 23:56:42 +0000816 assert((HeaderStack.size() == 0) && "Header stack should be empty.");
817 pushHeaderHandle(addHeader(rootHeaderFile));
Craig Topper775862a2014-09-10 05:07:57 +0000818 PP.addPPCallbacks(llvm::make_unique<PreprocessorCallbacks>(*this, PP,
819 rootHeaderFile));
John Thompson94faa4d2013-07-26 23:56:42 +0000820 }
821 // Handle exiting a preprocessing session.
Alexander Kornienko87638f62015-04-11 07:59:33 +0000822 void handlePreprocessorExit() override { HeaderStack.clear(); }
John Thompson94faa4d2013-07-26 23:56:42 +0000823
John Thompson74083922013-09-18 18:19:43 +0000824 // 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,
Alexander Kornienko87638f62015-04-11 07:59:33 +0000829 int DirectiveColumn,
830 llvm::StringRef TargetPath) override {
John Thompsonecd3b042015-02-11 16:58:36 +0000831 // If it's not a header in the header list, ignore it with respect to
832 // the check.
John Thompson9ea81b02015-02-13 23:32:08 +0000833 if (BlockCheckHeaderListOnly && !isHeaderListHeader(TargetPath))
John Thompsonecd3b042015-02-11 16:58:36 +0000834 return;
John Thompson74083922013-09-18 18:19:43 +0000835 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,
Alexander Kornienko87638f62015-04-11 07:59:33 +0000855 llvm::raw_ostream &OS) override {
John Thompson74083922013-09-18 18:19:43 +0000856 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);
John Thompsonb70ecf62015-02-26 19:31:10 +0000862 SourcePath = ModularizeUtilities::getCanonicalPath(SourcePath);
John Thompson74083922013-09-18 18:19:43 +0000863 HeaderHandle SourceHandle = findHeaderHandle(SourcePath);
John Thompsonb87fd7d2015-02-18 16:12:26 +0000864 if (SourceHandle == -1)
865 return true;
John Thompson74083922013-09-18 18:19:43 +0000866 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;
John Thompsona2b66872013-09-20 14:44:20 +0000879 OS << SourcePath << ":" << I->Line << ":" << I->Column << ":\n";
John Thompson74083922013-09-18 18:19:43 +0000880 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
John Thompsona2b66872013-09-20 14:44:20 +0000886 << ":\n";
John Thompson74083922013-09-18 18:19:43 +0000887 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
John Thompson94faa4d2013-07-26 23:56:42 +0000896 // 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);
John Thompson4ed963a2013-08-07 18:49:47 +0000902 if (H != getCurrentHeaderHandle())
John Thompson94faa4d2013-07-26 23:56:42 +0000903 pushHeaderHandle(H);
John Thompson4ed963a2013-08-07 18:49:47 +0000904 // Check for nested header.
905 if (!InNestedHeader)
David Blaikie34318812014-11-19 07:49:54 +0000906 InNestedHeader = !HeadersInThisCompile.insert(H).second;
John Thompson94faa4d2013-07-26 23:56:42 +0000907 }
John Thompsonecd3b042015-02-11 16:58:36 +0000908
John Thompson94faa4d2013-07-26 23:56:42 +0000909 // 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);
John Thompsonf1828ef2015-02-12 15:26:17 +0000915 HeaderHandle TH;
John Thompson94faa4d2013-07-26 23:56:42 +0000916 if (isHeaderHandleInStack(H)) {
John Thompsonf1828ef2015-02-12 15:26:17 +0000917 do {
918 TH = getCurrentHeaderHandle();
John Thompson94faa4d2013-07-26 23:56:42 +0000919 popHeaderHandle();
John Thompsonf1828ef2015-02-12 15:26:17 +0000920 } while ((TH != H) && (HeaderStack.size() != 0));
John Thompson94faa4d2013-07-26 23:56:42 +0000921 }
John Thompson48df0962013-08-05 23:55:14 +0000922 InNestedHeader = false;
John Thompson94faa4d2013-07-26 23:56:42 +0000923 }
924
925 // Lookup/add string.
926 StringHandle addString(llvm::StringRef Str) { return Strings.intern(Str); }
927
John Thompson97244312015-02-11 16:45:50 +0000928 // 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
John Thompsonecd3b042015-02-11 16:58:36 +0000935 // 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
John Thompson94faa4d2013-07-26 23:56:42 +0000947 // Get the handle of a header file entry.
948 // Return HeaderHandleInvalid if not found.
949 HeaderHandle findHeaderHandle(llvm::StringRef HeaderPath) const {
John Thompson97244312015-02-11 16:45:50 +0000950 std::string CanonicalPath = getCanonicalPath(HeaderPath);
John Thompson94faa4d2013-07-26 23:56:42 +0000951 HeaderHandle H = 0;
Piotr Padlewski08124b12016-12-14 15:29:23 +0000952 for (auto I = HeaderPaths.begin(), E = HeaderPaths.end(); I != E;
953 ++I, ++H) {
John Thompson48df0962013-08-05 23:55:14 +0000954 if (**I == CanonicalPath)
John Thompson94faa4d2013-07-26 23:56:42 +0000955 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) {
John Thompson97244312015-02-11 16:45:50 +0000963 std::string CanonicalPath = getCanonicalPath(HeaderPath);
John Thompson48df0962013-08-05 23:55:14 +0000964 HeaderHandle H = findHeaderHandle(CanonicalPath);
John Thompson94faa4d2013-07-26 23:56:42 +0000965 if (H == HeaderHandleInvalid) {
966 H = HeaderPaths.size();
John Thompson48df0962013-08-05 23:55:14 +0000967 HeaderPaths.push_back(addString(CanonicalPath));
John Thompson94faa4d2013-07-26 23:56:42 +0000968 }
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 {
Piotr Padlewski08124b12016-12-14 15:29:23 +00001001 for (auto I = HeaderStack.begin(), E = HeaderStack.end(); I != E; ++I) {
John Thompson94faa4d2013-07-26 23:56:42 +00001002 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;
Piotr Padlewski08124b12016-12-14 15:29:23 +00001013 for (auto I = InclusionPaths.begin(), E = InclusionPaths.end(); I != E;
1014 ++I, ++H) {
John Thompson94faa4d2013-07-26 23:56:42 +00001015 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) {
John Thompsonc8d710c2013-08-13 18:11:36 +00001053 if (InNestedHeader)
1054 return;
John Thompson94faa4d2013-07-26 23:56:42 +00001055 StringHandle MacroName = addString(II->getName());
1056 PPItemKey InstanceKey(PP, MacroName, H, InstanceLoc);
1057 PPItemKey DefinitionKey(PP, MacroName, H, DefinitionLoc);
Piotr Padlewski08124b12016-12-14 15:29:23 +00001058 auto I = MacroExpansions.find(InstanceKey);
John Thompson7c6e79f32013-07-29 19:07:00 +00001059 // If existing instance of expansion not found, add one.
John Thompson94faa4d2013-07-26 23:56:42 +00001060 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 {
John Thompson7c6e79f32013-07-29 19:07:00 +00001072 // We've seen the macro before. Get its tracker.
John Thompson94faa4d2013-07-26 23:56:42 +00001073 MacroExpansionTracker &CondTracker = I->second;
John Thompson7c6e79f32013-07-29 19:07:00 +00001074 // Look up an existing instance value for the macro.
John Thompson94faa4d2013-07-26 23:56:42 +00001075 MacroExpansionInstance *MacroInfo =
1076 CondTracker.findMacroExpansionInstance(addString(MacroExpanded),
1077 DefinitionKey);
John Thompson7c6e79f32013-07-29 19:07:00 +00001078 // If found, just add the inclusion path to the instance.
Craig Topperf61be9c2014-06-09 02:03:06 +00001079 if (MacroInfo)
John Thompson94faa4d2013-07-26 23:56:42 +00001080 MacroInfo->addInclusionPathHandle(InclusionPathHandle);
1081 else {
John Thompson7c6e79f32013-07-29 19:07:00 +00001082 // Otherwise add a new instance with the unique value.
John Thompson94faa4d2013-07-26 23:56:42 +00001083 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,
John Thompson87f9fef2013-12-07 08:41:15 +00001098 clang::PPCallbacks::ConditionValueKind ConditionValue,
John Thompson94faa4d2013-07-26 23:56:42 +00001099 llvm::StringRef ConditionUnexpanded,
1100 InclusionPathHandle InclusionPathHandle) {
John Thompson48df0962013-08-05 23:55:14 +00001101 // Ignore header guards, assuming the header guard is the only conditional.
1102 if (InNestedHeader)
1103 return;
John Thompson94faa4d2013-07-26 23:56:42 +00001104 StringHandle ConditionUnexpandedHandle(addString(ConditionUnexpanded));
1105 PPItemKey InstanceKey(PP, ConditionUnexpandedHandle, H, InstanceLoc);
Piotr Padlewski08124b12016-12-14 15:29:23 +00001106 auto I = ConditionalExpansions.find(InstanceKey);
John Thompson7c6e79f32013-07-29 19:07:00 +00001107 // If existing instance of condition not found, add one.
John Thompson94faa4d2013-07-26 23:56:42 +00001108 if (I == ConditionalExpansions.end()) {
1109 std::string InstanceSourceLine =
1110 getSourceLocationString(PP, InstanceLoc) + ":\n" +
1111 getSourceLine(PP, InstanceLoc) + "\n";
1112 ConditionalExpansions[InstanceKey] =
John Thompson48df0962013-08-05 23:55:14 +00001113 ConditionalTracker(DirectiveKind, ConditionValue,
John Thompsoncc2e2912013-09-03 18:44:11 +00001114 ConditionUnexpandedHandle, InclusionPathHandle);
John Thompson94faa4d2013-07-26 23:56:42 +00001115 } else {
John Thompson7c6e79f32013-07-29 19:07:00 +00001116 // We've seen the conditional before. Get its tracker.
John Thompson94faa4d2013-07-26 23:56:42 +00001117 ConditionalTracker &CondTracker = I->second;
John Thompson7c6e79f32013-07-29 19:07:00 +00001118 // Look up an existing instance value for the condition.
John Thompson94faa4d2013-07-26 23:56:42 +00001119 ConditionalExpansionInstance *MacroInfo =
1120 CondTracker.findConditionalExpansionInstance(ConditionValue);
John Thompson7c6e79f32013-07-29 19:07:00 +00001121 // If found, just add the inclusion path to the instance.
Craig Topperf61be9c2014-06-09 02:03:06 +00001122 if (MacroInfo)
John Thompson94faa4d2013-07-26 23:56:42 +00001123 MacroInfo->addInclusionPathHandle(InclusionPathHandle);
1124 else {
John Thompson7c6e79f32013-07-29 19:07:00 +00001125 // Otherwise add a new instance with the unique value.
John Thompson94faa4d2013-07-26 23:56:42 +00001126 CondTracker.addConditionalExpansionInstance(ConditionValue,
1127 InclusionPathHandle);
1128 }
1129 }
1130 }
1131
1132 // Report on inconsistent macro instances.
1133 // Returns true if any mismatches.
Alexander Kornienko87638f62015-04-11 07:59:33 +00001134 bool reportInconsistentMacros(llvm::raw_ostream &OS) override {
John Thompson94faa4d2013-07-26 23:56:42 +00001135 bool ReturnValue = false;
John Thompson7c6e79f32013-07-29 19:07:00 +00001136 // Walk all the macro expansion trackers in the map.
Piotr Padlewski08124b12016-12-14 15:29:23 +00001137 for (auto I = MacroExpansions.begin(), E = MacroExpansions.end(); I != E;
1138 ++I) {
John Thompson94faa4d2013-07-26 23:56:42 +00001139 const PPItemKey &ItemKey = I->first;
1140 MacroExpansionTracker &MacroExpTracker = I->second;
John Thompson7c6e79f32013-07-29 19:07:00 +00001141 // If no mismatch (only one instance value) continue.
John Thompson94faa4d2013-07-26 23:56:42 +00001142 if (!MacroExpTracker.hasMismatch())
1143 continue;
John Thompson7c6e79f32013-07-29 19:07:00 +00001144 // Tell caller we found one or more errors.
John Thompson94faa4d2013-07-26 23:56:42 +00001145 ReturnValue = true;
John Thompson7c6e79f32013-07-29 19:07:00 +00001146 // Start the error message.
John Thompson94faa4d2013-07-26 23:56:42 +00001147 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";
John Thompson7c6e79f32013-07-29 19:07:00 +00001153 // Walk all the instances.
Piotr Padlewski08124b12016-12-14 15:29:23 +00001154 for (auto IMT = MacroExpTracker.MacroExpansionInstances.begin(),
1155 EMT = MacroExpTracker.MacroExpansionInstances.end();
John Thompson94faa4d2013-07-26 23:56:42 +00001156 IMT != EMT; ++IMT) {
1157 MacroExpansionInstance &MacroInfo = *IMT;
1158 OS << " '" << *MacroExpTracker.MacroUnexpanded << "' expanded to: '"
1159 << *MacroInfo.MacroExpanded
1160 << "' with respect to these inclusion paths:\n";
John Thompson7c6e79f32013-07-29 19:07:00 +00001161 // Walk all the inclusion path hierarchies.
Piotr Padlewski08124b12016-12-14 15:29:23 +00001162 for (auto IIP = MacroInfo.InclusionPathHandles.begin(),
1163 EIP = MacroInfo.InclusionPathHandles.end();
John Thompson94faa4d2013-07-26 23:56:42 +00001164 IIP != EIP; ++IIP) {
1165 const std::vector<HeaderHandle> &ip = getInclusionPath(*IIP);
Piotr Padlewski08124b12016-12-14 15:29:23 +00001166 auto Count = (int)ip.size();
John Thompson94faa4d2013-07-26 23:56:42 +00001167 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.
Alexander Kornienko87638f62015-04-11 07:59:33 +00001192 bool reportInconsistentConditionals(llvm::raw_ostream &OS) override {
John Thompson94faa4d2013-07-26 23:56:42 +00001193 bool ReturnValue = false;
John Thompson7c6e79f32013-07-29 19:07:00 +00001194 // Walk all the conditional trackers in the map.
Piotr Padlewski08124b12016-12-14 15:29:23 +00001195 for (auto I = ConditionalExpansions.begin(),
1196 E = ConditionalExpansions.end();
John Thompson94faa4d2013-07-26 23:56:42 +00001197 I != E; ++I) {
1198 const PPItemKey &ItemKey = I->first;
1199 ConditionalTracker &CondTracker = I->second;
1200 if (!CondTracker.hasMismatch())
1201 continue;
John Thompson7c6e79f32013-07-29 19:07:00 +00001202 // Tell caller we found one or more errors.
John Thompson94faa4d2013-07-26 23:56:42 +00001203 ReturnValue = true;
John Thompson7c6e79f32013-07-29 19:07:00 +00001204 // Start the error message.
John Thompson94faa4d2013-07-26 23:56:42 +00001205 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";
John Thompson7c6e79f32013-07-29 19:07:00 +00001214 // Walk all the instances.
Piotr Padlewski08124b12016-12-14 15:29:23 +00001215 for (auto IMT = CondTracker.ConditionalExpansionInstances.begin(),
1216 EMT = CondTracker.ConditionalExpansionInstances.end();
John Thompson94faa4d2013-07-26 23:56:42 +00001217 IMT != EMT; ++IMT) {
1218 ConditionalExpansionInstance &MacroInfo = *IMT;
1219 OS << " '" << *CondTracker.ConditionUnexpanded << "' expanded to: '"
John Thompson87f9fef2013-12-07 08:41:15 +00001220 << ConditionValueKindStrings[MacroInfo.ConditionValue]
John Thompson94faa4d2013-07-26 23:56:42 +00001221 << "' with respect to these inclusion paths:\n";
John Thompson7c6e79f32013-07-29 19:07:00 +00001222 // Walk all the inclusion path hierarchies.
Piotr Padlewski08124b12016-12-14 15:29:23 +00001223 for (auto IIP = MacroInfo.InclusionPathHandles.begin(),
1224 EIP = MacroInfo.InclusionPathHandles.end();
John Thompson94faa4d2013-07-26 23:56:42 +00001225 IIP != EIP; ++IIP) {
1226 const std::vector<HeaderHandle> &ip = getInclusionPath(*IIP);
Piotr Padlewski08124b12016-12-14 15:29:23 +00001227 auto Count = (int)ip.size();
John Thompson94faa4d2013-07-26 23:56:42 +00001228 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
1255private:
John Thompsonecd3b042015-02-11 16:58:36 +00001256 llvm::SmallVector<std::string, 32> HeaderList;
1257 // Only do extern, namespace check for headers in HeaderList.
1258 bool BlockCheckHeaderListOnly;
John Thompson94faa4d2013-07-26 23:56:42 +00001259 llvm::StringPool Strings;
1260 std::vector<StringHandle> HeaderPaths;
1261 std::vector<HeaderHandle> HeaderStack;
1262 std::vector<HeaderInclusionPath> InclusionPaths;
1263 InclusionPathHandle CurrentInclusionPathHandle;
Matthias Braun48c84262016-02-01 22:18:58 +00001264 llvm::SmallSet<HeaderHandle, 32> HeadersInThisCompile;
John Thompson74083922013-09-18 18:19:43 +00001265 std::vector<PPItemKey> IncludeDirectives;
John Thompson94faa4d2013-07-26 23:56:42 +00001266 MacroExpansionMap MacroExpansions;
1267 ConditionalExpansionMap ConditionalExpansions;
John Thompson48df0962013-08-05 23:55:14 +00001268 bool InNestedHeader;
John Thompson94faa4d2013-07-26 23:56:42 +00001269};
1270
Benjamin Kramere7103712015-03-23 12:49:15 +00001271} // namespace
1272
John Thompson94faa4d2013-07-26 23:56:42 +00001273// PreprocessorTracker functions.
1274
1275// PreprocessorTracker desctructor.
David Blaikiee04a3da2015-10-20 21:45:52 +00001276PreprocessorTracker::~PreprocessorTracker() {}
John Thompson94faa4d2013-07-26 23:56:42 +00001277
1278// Create instance of PreprocessorTracker.
John Thompsonecd3b042015-02-11 16:58:36 +00001279PreprocessorTracker *PreprocessorTracker::create(
1280 llvm::SmallVector<std::string, 32> &Headers,
1281 bool DoBlockCheckHeaderListOnly) {
1282 return new PreprocessorTrackerImpl(Headers, DoBlockCheckHeaderListOnly);
John Thompson94faa4d2013-07-26 23:56:42 +00001283}
1284
1285// Preprocessor callbacks for modularize.
1286
John Thompson74083922013-09-18 18:19:43 +00001287// Handle include directive.
1288void 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,
Julie Hockett546943f2018-05-10 19:13:14 +00001293 const clang::Module *Imported, clang::SrcMgr::CharacteristicKind FileType) {
John Thompson74083922013-09-18 18:19:43 +00001294 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
John Thompson94faa4d2013-07-26 23:56:42 +00001301// Handle file entry/exit.
1302void 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;
John Thompsoncc2e2912013-09-03 18:44:11 +00001309 case ExitFile: {
1310 const clang::FileEntry *F =
John Thompson48df0962013-08-05 23:55:14 +00001311 PP.getSourceManager().getFileEntryForID(PrevFID);
Craig Topperf61be9c2014-06-09 02:03:06 +00001312 if (F)
John Thompsoncc2e2912013-09-03 18:44:11 +00001313 PPTracker.handleHeaderExit(F->getName());
1314 } break;
John Thompson94faa4d2013-07-26 23:56:42 +00001315 case SystemHeaderPragma:
John Thompson94faa4d2013-07-26 23:56:42 +00001316 case RenameFile:
Benjamin Kramerf2576812013-07-27 15:57:46 +00001317 break;
John Thompson94faa4d2013-07-26 23:56:42 +00001318 }
1319}
1320
1321// Handle macro expansion.
1322void PreprocessorCallbacks::MacroExpands(const clang::Token &MacroNameTok,
Richard Smith33de8562015-05-04 03:15:55 +00001323 const clang::MacroDefinition &MD,
John Thompson94faa4d2013-07-26 23:56:42 +00001324 clang::SourceRange Range,
1325 const clang::MacroArgs *Args) {
1326 clang::SourceLocation Loc = Range.getBegin();
John Thompson91555bd2013-08-09 00:22:20 +00001327 // Ignore macro argument expansions.
1328 if (!Loc.isFileID())
1329 return;
John Thompson94faa4d2013-07-26 23:56:42 +00001330 clang::IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
Richard Smith33de8562015-05-04 03:15:55 +00001331 const clang::MacroInfo *MI = MD.getMacroInfo();
John Thompson94faa4d2013-07-26 23:56:42 +00001332 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
1340void PreprocessorCallbacks::Defined(const clang::Token &MacroNameTok,
Richard Smith33de8562015-05-04 03:15:55 +00001341 const clang::MacroDefinition &MD,
John Thompson94faa4d2013-07-26 23:56:42 +00001342 clang::SourceRange Range) {
1343 clang::SourceLocation Loc(Range.getBegin());
1344 clang::IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
Richard Smith33de8562015-05-04 03:15:55 +00001345 const clang::MacroInfo *MI = MD.getMacroInfo();
John Thompson94faa4d2013-07-26 23:56:42 +00001346 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
1354void PreprocessorCallbacks::If(clang::SourceLocation Loc,
1355 clang::SourceRange ConditionRange,
John Thompson87f9fef2013-12-07 08:41:15 +00001356 clang::PPCallbacks::ConditionValueKind ConditionResult) {
John Thompson94faa4d2013-07-26 23:56:42 +00001357 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
1363void PreprocessorCallbacks::Elif(clang::SourceLocation Loc,
1364 clang::SourceRange ConditionRange,
John Thompson87f9fef2013-12-07 08:41:15 +00001365 clang::PPCallbacks::ConditionValueKind ConditionResult,
John Thompson94faa4d2013-07-26 23:56:42 +00001366 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
1373void PreprocessorCallbacks::Ifdef(clang::SourceLocation Loc,
1374 const clang::Token &MacroNameTok,
Richard Smith33de8562015-05-04 03:15:55 +00001375 const clang::MacroDefinition &MD) {
John Thompson87f9fef2013-12-07 08:41:15 +00001376 clang::PPCallbacks::ConditionValueKind IsDefined =
Craig Topperf61be9c2014-06-09 02:03:06 +00001377 (MD ? clang::PPCallbacks::CVK_True : clang::PPCallbacks::CVK_False );
John Thompson94faa4d2013-07-26 23:56:42 +00001378 PPTracker.addConditionalExpansionInstance(
1379 PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_ifdef,
1380 IsDefined, PP.getSpelling(MacroNameTok),
1381 PPTracker.getCurrentInclusionPathHandle());
1382}
1383
1384void PreprocessorCallbacks::Ifndef(clang::SourceLocation Loc,
1385 const clang::Token &MacroNameTok,
Richard Smith33de8562015-05-04 03:15:55 +00001386 const clang::MacroDefinition &MD) {
John Thompson87f9fef2013-12-07 08:41:15 +00001387 clang::PPCallbacks::ConditionValueKind IsNotDefined =
Craig Topperf61be9c2014-06-09 02:03:06 +00001388 (!MD ? clang::PPCallbacks::CVK_True : clang::PPCallbacks::CVK_False );
John Thompson94faa4d2013-07-26 23:56:42 +00001389 PPTracker.addConditionalExpansionInstance(
1390 PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_ifndef,
1391 IsNotDefined, PP.getSpelling(MacroNameTok),
1392 PPTracker.getCurrentInclusionPathHandle());
1393}
1394} // end namespace Modularize