clang 10.0.0git

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