clang  8.0.0svn
MacroPPCallbacks.cpp
Go to the documentation of this file.
1 //===--- MacroPPCallbacks.cpp ---------------------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains implementation for the macro preprocessors callbacks.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "MacroPPCallbacks.h"
15 #include "CGDebugInfo.h"
17 #include "clang/Lex/MacroInfo.h"
18 #include "clang/Lex/Preprocessor.h"
19 
20 using namespace clang;
21 
22 void MacroPPCallbacks::writeMacroDefinition(const IdentifierInfo &II,
23  const MacroInfo &MI,
24  Preprocessor &PP, raw_ostream &Name,
25  raw_ostream &Value) {
26  Name << II.getName();
27 
28  if (MI.isFunctionLike()) {
29  Name << '(';
30  if (!MI.param_empty()) {
32  for (; AI + 1 != E; ++AI) {
33  Name << (*AI)->getName();
34  Name << ',';
35  }
36 
37  // Last argument.
38  if ((*AI)->getName() == "__VA_ARGS__")
39  Name << "...";
40  else
41  Name << (*AI)->getName();
42  }
43 
44  if (MI.isGNUVarargs())
45  // #define foo(x...)
46  Name << "...";
47 
48  Name << ')';
49  }
50 
51  SmallString<128> SpellingBuffer;
52  bool First = true;
53  for (const auto &T : MI.tokens()) {
54  if (!First && T.hasLeadingSpace())
55  Value << ' ';
56 
57  Value << PP.getSpelling(T, SpellingBuffer);
58  First = false;
59  }
60 }
61 
63  : Gen(Gen), PP(PP), Status(NoScope) {}
64 
65 // This is the expected flow of enter/exit compiler and user files:
66 // - Main File Enter
67 // - <built-in> file enter
68 // {Compiler macro definitions} - (Line=0, no scope)
69 // - (Optional) <command line> file enter
70 // {Command line macro definitions} - (Line=0, no scope)
71 // - (Optional) <command line> file exit
72 // {Command line file includes} - (Line=0, Main file scope)
73 // {macro definitions and file includes} - (Line!=0, Parent scope)
74 // - <built-in> file exit
75 // {User code macro definitions and file includes} - (Line!=0, Parent scope)
76 
77 llvm::DIMacroFile *MacroPPCallbacks::getCurrentScope() {
78  if (Status == MainFileScope || Status == CommandLineIncludeScope)
79  return Scopes.back();
80  return nullptr;
81 }
82 
83 SourceLocation MacroPPCallbacks::getCorrectLocation(SourceLocation Loc) {
84  if (Status == MainFileScope || EnteredCommandLineIncludeFiles)
85  return Loc;
86 
87  // While parsing skipped files, location of macros is invalid.
88  // Invalid location represents line zero.
89  return SourceLocation();
90 }
91 
92 void MacroPPCallbacks::updateStatusToNextScope() {
93  switch (Status) {
94  case NoScope:
95  Status = InitializedScope;
96  break;
97  case InitializedScope:
98  Status = BuiltinScope;
99  break;
100  case BuiltinScope:
101  Status = CommandLineIncludeScope;
102  break;
103  case CommandLineIncludeScope:
104  Status = MainFileScope;
105  break;
106  case MainFileScope:
107  llvm_unreachable("There is no next scope, already in the final scope");
108  }
109 }
110 
111 void MacroPPCallbacks::FileEntered(SourceLocation Loc) {
112  SourceLocation LineLoc = getCorrectLocation(LastHashLoc);
113  switch (Status) {
114  case NoScope:
115  updateStatusToNextScope();
116  break;
117  case InitializedScope:
118  updateStatusToNextScope();
119  return;
120  case BuiltinScope:
122  return;
123  updateStatusToNextScope();
124  LLVM_FALLTHROUGH;
125  case CommandLineIncludeScope:
126  EnteredCommandLineIncludeFiles++;
127  break;
128  case MainFileScope:
129  break;
130  }
131 
132  Scopes.push_back(Gen->getCGDebugInfo()->CreateTempMacroFile(getCurrentScope(),
133  LineLoc, Loc));
134 }
135 
136 void MacroPPCallbacks::FileExited(SourceLocation Loc) {
137  switch (Status) {
138  default:
139  llvm_unreachable("Do not expect to exit a file from current scope");
140  case BuiltinScope:
142  // Skip next scope and change status to MainFileScope.
143  Status = MainFileScope;
144  return;
145  case CommandLineIncludeScope:
146  if (!EnteredCommandLineIncludeFiles) {
147  updateStatusToNextScope();
148  return;
149  }
150  EnteredCommandLineIncludeFiles--;
151  break;
152  case MainFileScope:
153  break;
154  }
155 
156  Scopes.pop_back();
157 }
158 
161  FileID PrevFID) {
162  // Only care about enter file or exit file changes.
163  if (Reason == EnterFile)
164  FileEntered(Loc);
165  else if (Reason == ExitFile)
166  FileExited(Loc);
167 }
168 
170  SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
171  bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File,
172  StringRef SearchPath, StringRef RelativePath, const Module *Imported,
173  SrcMgr::CharacteristicKind FileType) {
174 
175  // Record the line location of the current included file.
176  LastHashLoc = HashLoc;
177 }
178 
179 void MacroPPCallbacks::MacroDefined(const Token &MacroNameTok,
180  const MacroDirective *MD) {
181  IdentifierInfo *Id = MacroNameTok.getIdentifierInfo();
182  SourceLocation location = getCorrectLocation(MacroNameTok.getLocation());
183  std::string NameBuffer, ValueBuffer;
184  llvm::raw_string_ostream Name(NameBuffer);
185  llvm::raw_string_ostream Value(ValueBuffer);
186  writeMacroDefinition(*Id, *MD->getMacroInfo(), PP, Name, Value);
187  Gen->getCGDebugInfo()->CreateMacro(getCurrentScope(),
188  llvm::dwarf::DW_MACINFO_define, location,
189  Name.str(), Value.str());
190 }
191 
192 void MacroPPCallbacks::MacroUndefined(const Token &MacroNameTok,
193  const MacroDefinition &MD,
194  const MacroDirective *Undef) {
195  IdentifierInfo *Id = MacroNameTok.getIdentifierInfo();
196  SourceLocation location = getCorrectLocation(MacroNameTok.getLocation());
197  Gen->getCGDebugInfo()->CreateMacro(getCurrentScope(),
198  llvm::dwarf::DW_MACINFO_undef, location,
199  Id->getName(), "");
200 }
param_iterator param_begin() const
Definition: MacroInfo.h:181
Defines the clang::MacroInfo and clang::MacroDirective classes.
A description of the current definition of a macro.
Definition: MacroInfo.h:565
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
Definition: SourceManager.h:78
One of these records is kept for each identifier that is lexed.
Token - This structure provides full information about a lexed token.
Definition: Token.h:35
llvm::DIMacro * CreateMacro(llvm::DIMacroFile *Parent, unsigned MType, SourceLocation LineLoc, StringRef Name, StringRef Value)
Create debug info for a macro defined by a #define directive or a macro undefined by a #undef directi...
Describes a module or submodule.
Definition: Module.h:65
param_iterator param_end() const
Definition: MacroInfo.h:182
StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const
Return the &#39;spelling&#39; of the token at the given location; does not go up to the spelling location or ...
The primary public interface to the Clang code generator.
Definition: ModuleBuilder.h:44
IdentifierInfo *const * param_iterator
Parameters - The list of parameters for a function-like macro.
Definition: MacroInfo.h:179
void FileChanged(SourceLocation Loc, FileChangeReason Reason, SrcMgr::CharacteristicKind FileType, FileID PrevFID=FileID()) override
Callback invoked whenever a source file is entered or exited.
Represents a character-granular source range.
int Id
Definition: ASTDiff.cpp:191
llvm::DIMacroFile * CreateTempMacroFile(llvm::DIMacroFile *Parent, SourceLocation LineLoc, SourceLocation FileLoc)
Create debug info for a file referenced by an #include directive.
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
Definition: Token.h:124
Defines the clang::Preprocessor interface.
SourceManager & getSourceManager() const
Definition: Preprocessor.h:819
Encapsulates changes to the "macros namespace" (the location where the macro name became active...
Definition: MacroInfo.h:291
Encodes a location in the source.
IdentifierInfo * getIdentifierInfo() const
Definition: Token.h:177
Cached information about one file (either on disk or in the virtual file system). ...
Definition: FileManager.h:60
bool isWrittenInBuiltinFile(SourceLocation Loc) const
Returns whether Loc is located in a <built-in> file.
const MacroInfo * getMacroInfo() const
Definition: MacroInfo.h:391
bool param_empty() const
Definition: MacroInfo.h:180
void MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD, const MacroDirective *Undef) override
Hook called whenever a macro #undef is seen.
StringRef getName() const
Return the actual identifier string.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Dataflow Directional Tag Classes.
bool isFunctionLike() const
Definition: MacroInfo.h:200
Encapsulates the data about a macro definition (e.g.
Definition: MacroInfo.h:40
void MacroDefined(const Token &MacroNameTok, const MacroDirective *MD) override
Hook called whenever a macro definition is seen.
void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File, StringRef SearchPath, StringRef RelativePath, const Module *Imported, SrcMgr::CharacteristicKind FileType) override
Callback invoked whenever a directive (#xxx) is processed.
bool isWrittenInCommandLineFile(SourceLocation Loc) const
Returns whether Loc is located in a <command line>=""> file.
ArrayRef< Token > tokens() const
Definition: MacroInfo.h:246
bool isGNUVarargs() const
Definition: MacroInfo.h:207
MacroPPCallbacks(CodeGenerator *Gen, Preprocessor &PP)
CodeGen::CGDebugInfo * getCGDebugInfo()
Return debug info code generator.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:125