]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/CodeGen/MacroPPCallbacks.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / lib / CodeGen / MacroPPCallbacks.cpp
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"
16 #include "clang/CodeGen/ModuleBuilder.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()) {
31       MacroInfo::param_iterator AI = MI.param_begin(), E = MI.param_end();
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
62 MacroPPCallbacks::MacroPPCallbacks(CodeGenerator *Gen, Preprocessor &PP)
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:
121     if (PP.getSourceManager().isWrittenInCommandLineFile(Loc))
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:
141     if (!PP.getSourceManager().isWrittenInBuiltinFile(Loc))
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
159 void MacroPPCallbacks::FileChanged(SourceLocation Loc, FileChangeReason Reason,
160                                    SrcMgr::CharacteristicKind FileType,
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
169 void MacroPPCallbacks::InclusionDirective(
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 }