blob: 0b761466b3fadb554d181022724627a24915b76d [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
258// Forwards.
259class PreprocessorTrackerImpl;
260
261// Some handle types
262typedef llvm::PooledStringPtr StringHandle;
263
264typedef int HeaderHandle;
265const HeaderHandle HeaderHandleInvalid = -1;
266
267typedef int InclusionPathHandle;
268const InclusionPathHandle InclusionPathHandleInvalid = -1;
269
270// Some utility functions.
271
272// Get a "file:line:column" source location string.
273static std::string getSourceLocationString(clang::Preprocessor &PP,
274 clang::SourceLocation Loc) {
275 if (Loc.isInvalid())
276 return std::string("(none)");
277 else
278 return Loc.printToString(PP.getSourceManager());
279}
280
281// Get just the file name from a source location.
282static std::string getSourceLocationFile(clang::Preprocessor &PP,
283 clang::SourceLocation Loc) {
284 std::string Source(getSourceLocationString(PP, Loc));
285 size_t Offset = Source.find(':', 2);
286 if (Offset == std::string::npos)
287 return Source;
288 return Source.substr(0, Offset);
289}
290
291// Get just the line and column from a source location.
292static void getSourceLocationLineAndColumn(clang::Preprocessor &PP,
293 clang::SourceLocation Loc, int &Line,
294 int &Column) {
295 clang::PresumedLoc PLoc = PP.getSourceManager().getPresumedLoc(Loc);
296 if (PLoc.isInvalid()) {
297 Line = 0;
298 Column = 0;
299 return;
300 }
301 Line = PLoc.getLine();
302 Column = PLoc.getColumn();
303}
304
305// Retrieve source snippet from file image.
306std::string getSourceString(clang::Preprocessor &PP, clang::SourceRange Range) {
307 clang::SourceLocation BeginLoc = Range.getBegin();
308 clang::SourceLocation EndLoc = Range.getEnd();
309 const char *BeginPtr = PP.getSourceManager().getCharacterData(BeginLoc);
310 const char *EndPtr = PP.getSourceManager().getCharacterData(EndLoc);
311 size_t Length = EndPtr - BeginPtr;
312 return llvm::StringRef(BeginPtr, Length).trim().str();
313}
314
John Thompson74083922013-09-18 18:19:43 +0000315// Retrieve source line from file image given a location.
John Thompson94faa4d2013-07-26 23:56:42 +0000316std::string getSourceLine(clang::Preprocessor &PP, clang::SourceLocation Loc) {
317 const llvm::MemoryBuffer *MemBuffer =
318 PP.getSourceManager().getBuffer(PP.getSourceManager().getFileID(Loc));
319 const char *Buffer = MemBuffer->getBufferStart();
320 const char *BufferEnd = MemBuffer->getBufferEnd();
321 const char *BeginPtr = PP.getSourceManager().getCharacterData(Loc);
322 const char *EndPtr = BeginPtr;
323 while (BeginPtr > Buffer) {
324 if (*BeginPtr == '\n') {
325 BeginPtr++;
326 break;
327 }
328 BeginPtr--;
329 }
330 while (EndPtr < BufferEnd) {
331 if (*EndPtr == '\n') {
332 break;
333 }
334 EndPtr++;
335 }
336 size_t Length = EndPtr - BeginPtr;
337 return llvm::StringRef(BeginPtr, Length).str();
338}
339
John Thompson74083922013-09-18 18:19:43 +0000340// Retrieve source line from file image given a file ID and line number.
341std::string getSourceLine(clang::Preprocessor &PP, clang::FileID FileID,
342 int Line) {
343 const llvm::MemoryBuffer *MemBuffer = PP.getSourceManager().getBuffer(FileID);
344 const char *Buffer = MemBuffer->getBufferStart();
345 const char *BufferEnd = MemBuffer->getBufferEnd();
346 const char *BeginPtr = Buffer;
347 const char *EndPtr = BufferEnd;
348 int LineCounter = 1;
349 if (Line == 1)
350 BeginPtr = Buffer;
351 else {
352 while (Buffer < BufferEnd) {
353 if (*Buffer == '\n') {
354 if (++LineCounter == Line) {
355 BeginPtr = Buffer++ + 1;
356 break;
357 }
358 }
359 Buffer++;
360 }
361 }
362 while (Buffer < BufferEnd) {
363 if (*Buffer == '\n') {
364 EndPtr = Buffer;
365 break;
366 }
367 Buffer++;
368 }
369 size_t Length = EndPtr - BeginPtr;
370 return llvm::StringRef(BeginPtr, Length).str();
371}
372
John Thompson94faa4d2013-07-26 23:56:42 +0000373// Get the string for the Unexpanded macro instance.
374// The soureRange is expected to end at the last token
375// for the macro instance, which in the case of a function-style
376// macro will be a ')', but for an object-style macro, it
377// will be the macro name itself.
378std::string getMacroUnexpandedString(clang::SourceRange Range,
379 clang::Preprocessor &PP,
380 llvm::StringRef MacroName,
381 const clang::MacroInfo *MI) {
382 clang::SourceLocation BeginLoc(Range.getBegin());
383 const char *BeginPtr = PP.getSourceManager().getCharacterData(BeginLoc);
384 size_t Length;
385 std::string Unexpanded;
386 if (MI->isFunctionLike()) {
387 clang::SourceLocation EndLoc(Range.getEnd());
388 const char *EndPtr = PP.getSourceManager().getCharacterData(EndLoc) + 1;
389 Length = (EndPtr - BeginPtr) + 1; // +1 is ')' width.
390 } else
391 Length = MacroName.size();
392 return llvm::StringRef(BeginPtr, Length).trim().str();
393}
394
395// Get the expansion for a macro instance, given the information
396// provided by PPCallbacks.
John Thompson91555bd2013-08-09 00:22:20 +0000397// FIXME: This doesn't support function-style macro instances
398// passed as arguments to another function-style macro. However,
399// since it still expands the inner arguments, it still
400// allows modularize to effectively work with respect to macro
401// consistency checking, although it displays the incorrect
402// expansion in error messages.
John Thompson94faa4d2013-07-26 23:56:42 +0000403std::string getMacroExpandedString(clang::Preprocessor &PP,
404 llvm::StringRef MacroName,
405 const clang::MacroInfo *MI,
406 const clang::MacroArgs *Args) {
407 std::string Expanded;
408 // Walk over the macro Tokens.
409 typedef clang::MacroInfo::tokens_iterator Iter;
410 for (Iter I = MI->tokens_begin(), E = MI->tokens_end(); I != E; ++I) {
411 clang::IdentifierInfo *II = I->getIdentifierInfo();
412 int ArgNo = (II && Args ? MI->getArgumentNum(II) : -1);
413 if (ArgNo == -1) {
414 // This isn't an argument, just add it.
Craig Topperf61be9c2014-06-09 02:03:06 +0000415 if (II == nullptr)
John Thompson94faa4d2013-07-26 23:56:42 +0000416 Expanded += PP.getSpelling((*I)); // Not an identifier.
417 else {
418 // Token is for an identifier.
419 std::string Name = II->getName().str();
420 // Check for nexted macro references.
421 clang::MacroInfo *MacroInfo = PP.getMacroInfo(II);
Craig Topperf61be9c2014-06-09 02:03:06 +0000422 if (MacroInfo)
423 Expanded += getMacroExpandedString(PP, Name, MacroInfo, nullptr);
John Thompson94faa4d2013-07-26 23:56:42 +0000424 else
425 Expanded += Name;
426 }
427 continue;
428 }
429 // We get here if it's a function-style macro with arguments.
430 const clang::Token *ResultArgToks;
431 const clang::Token *ArgTok = Args->getUnexpArgument(ArgNo);
432 if (Args->ArgNeedsPreexpansion(ArgTok, PP))
433 ResultArgToks = &(const_cast<clang::MacroArgs *>(Args))
434 ->getPreExpArgument(ArgNo, MI, PP)[0];
435 else
436 ResultArgToks = ArgTok; // Use non-preexpanded Tokens.
437 // If the arg token didn't expand into anything, ignore it.
438 if (ResultArgToks->is(clang::tok::eof))
439 continue;
440 unsigned NumToks = clang::MacroArgs::getArgLength(ResultArgToks);
441 // Append the resulting argument expansions.
442 for (unsigned ArgumentIndex = 0; ArgumentIndex < NumToks; ++ArgumentIndex) {
443 const clang::Token &AT = ResultArgToks[ArgumentIndex];
444 clang::IdentifierInfo *II = AT.getIdentifierInfo();
Craig Topperf61be9c2014-06-09 02:03:06 +0000445 if (II == nullptr)
John Thompson94faa4d2013-07-26 23:56:42 +0000446 Expanded += PP.getSpelling(AT); // Not an identifier.
447 else {
448 // It's an identifier. Check for further expansion.
449 std::string Name = II->getName().str();
450 clang::MacroInfo *MacroInfo = PP.getMacroInfo(II);
Craig Topperf61be9c2014-06-09 02:03:06 +0000451 if (MacroInfo)
452 Expanded += getMacroExpandedString(PP, Name, MacroInfo, nullptr);
John Thompson94faa4d2013-07-26 23:56:42 +0000453 else
454 Expanded += Name;
455 }
456 }
457 }
458 return Expanded;
459}
460
461// Get the string representing a vector of Tokens.
462std::string
463getTokensSpellingString(clang::Preprocessor &PP,
464 llvm::SmallVectorImpl<clang::Token> &Tokens) {
465 std::string Expanded;
466 // Walk over the macro Tokens.
467 typedef llvm::SmallVectorImpl<clang::Token>::iterator Iter;
468 for (Iter I = Tokens.begin(), E = Tokens.end(); I != E; ++I)
469 Expanded += PP.getSpelling(*I); // Not an identifier.
470 return llvm::StringRef(Expanded).trim().str();
471}
472
473// Get the expansion for a macro instance, given the information
474// provided by PPCallbacks.
475std::string getExpandedString(clang::Preprocessor &PP,
476 llvm::StringRef MacroName,
477 const clang::MacroInfo *MI,
478 const clang::MacroArgs *Args) {
479 std::string Expanded;
480 // Walk over the macro Tokens.
481 typedef clang::MacroInfo::tokens_iterator Iter;
482 for (Iter I = MI->tokens_begin(), E = MI->tokens_end(); I != E; ++I) {
483 clang::IdentifierInfo *II = I->getIdentifierInfo();
484 int ArgNo = (II && Args ? MI->getArgumentNum(II) : -1);
485 if (ArgNo == -1) {
486 // This isn't an argument, just add it.
Craig Topperf61be9c2014-06-09 02:03:06 +0000487 if (II == nullptr)
John Thompson94faa4d2013-07-26 23:56:42 +0000488 Expanded += PP.getSpelling((*I)); // Not an identifier.
489 else {
490 // Token is for an identifier.
491 std::string Name = II->getName().str();
492 // Check for nexted macro references.
493 clang::MacroInfo *MacroInfo = PP.getMacroInfo(II);
Craig Topperf61be9c2014-06-09 02:03:06 +0000494 if (MacroInfo)
495 Expanded += getMacroExpandedString(PP, Name, MacroInfo, nullptr);
John Thompson94faa4d2013-07-26 23:56:42 +0000496 else
497 Expanded += Name;
498 }
499 continue;
500 }
501 // We get here if it's a function-style macro with arguments.
502 const clang::Token *ResultArgToks;
503 const clang::Token *ArgTok = Args->getUnexpArgument(ArgNo);
504 if (Args->ArgNeedsPreexpansion(ArgTok, PP))
505 ResultArgToks = &(const_cast<clang::MacroArgs *>(Args))
506 ->getPreExpArgument(ArgNo, MI, PP)[0];
507 else
508 ResultArgToks = ArgTok; // Use non-preexpanded Tokens.
509 // If the arg token didn't expand into anything, ignore it.
510 if (ResultArgToks->is(clang::tok::eof))
511 continue;
512 unsigned NumToks = clang::MacroArgs::getArgLength(ResultArgToks);
513 // Append the resulting argument expansions.
514 for (unsigned ArgumentIndex = 0; ArgumentIndex < NumToks; ++ArgumentIndex) {
515 const clang::Token &AT = ResultArgToks[ArgumentIndex];
516 clang::IdentifierInfo *II = AT.getIdentifierInfo();
Craig Topperf61be9c2014-06-09 02:03:06 +0000517 if (II == nullptr)
John Thompson94faa4d2013-07-26 23:56:42 +0000518 Expanded += PP.getSpelling(AT); // Not an identifier.
519 else {
520 // It's an identifier. Check for further expansion.
521 std::string Name = II->getName().str();
522 clang::MacroInfo *MacroInfo = PP.getMacroInfo(II);
Craig Topperf61be9c2014-06-09 02:03:06 +0000523 if (MacroInfo)
524 Expanded += getMacroExpandedString(PP, Name, MacroInfo, nullptr);
John Thompson94faa4d2013-07-26 23:56:42 +0000525 else
526 Expanded += Name;
527 }
528 }
529 }
530 return Expanded;
531}
532
John Thompson87f9fef2013-12-07 08:41:15 +0000533// ConditionValueKind strings.
534const char *
535ConditionValueKindStrings[] = {
536 "(not evaluated)", "false", "true"
537};
538
John Thompson94faa4d2013-07-26 23:56:42 +0000539bool operator<(const StringHandle &H1, const StringHandle &H2) {
540 const char *S1 = (H1 ? *H1 : "");
541 const char *S2 = (H2 ? *H2 : "");
542 int Diff = strcmp(S1, S2);
543 return Diff < 0;
544}
545bool operator>(const StringHandle &H1, const StringHandle &H2) {
546 const char *S1 = (H1 ? *H1 : "");
547 const char *S2 = (H2 ? *H2 : "");
548 int Diff = strcmp(S1, S2);
549 return Diff > 0;
550}
551
552// Preprocessor item key.
553//
554// This class represents a location in a source file, for use
555// as a key representing a unique name/file/line/column quadruplet,
556// which in this case is used to identify a macro expansion instance,
557// but could be used for other things as well.
558// The file is a header file handle, the line is a line number,
559// and the column is a column number.
560class PPItemKey {
561public:
562 PPItemKey(clang::Preprocessor &PP, StringHandle Name, HeaderHandle File,
563 clang::SourceLocation Loc)
564 : Name(Name), File(File) {
565 getSourceLocationLineAndColumn(PP, Loc, Line, Column);
566 }
567 PPItemKey(StringHandle Name, HeaderHandle File, int Line, int Column)
568 : Name(Name), File(File), Line(Line), Column(Column) {}
569 PPItemKey(const PPItemKey &Other)
570 : Name(Other.Name), File(Other.File), Line(Other.Line),
571 Column(Other.Column) {}
572 PPItemKey() : File(HeaderHandleInvalid), Line(0), Column(0) {}
573 bool operator==(const PPItemKey &Other) const {
574 if (Name != Other.Name)
575 return false;
576 if (File != Other.File)
577 return false;
578 if (Line != Other.Line)
579 return false;
580 return Column == Other.Column;
581 }
582 bool operator<(const PPItemKey &Other) const {
583 if (Name < Other.Name)
584 return true;
585 else if (Name > Other.Name)
586 return false;
587 if (File < Other.File)
588 return true;
589 else if (File > Other.File)
590 return false;
591 if (Line < Other.Line)
592 return true;
593 else if (Line > Other.Line)
594 return false;
595 return Column < Other.Column;
596 }
597 StringHandle Name;
598 HeaderHandle File;
599 int Line;
600 int Column;
601};
602
603// Header inclusion path.
604class HeaderInclusionPath {
605public:
606 HeaderInclusionPath(std::vector<HeaderHandle> HeaderInclusionPath)
607 : Path(HeaderInclusionPath) {}
608 HeaderInclusionPath(const HeaderInclusionPath &Other) : Path(Other.Path) {}
609 HeaderInclusionPath() {}
610 std::vector<HeaderHandle> Path;
611};
612
613// Macro expansion instance.
614//
615// This class represents an instance of a macro expansion with a
616// unique value. It also stores the unique header inclusion paths
John Thompson7c6e79f32013-07-29 19:07:00 +0000617// for use in telling the user the nested include path to the header.
John Thompson94faa4d2013-07-26 23:56:42 +0000618class MacroExpansionInstance {
619public:
620 MacroExpansionInstance(StringHandle MacroExpanded,
621 PPItemKey &DefinitionLocation,
622 StringHandle DefinitionSourceLine,
623 InclusionPathHandle H)
624 : MacroExpanded(MacroExpanded), DefinitionLocation(DefinitionLocation),
625 DefinitionSourceLine(DefinitionSourceLine) {
626 InclusionPathHandles.push_back(H);
627 }
628 MacroExpansionInstance() {}
629
630 // Check for the presence of a header inclusion path handle entry.
631 // Return false if not found.
632 bool haveInclusionPathHandle(InclusionPathHandle H) {
633 for (std::vector<InclusionPathHandle>::iterator
634 I = InclusionPathHandles.begin(),
635 E = InclusionPathHandles.end();
636 I != E; ++I) {
637 if (*I == H)
638 return true;
639 }
640 return InclusionPathHandleInvalid;
641 }
642 // Add a new header inclusion path entry, if not already present.
643 void addInclusionPathHandle(InclusionPathHandle H) {
644 if (!haveInclusionPathHandle(H))
645 InclusionPathHandles.push_back(H);
646 }
647
648 // A string representing the macro instance after preprocessing.
649 StringHandle MacroExpanded;
650 // A file/line/column triplet representing the macro definition location.
651 PPItemKey DefinitionLocation;
652 // A place to save the macro definition line string.
653 StringHandle DefinitionSourceLine;
654 // The header inclusion path handles for all the instances.
655 std::vector<InclusionPathHandle> InclusionPathHandles;
656};
657
658// Macro expansion instance tracker.
659//
660// This class represents one macro expansion, keyed by a PPItemKey.
661// It stores a string representing the macro reference in the source,
662// and a list of ConditionalExpansionInstances objects representing
John Thompson7c6e79f32013-07-29 19:07:00 +0000663// the unique values the condition expands to in instances of the header.
John Thompson94faa4d2013-07-26 23:56:42 +0000664class MacroExpansionTracker {
665public:
666 MacroExpansionTracker(StringHandle MacroUnexpanded,
667 StringHandle MacroExpanded,
668 StringHandle InstanceSourceLine,
669 PPItemKey &DefinitionLocation,
670 StringHandle DefinitionSourceLine,
671 InclusionPathHandle InclusionPathHandle)
672 : MacroUnexpanded(MacroUnexpanded),
673 InstanceSourceLine(InstanceSourceLine) {
674 addMacroExpansionInstance(MacroExpanded, DefinitionLocation,
675 DefinitionSourceLine, InclusionPathHandle);
676 }
677 MacroExpansionTracker() {}
678
679 // Find a matching macro expansion instance.
680 MacroExpansionInstance *
681 findMacroExpansionInstance(StringHandle MacroExpanded,
682 PPItemKey &DefinitionLocation) {
683 for (std::vector<MacroExpansionInstance>::iterator
684 I = MacroExpansionInstances.begin(),
685 E = MacroExpansionInstances.end();
686 I != E; ++I) {
687 if ((I->MacroExpanded == MacroExpanded) &&
688 (I->DefinitionLocation == DefinitionLocation)) {
689 return &*I; // Found.
690 }
691 }
Craig Topperf61be9c2014-06-09 02:03:06 +0000692 return nullptr; // Not found.
John Thompson94faa4d2013-07-26 23:56:42 +0000693 }
694
695 // Add a macro expansion instance.
696 void addMacroExpansionInstance(StringHandle MacroExpanded,
697 PPItemKey &DefinitionLocation,
698 StringHandle DefinitionSourceLine,
699 InclusionPathHandle InclusionPathHandle) {
700 MacroExpansionInstances.push_back(
701 MacroExpansionInstance(MacroExpanded, DefinitionLocation,
702 DefinitionSourceLine, InclusionPathHandle));
703 }
704
705 // Return true if there is a mismatch.
706 bool hasMismatch() { return MacroExpansionInstances.size() > 1; }
707
708 // A string representing the macro instance without expansion.
709 StringHandle MacroUnexpanded;
710 // A place to save the macro instance source line string.
711 StringHandle InstanceSourceLine;
712 // The macro expansion instances.
713 // If all instances of the macro expansion expand to the same value,
714 // This vector will only have one instance.
715 std::vector<MacroExpansionInstance> MacroExpansionInstances;
716};
717
718// Conditional expansion instance.
719//
John Thompson7c6e79f32013-07-29 19:07:00 +0000720// This class represents an instance of a condition exoression result
721// with a unique value. It also stores the unique header inclusion paths
722// for use in telling the user the nested include path to the header.
John Thompson94faa4d2013-07-26 23:56:42 +0000723class ConditionalExpansionInstance {
724public:
John Thompson87f9fef2013-12-07 08:41:15 +0000725 ConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind ConditionValue, InclusionPathHandle H)
John Thompson94faa4d2013-07-26 23:56:42 +0000726 : ConditionValue(ConditionValue) {
727 InclusionPathHandles.push_back(H);
728 }
729 ConditionalExpansionInstance() {}
730
731 // Check for the presence of a header inclusion path handle entry.
732 // Return false if not found.
733 bool haveInclusionPathHandle(InclusionPathHandle H) {
734 for (std::vector<InclusionPathHandle>::iterator
735 I = InclusionPathHandles.begin(),
736 E = InclusionPathHandles.end();
737 I != E; ++I) {
738 if (*I == H)
739 return true;
740 }
741 return InclusionPathHandleInvalid;
742 }
743 // Add a new header inclusion path entry, if not already present.
744 void addInclusionPathHandle(InclusionPathHandle H) {
745 if (!haveInclusionPathHandle(H))
746 InclusionPathHandles.push_back(H);
747 }
748
749 // A flag representing the evaluated condition value.
John Thompson87f9fef2013-12-07 08:41:15 +0000750 clang::PPCallbacks::ConditionValueKind ConditionValue;
John Thompson94faa4d2013-07-26 23:56:42 +0000751 // The header inclusion path handles for all the instances.
752 std::vector<InclusionPathHandle> InclusionPathHandles;
753};
754
755// Conditional directive instance tracker.
756//
757// This class represents one conditional directive, keyed by a PPItemKey.
758// It stores a string representing the macro reference in the source,
John Thompson7c6e79f32013-07-29 19:07:00 +0000759// and a list of ConditionExpansionInstance objects representing
760// the unique value the condition expression expands to in instances of
761// the header.
John Thompson94faa4d2013-07-26 23:56:42 +0000762class ConditionalTracker {
763public:
764 ConditionalTracker(clang::tok::PPKeywordKind DirectiveKind,
John Thompson87f9fef2013-12-07 08:41:15 +0000765 clang::PPCallbacks::ConditionValueKind ConditionValue,
766 StringHandle ConditionUnexpanded,
John Thompson94faa4d2013-07-26 23:56:42 +0000767 InclusionPathHandle InclusionPathHandle)
768 : DirectiveKind(DirectiveKind), ConditionUnexpanded(ConditionUnexpanded) {
769 addConditionalExpansionInstance(ConditionValue, InclusionPathHandle);
770 }
771 ConditionalTracker() {}
772
773 // Find a matching condition expansion instance.
774 ConditionalExpansionInstance *
John Thompson87f9fef2013-12-07 08:41:15 +0000775 findConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind ConditionValue) {
John Thompson94faa4d2013-07-26 23:56:42 +0000776 for (std::vector<ConditionalExpansionInstance>::iterator
777 I = ConditionalExpansionInstances.begin(),
778 E = ConditionalExpansionInstances.end();
779 I != E; ++I) {
780 if (I->ConditionValue == ConditionValue) {
781 return &*I; // Found.
782 }
783 }
Craig Topperf61be9c2014-06-09 02:03:06 +0000784 return nullptr; // Not found.
John Thompson94faa4d2013-07-26 23:56:42 +0000785 }
786
787 // Add a conditional expansion instance.
788 void
John Thompson87f9fef2013-12-07 08:41:15 +0000789 addConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind ConditionValue,
John Thompson94faa4d2013-07-26 23:56:42 +0000790 InclusionPathHandle InclusionPathHandle) {
791 ConditionalExpansionInstances.push_back(
792 ConditionalExpansionInstance(ConditionValue, InclusionPathHandle));
793 }
794
795 // Return true if there is a mismatch.
796 bool hasMismatch() { return ConditionalExpansionInstances.size() > 1; }
797
798 // The kind of directive.
799 clang::tok::PPKeywordKind DirectiveKind;
800 // A string representing the macro instance without expansion.
801 StringHandle ConditionUnexpanded;
802 // The condition expansion instances.
803 // If all instances of the conditional expression expand to the same value,
804 // This vector will only have one instance.
805 std::vector<ConditionalExpansionInstance> ConditionalExpansionInstances;
806};
807
808// Preprocessor callbacks for modularize.
809//
810// This class derives from the Clang PPCallbacks class to track preprocessor
811// actions, such as changing files and handling preprocessor directives and
812// macro expansions. It has to figure out when a new header file is entered
813// and left, as the provided handler is not particularly clear about it.
814class PreprocessorCallbacks : public clang::PPCallbacks {
815public:
816 PreprocessorCallbacks(PreprocessorTrackerImpl &ppTracker,
817 clang::Preprocessor &PP, llvm::StringRef rootHeaderFile)
818 : PPTracker(ppTracker), PP(PP), RootHeaderFile(rootHeaderFile) {}
819 ~PreprocessorCallbacks() {}
820
821 // Overridden handlers.
John Thompson74083922013-09-18 18:19:43 +0000822 void InclusionDirective(clang::SourceLocation HashLoc,
823 const clang::Token &IncludeTok,
824 llvm::StringRef FileName, bool IsAngled,
825 clang::CharSourceRange FilenameRange,
826 const clang::FileEntry *File,
827 llvm::StringRef SearchPath,
828 llvm::StringRef RelativePath,
829 const clang::Module *Imported);
John Thompson94faa4d2013-07-26 23:56:42 +0000830 void FileChanged(clang::SourceLocation Loc,
831 clang::PPCallbacks::FileChangeReason Reason,
832 clang::SrcMgr::CharacteristicKind FileType,
833 clang::FileID PrevFID = clang::FileID());
834 void MacroExpands(const clang::Token &MacroNameTok,
835 const clang::MacroDirective *MD, clang::SourceRange Range,
836 const clang::MacroArgs *Args);
837 void Defined(const clang::Token &MacroNameTok,
838 const clang::MacroDirective *MD, clang::SourceRange Range);
839 void If(clang::SourceLocation Loc, clang::SourceRange ConditionRange,
John Thompson87f9fef2013-12-07 08:41:15 +0000840 clang::PPCallbacks::ConditionValueKind ConditionResult);
John Thompson94faa4d2013-07-26 23:56:42 +0000841 void Elif(clang::SourceLocation Loc, clang::SourceRange ConditionRange,
John Thompson87f9fef2013-12-07 08:41:15 +0000842 clang::PPCallbacks::ConditionValueKind ConditionResult, clang::SourceLocation IfLoc);
John Thompson94faa4d2013-07-26 23:56:42 +0000843 void Ifdef(clang::SourceLocation Loc, const clang::Token &MacroNameTok,
844 const clang::MacroDirective *MD);
845 void Ifndef(clang::SourceLocation Loc, const clang::Token &MacroNameTok,
846 const clang::MacroDirective *MD);
847
848private:
849 PreprocessorTrackerImpl &PPTracker;
850 clang::Preprocessor &PP;
851 std::string RootHeaderFile;
852};
853
854// Preprocessor macro expansion item map types.
855typedef std::map<PPItemKey, MacroExpansionTracker> MacroExpansionMap;
856typedef std::map<PPItemKey, MacroExpansionTracker>::iterator
857MacroExpansionMapIter;
858
859// Preprocessor conditional expansion item map types.
860typedef std::map<PPItemKey, ConditionalTracker> ConditionalExpansionMap;
861typedef std::map<PPItemKey, ConditionalTracker>::iterator
862ConditionalExpansionMapIter;
863
864// Preprocessor tracker for modularize.
865//
866// This class stores information about all the headers processed in the
867// course of running modularize.
868class PreprocessorTrackerImpl : public PreprocessorTracker {
869public:
John Thompsonecd3b042015-02-11 16:58:36 +0000870 PreprocessorTrackerImpl(llvm::SmallVector<std::string, 32> &Headers,
871 bool DoBlockCheckHeaderListOnly)
872 : BlockCheckHeaderListOnly(DoBlockCheckHeaderListOnly),
873 CurrentInclusionPathHandle(InclusionPathHandleInvalid),
874 InNestedHeader(false) {
875 // Use canonical header path representation.
876 for (llvm::ArrayRef<std::string>::iterator I = Headers.begin(),
877 E = Headers.end();
878 I != E; ++I) {
879 HeaderList.push_back(getCanonicalPath(*I));
880 }
881 }
882
John Thompson94faa4d2013-07-26 23:56:42 +0000883 ~PreprocessorTrackerImpl() {}
884
885 // Handle entering a preprocessing session.
886 void handlePreprocessorEntry(clang::Preprocessor &PP,
887 llvm::StringRef rootHeaderFile) {
John Thompson4ed963a2013-08-07 18:49:47 +0000888 HeadersInThisCompile.clear();
John Thompson94faa4d2013-07-26 23:56:42 +0000889 assert((HeaderStack.size() == 0) && "Header stack should be empty.");
890 pushHeaderHandle(addHeader(rootHeaderFile));
Craig Topper775862a2014-09-10 05:07:57 +0000891 PP.addPPCallbacks(llvm::make_unique<PreprocessorCallbacks>(*this, PP,
892 rootHeaderFile));
John Thompson94faa4d2013-07-26 23:56:42 +0000893 }
894 // Handle exiting a preprocessing session.
895 void handlePreprocessorExit() { HeaderStack.clear(); }
896
John Thompson74083922013-09-18 18:19:43 +0000897 // Handle include directive.
898 // This function is called every time an include directive is seen by the
899 // preprocessor, for the purpose of later checking for 'extern "" {}' or
900 // "namespace {}" blocks containing #include directives.
901 void handleIncludeDirective(llvm::StringRef DirectivePath, int DirectiveLine,
902 int DirectiveColumn, llvm::StringRef TargetPath) {
John Thompsonecd3b042015-02-11 16:58:36 +0000903 // If it's not a header in the header list, ignore it with respect to
904 // the check.
John Thompson9ea81b02015-02-13 23:32:08 +0000905 if (BlockCheckHeaderListOnly && !isHeaderListHeader(TargetPath))
John Thompsonecd3b042015-02-11 16:58:36 +0000906 return;
John Thompson74083922013-09-18 18:19:43 +0000907 HeaderHandle CurrentHeaderHandle = findHeaderHandle(DirectivePath);
908 StringHandle IncludeHeaderHandle = addString(TargetPath);
909 for (std::vector<PPItemKey>::const_iterator I = IncludeDirectives.begin(),
910 E = IncludeDirectives.end();
911 I != E; ++I) {
912 // If we already have an entry for this directive, return now.
913 if ((I->File == CurrentHeaderHandle) && (I->Line == DirectiveLine))
914 return;
915 }
916 PPItemKey IncludeDirectiveItem(IncludeHeaderHandle, CurrentHeaderHandle,
917 DirectiveLine, DirectiveColumn);
918 IncludeDirectives.push_back(IncludeDirectiveItem);
919 }
920
921 // Check for include directives within the given source line range.
922 // Report errors if any found. Returns true if no include directives
923 // found in block.
924 bool checkForIncludesInBlock(clang::Preprocessor &PP,
925 clang::SourceRange BlockSourceRange,
926 const char *BlockIdentifierMessage,
927 llvm::raw_ostream &OS) {
928 clang::SourceLocation BlockStartLoc = BlockSourceRange.getBegin();
929 clang::SourceLocation BlockEndLoc = BlockSourceRange.getEnd();
930 // Use block location to get FileID of both the include directive
931 // and block statement.
932 clang::FileID FileID = PP.getSourceManager().getFileID(BlockStartLoc);
933 std::string SourcePath = getSourceLocationFile(PP, BlockStartLoc);
John Thompsonb70ecf62015-02-26 19:31:10 +0000934 SourcePath = ModularizeUtilities::getCanonicalPath(SourcePath);
John Thompson74083922013-09-18 18:19:43 +0000935 HeaderHandle SourceHandle = findHeaderHandle(SourcePath);
John Thompsonb87fd7d2015-02-18 16:12:26 +0000936 if (SourceHandle == -1)
937 return true;
John Thompson74083922013-09-18 18:19:43 +0000938 int BlockStartLine, BlockStartColumn, BlockEndLine, BlockEndColumn;
939 bool returnValue = true;
940 getSourceLocationLineAndColumn(PP, BlockStartLoc, BlockStartLine,
941 BlockStartColumn);
942 getSourceLocationLineAndColumn(PP, BlockEndLoc, BlockEndLine,
943 BlockEndColumn);
944 for (std::vector<PPItemKey>::const_iterator I = IncludeDirectives.begin(),
945 E = IncludeDirectives.end();
946 I != E; ++I) {
947 // If we find an entry within the block, report an error.
948 if ((I->File == SourceHandle) && (I->Line >= BlockStartLine) &&
949 (I->Line < BlockEndLine)) {
950 returnValue = false;
John Thompsona2b66872013-09-20 14:44:20 +0000951 OS << SourcePath << ":" << I->Line << ":" << I->Column << ":\n";
John Thompson74083922013-09-18 18:19:43 +0000952 OS << getSourceLine(PP, FileID, I->Line) << "\n";
953 if (I->Column > 0)
954 OS << std::string(I->Column - 1, ' ') << "^\n";
955 OS << "error: Include directive within " << BlockIdentifierMessage
956 << ".\n";
957 OS << SourcePath << ":" << BlockStartLine << ":" << BlockStartColumn
John Thompsona2b66872013-09-20 14:44:20 +0000958 << ":\n";
John Thompson74083922013-09-18 18:19:43 +0000959 OS << getSourceLine(PP, BlockStartLoc) << "\n";
960 if (BlockStartColumn > 0)
961 OS << std::string(BlockStartColumn - 1, ' ') << "^\n";
962 OS << "The \"" << BlockIdentifierMessage << "\" block is here.\n";
963 }
964 }
965 return returnValue;
966 }
967
John Thompson94faa4d2013-07-26 23:56:42 +0000968 // Handle entering a header source file.
969 void handleHeaderEntry(clang::Preprocessor &PP, llvm::StringRef HeaderPath) {
970 // Ignore <built-in> and <command-line> to reduce message clutter.
971 if (HeaderPath.startswith("<"))
972 return;
973 HeaderHandle H = addHeader(HeaderPath);
John Thompson4ed963a2013-08-07 18:49:47 +0000974 if (H != getCurrentHeaderHandle())
John Thompson94faa4d2013-07-26 23:56:42 +0000975 pushHeaderHandle(H);
John Thompson4ed963a2013-08-07 18:49:47 +0000976 // Check for nested header.
977 if (!InNestedHeader)
David Blaikie34318812014-11-19 07:49:54 +0000978 InNestedHeader = !HeadersInThisCompile.insert(H).second;
John Thompson94faa4d2013-07-26 23:56:42 +0000979 }
John Thompsonecd3b042015-02-11 16:58:36 +0000980
John Thompson94faa4d2013-07-26 23:56:42 +0000981 // Handle exiting a header source file.
982 void handleHeaderExit(llvm::StringRef HeaderPath) {
983 // Ignore <built-in> and <command-line> to reduce message clutter.
984 if (HeaderPath.startswith("<"))
985 return;
986 HeaderHandle H = findHeaderHandle(HeaderPath);
John Thompsonf1828ef2015-02-12 15:26:17 +0000987 HeaderHandle TH;
John Thompson94faa4d2013-07-26 23:56:42 +0000988 if (isHeaderHandleInStack(H)) {
John Thompsonf1828ef2015-02-12 15:26:17 +0000989 do {
990 TH = getCurrentHeaderHandle();
John Thompson94faa4d2013-07-26 23:56:42 +0000991 popHeaderHandle();
John Thompsonf1828ef2015-02-12 15:26:17 +0000992 } while ((TH != H) && (HeaderStack.size() != 0));
John Thompson94faa4d2013-07-26 23:56:42 +0000993 }
John Thompson48df0962013-08-05 23:55:14 +0000994 InNestedHeader = false;
John Thompson94faa4d2013-07-26 23:56:42 +0000995 }
996
997 // Lookup/add string.
998 StringHandle addString(llvm::StringRef Str) { return Strings.intern(Str); }
999
John Thompson97244312015-02-11 16:45:50 +00001000 // Convert to a canonical path.
1001 std::string getCanonicalPath(llvm::StringRef path) const {
1002 std::string CanonicalPath(path);
1003 std::replace(CanonicalPath.begin(), CanonicalPath.end(), '\\', '/');
1004 return CanonicalPath;
1005 }
1006
John Thompsonecd3b042015-02-11 16:58:36 +00001007 // Return true if the given header is in the header list.
1008 bool isHeaderListHeader(llvm::StringRef HeaderPath) const {
1009 std::string CanonicalPath = getCanonicalPath(HeaderPath);
1010 for (llvm::ArrayRef<std::string>::iterator I = HeaderList.begin(),
1011 E = HeaderList.end();
1012 I != E; ++I) {
1013 if (*I == CanonicalPath)
1014 return true;
1015 }
1016 return false;
1017 }
1018
John Thompson94faa4d2013-07-26 23:56:42 +00001019 // Get the handle of a header file entry.
1020 // Return HeaderHandleInvalid if not found.
1021 HeaderHandle findHeaderHandle(llvm::StringRef HeaderPath) const {
John Thompson97244312015-02-11 16:45:50 +00001022 std::string CanonicalPath = getCanonicalPath(HeaderPath);
John Thompson94faa4d2013-07-26 23:56:42 +00001023 HeaderHandle H = 0;
1024 for (std::vector<StringHandle>::const_iterator I = HeaderPaths.begin(),
1025 E = HeaderPaths.end();
1026 I != E; ++I, ++H) {
John Thompson48df0962013-08-05 23:55:14 +00001027 if (**I == CanonicalPath)
John Thompson94faa4d2013-07-26 23:56:42 +00001028 return H;
1029 }
1030 return HeaderHandleInvalid;
1031 }
1032
1033 // Add a new header file entry, or return existing handle.
1034 // Return the header handle.
1035 HeaderHandle addHeader(llvm::StringRef HeaderPath) {
John Thompson97244312015-02-11 16:45:50 +00001036 std::string CanonicalPath = getCanonicalPath(HeaderPath);
John Thompson48df0962013-08-05 23:55:14 +00001037 HeaderHandle H = findHeaderHandle(CanonicalPath);
John Thompson94faa4d2013-07-26 23:56:42 +00001038 if (H == HeaderHandleInvalid) {
1039 H = HeaderPaths.size();
John Thompson48df0962013-08-05 23:55:14 +00001040 HeaderPaths.push_back(addString(CanonicalPath));
John Thompson94faa4d2013-07-26 23:56:42 +00001041 }
1042 return H;
1043 }
1044
1045 // Return a header file path string given its handle.
1046 StringHandle getHeaderFilePath(HeaderHandle H) const {
1047 if ((H >= 0) && (H < (HeaderHandle)HeaderPaths.size()))
1048 return HeaderPaths[H];
1049 return StringHandle();
1050 }
1051
1052 // Returns a handle to the inclusion path.
1053 InclusionPathHandle pushHeaderHandle(HeaderHandle H) {
1054 HeaderStack.push_back(H);
1055 return CurrentInclusionPathHandle = addInclusionPathHandle(HeaderStack);
1056 }
1057 // Pops the last header handle from the stack;
1058 void popHeaderHandle() {
1059 // assert((HeaderStack.size() != 0) && "Header stack already empty.");
1060 if (HeaderStack.size() != 0) {
1061 HeaderStack.pop_back();
1062 CurrentInclusionPathHandle = addInclusionPathHandle(HeaderStack);
1063 }
1064 }
1065 // Get the top handle on the header stack.
1066 HeaderHandle getCurrentHeaderHandle() const {
1067 if (HeaderStack.size() != 0)
1068 return HeaderStack.back();
1069 return HeaderHandleInvalid;
1070 }
1071
1072 // Check for presence of header handle in the header stack.
1073 bool isHeaderHandleInStack(HeaderHandle H) const {
1074 for (std::vector<HeaderHandle>::const_iterator I = HeaderStack.begin(),
1075 E = HeaderStack.end();
1076 I != E; ++I) {
1077 if (*I == H)
1078 return true;
1079 }
1080 return false;
1081 }
1082
1083 // Get the handle of a header inclusion path entry.
1084 // Return InclusionPathHandleInvalid if not found.
1085 InclusionPathHandle
1086 findInclusionPathHandle(const std::vector<HeaderHandle> &Path) const {
1087 InclusionPathHandle H = 0;
1088 for (std::vector<HeaderInclusionPath>::const_iterator
1089 I = InclusionPaths.begin(),
1090 E = InclusionPaths.end();
1091 I != E; ++I, ++H) {
1092 if (I->Path == Path)
1093 return H;
1094 }
1095 return HeaderHandleInvalid;
1096 }
1097 // Add a new header inclusion path entry, or return existing handle.
1098 // Return the header inclusion path entry handle.
1099 InclusionPathHandle
1100 addInclusionPathHandle(const std::vector<HeaderHandle> &Path) {
1101 InclusionPathHandle H = findInclusionPathHandle(Path);
1102 if (H == HeaderHandleInvalid) {
1103 H = InclusionPaths.size();
1104 InclusionPaths.push_back(HeaderInclusionPath(Path));
1105 }
1106 return H;
1107 }
1108 // Return the current inclusion path handle.
1109 InclusionPathHandle getCurrentInclusionPathHandle() const {
1110 return CurrentInclusionPathHandle;
1111 }
1112
1113 // Return an inclusion path given its handle.
1114 const std::vector<HeaderHandle> &
1115 getInclusionPath(InclusionPathHandle H) const {
1116 if ((H >= 0) && (H <= (InclusionPathHandle)InclusionPaths.size()))
1117 return InclusionPaths[H].Path;
1118 static std::vector<HeaderHandle> Empty;
1119 return Empty;
1120 }
1121
1122 // Add a macro expansion instance.
1123 void addMacroExpansionInstance(clang::Preprocessor &PP, HeaderHandle H,
1124 clang::SourceLocation InstanceLoc,
1125 clang::SourceLocation DefinitionLoc,
1126 clang::IdentifierInfo *II,
1127 llvm::StringRef MacroUnexpanded,
1128 llvm::StringRef MacroExpanded,
1129 InclusionPathHandle InclusionPathHandle) {
John Thompsonc8d710c2013-08-13 18:11:36 +00001130 if (InNestedHeader)
1131 return;
John Thompson94faa4d2013-07-26 23:56:42 +00001132 StringHandle MacroName = addString(II->getName());
1133 PPItemKey InstanceKey(PP, MacroName, H, InstanceLoc);
1134 PPItemKey DefinitionKey(PP, MacroName, H, DefinitionLoc);
1135 MacroExpansionMapIter I = MacroExpansions.find(InstanceKey);
John Thompson7c6e79f32013-07-29 19:07:00 +00001136 // If existing instance of expansion not found, add one.
John Thompson94faa4d2013-07-26 23:56:42 +00001137 if (I == MacroExpansions.end()) {
1138 std::string InstanceSourceLine =
1139 getSourceLocationString(PP, InstanceLoc) + ":\n" +
1140 getSourceLine(PP, InstanceLoc) + "\n";
1141 std::string DefinitionSourceLine =
1142 getSourceLocationString(PP, DefinitionLoc) + ":\n" +
1143 getSourceLine(PP, DefinitionLoc) + "\n";
1144 MacroExpansions[InstanceKey] = MacroExpansionTracker(
1145 addString(MacroUnexpanded), addString(MacroExpanded),
1146 addString(InstanceSourceLine), DefinitionKey,
1147 addString(DefinitionSourceLine), InclusionPathHandle);
1148 } else {
John Thompson7c6e79f32013-07-29 19:07:00 +00001149 // We've seen the macro before. Get its tracker.
John Thompson94faa4d2013-07-26 23:56:42 +00001150 MacroExpansionTracker &CondTracker = I->second;
John Thompson7c6e79f32013-07-29 19:07:00 +00001151 // Look up an existing instance value for the macro.
John Thompson94faa4d2013-07-26 23:56:42 +00001152 MacroExpansionInstance *MacroInfo =
1153 CondTracker.findMacroExpansionInstance(addString(MacroExpanded),
1154 DefinitionKey);
John Thompson7c6e79f32013-07-29 19:07:00 +00001155 // If found, just add the inclusion path to the instance.
Craig Topperf61be9c2014-06-09 02:03:06 +00001156 if (MacroInfo)
John Thompson94faa4d2013-07-26 23:56:42 +00001157 MacroInfo->addInclusionPathHandle(InclusionPathHandle);
1158 else {
John Thompson7c6e79f32013-07-29 19:07:00 +00001159 // Otherwise add a new instance with the unique value.
John Thompson94faa4d2013-07-26 23:56:42 +00001160 std::string DefinitionSourceLine =
1161 getSourceLocationString(PP, DefinitionLoc) + ":\n" +
1162 getSourceLine(PP, DefinitionLoc) + "\n";
1163 CondTracker.addMacroExpansionInstance(
1164 addString(MacroExpanded), DefinitionKey,
1165 addString(DefinitionSourceLine), InclusionPathHandle);
1166 }
1167 }
1168 }
1169
1170 // Add a conditional expansion instance.
1171 void
1172 addConditionalExpansionInstance(clang::Preprocessor &PP, HeaderHandle H,
1173 clang::SourceLocation InstanceLoc,
1174 clang::tok::PPKeywordKind DirectiveKind,
John Thompson87f9fef2013-12-07 08:41:15 +00001175 clang::PPCallbacks::ConditionValueKind ConditionValue,
John Thompson94faa4d2013-07-26 23:56:42 +00001176 llvm::StringRef ConditionUnexpanded,
1177 InclusionPathHandle InclusionPathHandle) {
John Thompson48df0962013-08-05 23:55:14 +00001178 // Ignore header guards, assuming the header guard is the only conditional.
1179 if (InNestedHeader)
1180 return;
John Thompson94faa4d2013-07-26 23:56:42 +00001181 StringHandle ConditionUnexpandedHandle(addString(ConditionUnexpanded));
1182 PPItemKey InstanceKey(PP, ConditionUnexpandedHandle, H, InstanceLoc);
1183 ConditionalExpansionMapIter I = ConditionalExpansions.find(InstanceKey);
John Thompson7c6e79f32013-07-29 19:07:00 +00001184 // If existing instance of condition not found, add one.
John Thompson94faa4d2013-07-26 23:56:42 +00001185 if (I == ConditionalExpansions.end()) {
1186 std::string InstanceSourceLine =
1187 getSourceLocationString(PP, InstanceLoc) + ":\n" +
1188 getSourceLine(PP, InstanceLoc) + "\n";
1189 ConditionalExpansions[InstanceKey] =
John Thompson48df0962013-08-05 23:55:14 +00001190 ConditionalTracker(DirectiveKind, ConditionValue,
John Thompsoncc2e2912013-09-03 18:44:11 +00001191 ConditionUnexpandedHandle, InclusionPathHandle);
John Thompson94faa4d2013-07-26 23:56:42 +00001192 } else {
John Thompson7c6e79f32013-07-29 19:07:00 +00001193 // We've seen the conditional before. Get its tracker.
John Thompson94faa4d2013-07-26 23:56:42 +00001194 ConditionalTracker &CondTracker = I->second;
John Thompson7c6e79f32013-07-29 19:07:00 +00001195 // Look up an existing instance value for the condition.
John Thompson94faa4d2013-07-26 23:56:42 +00001196 ConditionalExpansionInstance *MacroInfo =
1197 CondTracker.findConditionalExpansionInstance(ConditionValue);
John Thompson7c6e79f32013-07-29 19:07:00 +00001198 // If found, just add the inclusion path to the instance.
Craig Topperf61be9c2014-06-09 02:03:06 +00001199 if (MacroInfo)
John Thompson94faa4d2013-07-26 23:56:42 +00001200 MacroInfo->addInclusionPathHandle(InclusionPathHandle);
1201 else {
John Thompson7c6e79f32013-07-29 19:07:00 +00001202 // Otherwise add a new instance with the unique value.
John Thompson94faa4d2013-07-26 23:56:42 +00001203 CondTracker.addConditionalExpansionInstance(ConditionValue,
1204 InclusionPathHandle);
1205 }
1206 }
1207 }
1208
1209 // Report on inconsistent macro instances.
1210 // Returns true if any mismatches.
1211 bool reportInconsistentMacros(llvm::raw_ostream &OS) {
1212 bool ReturnValue = false;
John Thompson7c6e79f32013-07-29 19:07:00 +00001213 // Walk all the macro expansion trackers in the map.
John Thompson94faa4d2013-07-26 23:56:42 +00001214 for (MacroExpansionMapIter I = MacroExpansions.begin(),
1215 E = MacroExpansions.end();
1216 I != E; ++I) {
1217 const PPItemKey &ItemKey = I->first;
1218 MacroExpansionTracker &MacroExpTracker = I->second;
John Thompson7c6e79f32013-07-29 19:07:00 +00001219 // If no mismatch (only one instance value) continue.
John Thompson94faa4d2013-07-26 23:56:42 +00001220 if (!MacroExpTracker.hasMismatch())
1221 continue;
John Thompson7c6e79f32013-07-29 19:07:00 +00001222 // Tell caller we found one or more errors.
John Thompson94faa4d2013-07-26 23:56:42 +00001223 ReturnValue = true;
John Thompson7c6e79f32013-07-29 19:07:00 +00001224 // Start the error message.
John Thompson94faa4d2013-07-26 23:56:42 +00001225 OS << *MacroExpTracker.InstanceSourceLine;
1226 if (ItemKey.Column > 0)
1227 OS << std::string(ItemKey.Column - 1, ' ') << "^\n";
1228 OS << "error: Macro instance '" << *MacroExpTracker.MacroUnexpanded
1229 << "' has different values in this header, depending on how it was "
1230 "included.\n";
John Thompson7c6e79f32013-07-29 19:07:00 +00001231 // Walk all the instances.
John Thompson94faa4d2013-07-26 23:56:42 +00001232 for (std::vector<MacroExpansionInstance>::iterator
1233 IMT = MacroExpTracker.MacroExpansionInstances.begin(),
1234 EMT = MacroExpTracker.MacroExpansionInstances.end();
1235 IMT != EMT; ++IMT) {
1236 MacroExpansionInstance &MacroInfo = *IMT;
1237 OS << " '" << *MacroExpTracker.MacroUnexpanded << "' expanded to: '"
1238 << *MacroInfo.MacroExpanded
1239 << "' with respect to these inclusion paths:\n";
John Thompson7c6e79f32013-07-29 19:07:00 +00001240 // Walk all the inclusion path hierarchies.
John Thompson94faa4d2013-07-26 23:56:42 +00001241 for (std::vector<InclusionPathHandle>::iterator
1242 IIP = MacroInfo.InclusionPathHandles.begin(),
1243 EIP = MacroInfo.InclusionPathHandles.end();
1244 IIP != EIP; ++IIP) {
1245 const std::vector<HeaderHandle> &ip = getInclusionPath(*IIP);
1246 int Count = (int)ip.size();
1247 for (int Index = 0; Index < Count; ++Index) {
1248 HeaderHandle H = ip[Index];
1249 OS << std::string((Index * 2) + 4, ' ') << *getHeaderFilePath(H)
1250 << "\n";
1251 }
1252 }
1253 // For a macro that wasn't defined, we flag it by using the
1254 // instance location.
1255 // If there is a definition...
1256 if (MacroInfo.DefinitionLocation.Line != ItemKey.Line) {
1257 OS << *MacroInfo.DefinitionSourceLine;
1258 if (MacroInfo.DefinitionLocation.Column > 0)
1259 OS << std::string(MacroInfo.DefinitionLocation.Column - 1, ' ')
1260 << "^\n";
1261 OS << "Macro defined here.\n";
1262 } else
1263 OS << "(no macro definition)"
1264 << "\n";
1265 }
1266 }
1267 return ReturnValue;
1268 }
1269
1270 // Report on inconsistent conditional instances.
1271 // Returns true if any mismatches.
1272 bool reportInconsistentConditionals(llvm::raw_ostream &OS) {
1273 bool ReturnValue = false;
John Thompson7c6e79f32013-07-29 19:07:00 +00001274 // Walk all the conditional trackers in the map.
John Thompson94faa4d2013-07-26 23:56:42 +00001275 for (ConditionalExpansionMapIter I = ConditionalExpansions.begin(),
1276 E = ConditionalExpansions.end();
1277 I != E; ++I) {
1278 const PPItemKey &ItemKey = I->first;
1279 ConditionalTracker &CondTracker = I->second;
1280 if (!CondTracker.hasMismatch())
1281 continue;
John Thompson7c6e79f32013-07-29 19:07:00 +00001282 // Tell caller we found one or more errors.
John Thompson94faa4d2013-07-26 23:56:42 +00001283 ReturnValue = true;
John Thompson7c6e79f32013-07-29 19:07:00 +00001284 // Start the error message.
John Thompson94faa4d2013-07-26 23:56:42 +00001285 OS << *HeaderPaths[ItemKey.File] << ":" << ItemKey.Line << ":"
1286 << ItemKey.Column << "\n";
1287 OS << "#" << getDirectiveSpelling(CondTracker.DirectiveKind) << " "
1288 << *CondTracker.ConditionUnexpanded << "\n";
1289 OS << "^\n";
1290 OS << "error: Conditional expression instance '"
1291 << *CondTracker.ConditionUnexpanded
1292 << "' has different values in this header, depending on how it was "
1293 "included.\n";
John Thompson7c6e79f32013-07-29 19:07:00 +00001294 // Walk all the instances.
John Thompson94faa4d2013-07-26 23:56:42 +00001295 for (std::vector<ConditionalExpansionInstance>::iterator
1296 IMT = CondTracker.ConditionalExpansionInstances.begin(),
1297 EMT = CondTracker.ConditionalExpansionInstances.end();
1298 IMT != EMT; ++IMT) {
1299 ConditionalExpansionInstance &MacroInfo = *IMT;
1300 OS << " '" << *CondTracker.ConditionUnexpanded << "' expanded to: '"
John Thompson87f9fef2013-12-07 08:41:15 +00001301 << ConditionValueKindStrings[MacroInfo.ConditionValue]
John Thompson94faa4d2013-07-26 23:56:42 +00001302 << "' with respect to these inclusion paths:\n";
John Thompson7c6e79f32013-07-29 19:07:00 +00001303 // Walk all the inclusion path hierarchies.
John Thompson94faa4d2013-07-26 23:56:42 +00001304 for (std::vector<InclusionPathHandle>::iterator
1305 IIP = MacroInfo.InclusionPathHandles.begin(),
1306 EIP = MacroInfo.InclusionPathHandles.end();
1307 IIP != EIP; ++IIP) {
1308 const std::vector<HeaderHandle> &ip = getInclusionPath(*IIP);
1309 int Count = (int)ip.size();
1310 for (int Index = 0; Index < Count; ++Index) {
1311 HeaderHandle H = ip[Index];
1312 OS << std::string((Index * 2) + 4, ' ') << *getHeaderFilePath(H)
1313 << "\n";
1314 }
1315 }
1316 }
1317 }
1318 return ReturnValue;
1319 }
1320
1321 // Get directive spelling.
1322 static const char *getDirectiveSpelling(clang::tok::PPKeywordKind kind) {
1323 switch (kind) {
1324 case clang::tok::pp_if:
1325 return "if";
1326 case clang::tok::pp_elif:
1327 return "elif";
1328 case clang::tok::pp_ifdef:
1329 return "ifdef";
1330 case clang::tok::pp_ifndef:
1331 return "ifndef";
1332 default:
1333 return "(unknown)";
1334 }
1335 }
1336
1337private:
John Thompsonecd3b042015-02-11 16:58:36 +00001338 llvm::SmallVector<std::string, 32> HeaderList;
1339 // Only do extern, namespace check for headers in HeaderList.
1340 bool BlockCheckHeaderListOnly;
John Thompson94faa4d2013-07-26 23:56:42 +00001341 llvm::StringPool Strings;
1342 std::vector<StringHandle> HeaderPaths;
1343 std::vector<HeaderHandle> HeaderStack;
1344 std::vector<HeaderInclusionPath> InclusionPaths;
1345 InclusionPathHandle CurrentInclusionPathHandle;
John Thompson4ed963a2013-08-07 18:49:47 +00001346 llvm::SmallSet<HeaderHandle, 128> HeadersInThisCompile;
John Thompson74083922013-09-18 18:19:43 +00001347 std::vector<PPItemKey> IncludeDirectives;
John Thompson94faa4d2013-07-26 23:56:42 +00001348 MacroExpansionMap MacroExpansions;
1349 ConditionalExpansionMap ConditionalExpansions;
John Thompson48df0962013-08-05 23:55:14 +00001350 bool InNestedHeader;
John Thompson94faa4d2013-07-26 23:56:42 +00001351};
1352
1353// PreprocessorTracker functions.
1354
1355// PreprocessorTracker desctructor.
1356PreprocessorTracker::~PreprocessorTracker() {}
1357
1358// Create instance of PreprocessorTracker.
John Thompsonecd3b042015-02-11 16:58:36 +00001359PreprocessorTracker *PreprocessorTracker::create(
1360 llvm::SmallVector<std::string, 32> &Headers,
1361 bool DoBlockCheckHeaderListOnly) {
1362 return new PreprocessorTrackerImpl(Headers, DoBlockCheckHeaderListOnly);
John Thompson94faa4d2013-07-26 23:56:42 +00001363}
1364
1365// Preprocessor callbacks for modularize.
1366
John Thompson74083922013-09-18 18:19:43 +00001367// Handle include directive.
1368void PreprocessorCallbacks::InclusionDirective(
1369 clang::SourceLocation HashLoc, const clang::Token &IncludeTok,
1370 llvm::StringRef FileName, bool IsAngled,
1371 clang::CharSourceRange FilenameRange, const clang::FileEntry *File,
1372 llvm::StringRef SearchPath, llvm::StringRef RelativePath,
1373 const clang::Module *Imported) {
1374 int DirectiveLine, DirectiveColumn;
1375 std::string HeaderPath = getSourceLocationFile(PP, HashLoc);
1376 getSourceLocationLineAndColumn(PP, HashLoc, DirectiveLine, DirectiveColumn);
1377 PPTracker.handleIncludeDirective(HeaderPath, DirectiveLine, DirectiveColumn,
1378 FileName);
1379}
1380
John Thompson94faa4d2013-07-26 23:56:42 +00001381// Handle file entry/exit.
1382void PreprocessorCallbacks::FileChanged(
1383 clang::SourceLocation Loc, clang::PPCallbacks::FileChangeReason Reason,
1384 clang::SrcMgr::CharacteristicKind FileType, clang::FileID PrevFID) {
1385 switch (Reason) {
1386 case EnterFile:
1387 PPTracker.handleHeaderEntry(PP, getSourceLocationFile(PP, Loc));
1388 break;
John Thompsoncc2e2912013-09-03 18:44:11 +00001389 case ExitFile: {
1390 const clang::FileEntry *F =
John Thompson48df0962013-08-05 23:55:14 +00001391 PP.getSourceManager().getFileEntryForID(PrevFID);
Craig Topperf61be9c2014-06-09 02:03:06 +00001392 if (F)
John Thompsoncc2e2912013-09-03 18:44:11 +00001393 PPTracker.handleHeaderExit(F->getName());
1394 } break;
John Thompson94faa4d2013-07-26 23:56:42 +00001395 case SystemHeaderPragma:
John Thompson94faa4d2013-07-26 23:56:42 +00001396 case RenameFile:
Benjamin Kramerf2576812013-07-27 15:57:46 +00001397 break;
John Thompson94faa4d2013-07-26 23:56:42 +00001398 }
1399}
1400
1401// Handle macro expansion.
1402void PreprocessorCallbacks::MacroExpands(const clang::Token &MacroNameTok,
1403 const clang::MacroDirective *MD,
1404 clang::SourceRange Range,
1405 const clang::MacroArgs *Args) {
1406 clang::SourceLocation Loc = Range.getBegin();
John Thompson91555bd2013-08-09 00:22:20 +00001407 // Ignore macro argument expansions.
1408 if (!Loc.isFileID())
1409 return;
John Thompson94faa4d2013-07-26 23:56:42 +00001410 clang::IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
1411 const clang::MacroInfo *MI = PP.getMacroInfo(II);
1412 std::string MacroName = II->getName().str();
1413 std::string Unexpanded(getMacroUnexpandedString(Range, PP, MacroName, MI));
1414 std::string Expanded(getMacroExpandedString(PP, MacroName, MI, Args));
1415 PPTracker.addMacroExpansionInstance(
1416 PP, PPTracker.getCurrentHeaderHandle(), Loc, MI->getDefinitionLoc(), II,
1417 Unexpanded, Expanded, PPTracker.getCurrentInclusionPathHandle());
1418}
1419
1420void PreprocessorCallbacks::Defined(const clang::Token &MacroNameTok,
1421 const clang::MacroDirective *MD,
1422 clang::SourceRange Range) {
1423 clang::SourceLocation Loc(Range.getBegin());
1424 clang::IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
1425 const clang::MacroInfo *MI = PP.getMacroInfo(II);
1426 std::string MacroName = II->getName().str();
1427 std::string Unexpanded(getSourceString(PP, Range));
1428 PPTracker.addMacroExpansionInstance(
1429 PP, PPTracker.getCurrentHeaderHandle(), Loc,
1430 (MI ? MI->getDefinitionLoc() : Loc), II, Unexpanded,
1431 (MI ? "true" : "false"), PPTracker.getCurrentInclusionPathHandle());
1432}
1433
1434void PreprocessorCallbacks::If(clang::SourceLocation Loc,
1435 clang::SourceRange ConditionRange,
John Thompson87f9fef2013-12-07 08:41:15 +00001436 clang::PPCallbacks::ConditionValueKind ConditionResult) {
John Thompson94faa4d2013-07-26 23:56:42 +00001437 std::string Unexpanded(getSourceString(PP, ConditionRange));
1438 PPTracker.addConditionalExpansionInstance(
1439 PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_if,
1440 ConditionResult, Unexpanded, PPTracker.getCurrentInclusionPathHandle());
1441}
1442
1443void PreprocessorCallbacks::Elif(clang::SourceLocation Loc,
1444 clang::SourceRange ConditionRange,
John Thompson87f9fef2013-12-07 08:41:15 +00001445 clang::PPCallbacks::ConditionValueKind ConditionResult,
John Thompson94faa4d2013-07-26 23:56:42 +00001446 clang::SourceLocation IfLoc) {
1447 std::string Unexpanded(getSourceString(PP, ConditionRange));
1448 PPTracker.addConditionalExpansionInstance(
1449 PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_elif,
1450 ConditionResult, Unexpanded, PPTracker.getCurrentInclusionPathHandle());
1451}
1452
1453void PreprocessorCallbacks::Ifdef(clang::SourceLocation Loc,
1454 const clang::Token &MacroNameTok,
1455 const clang::MacroDirective *MD) {
John Thompson87f9fef2013-12-07 08:41:15 +00001456 clang::PPCallbacks::ConditionValueKind IsDefined =
Craig Topperf61be9c2014-06-09 02:03:06 +00001457 (MD ? clang::PPCallbacks::CVK_True : clang::PPCallbacks::CVK_False );
John Thompson94faa4d2013-07-26 23:56:42 +00001458 PPTracker.addConditionalExpansionInstance(
1459 PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_ifdef,
1460 IsDefined, PP.getSpelling(MacroNameTok),
1461 PPTracker.getCurrentInclusionPathHandle());
1462}
1463
1464void PreprocessorCallbacks::Ifndef(clang::SourceLocation Loc,
1465 const clang::Token &MacroNameTok,
1466 const clang::MacroDirective *MD) {
John Thompson87f9fef2013-12-07 08:41:15 +00001467 clang::PPCallbacks::ConditionValueKind IsNotDefined =
Craig Topperf61be9c2014-06-09 02:03:06 +00001468 (!MD ? clang::PPCallbacks::CVK_True : clang::PPCallbacks::CVK_False );
John Thompson94faa4d2013-07-26 23:56:42 +00001469 PPTracker.addConditionalExpansionInstance(
1470 PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_ifndef,
1471 IsNotDefined, PP.getSpelling(MacroNameTok),
1472 PPTracker.getCurrentInclusionPathHandle());
1473}
1474} // end namespace Modularize