]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/CodeGen/MacroPPCallbacks.cpp
Merge clang trunk r338150, and resolve conflicts.
[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/Parse/Parser.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 static bool isBuiltinFile(SourceManager &SM, SourceLocation Loc) {
92   StringRef Filename(SM.getPresumedLoc(Loc).getFilename());
93   return Filename.equals("<built-in>");
94 }
95
96 static bool isCommandLineFile(SourceManager &SM, SourceLocation Loc) {
97   StringRef Filename(SM.getPresumedLoc(Loc).getFilename());
98   return Filename.equals("<command line>");
99 }
100
101 void MacroPPCallbacks::updateStatusToNextScope() {
102   switch (Status) {
103   case NoScope:
104     Status = InitializedScope;
105     break;
106   case InitializedScope:
107     Status = BuiltinScope;
108     break;
109   case BuiltinScope:
110     Status = CommandLineIncludeScope;
111     break;
112   case CommandLineIncludeScope:
113     Status = MainFileScope;
114     break;
115   case MainFileScope:
116     llvm_unreachable("There is no next scope, already in the final scope");
117   }
118 }
119
120 void MacroPPCallbacks::FileEntered(SourceLocation Loc) {
121   SourceLocation LineLoc = getCorrectLocation(LastHashLoc);
122   switch (Status) {
123   case NoScope:
124     updateStatusToNextScope();
125     break;
126   case InitializedScope:
127     updateStatusToNextScope();
128     return;
129   case BuiltinScope:
130     if (isCommandLineFile(PP.getSourceManager(), Loc))
131       return;
132     updateStatusToNextScope();
133     LLVM_FALLTHROUGH;
134   case CommandLineIncludeScope:
135     EnteredCommandLineIncludeFiles++;
136     break;
137   case MainFileScope:
138     break;
139   }
140
141   Scopes.push_back(Gen->getCGDebugInfo()->CreateTempMacroFile(getCurrentScope(),
142                                                               LineLoc, Loc));
143 }
144
145 void MacroPPCallbacks::FileExited(SourceLocation Loc) {
146   switch (Status) {
147   default:
148     llvm_unreachable("Do not expect to exit a file from current scope");
149   case BuiltinScope:
150     if (!isBuiltinFile(PP.getSourceManager(), Loc))
151       // Skip next scope and change status to MainFileScope.
152       Status = MainFileScope;
153     return;
154   case CommandLineIncludeScope:
155     if (!EnteredCommandLineIncludeFiles) {
156       updateStatusToNextScope();
157       return;
158     }
159     EnteredCommandLineIncludeFiles--;
160     break;
161   case MainFileScope:
162     break;
163   }
164
165   Scopes.pop_back();
166 }
167
168 void MacroPPCallbacks::FileChanged(SourceLocation Loc, FileChangeReason Reason,
169                                    SrcMgr::CharacteristicKind FileType,
170                                    FileID PrevFID) {
171   // Only care about enter file or exit file changes.
172   if (Reason == EnterFile)
173     FileEntered(Loc);
174   else if (Reason == ExitFile)
175     FileExited(Loc);
176 }
177
178 void MacroPPCallbacks::InclusionDirective(
179     SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
180     bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File,
181     StringRef SearchPath, StringRef RelativePath, const Module *Imported,
182     SrcMgr::CharacteristicKind FileType) {
183
184   // Record the line location of the current included file.
185   LastHashLoc = HashLoc;
186 }
187
188 void MacroPPCallbacks::MacroDefined(const Token &MacroNameTok,
189                                     const MacroDirective *MD) {
190   IdentifierInfo *Id = MacroNameTok.getIdentifierInfo();
191   SourceLocation location = getCorrectLocation(MacroNameTok.getLocation());
192   std::string NameBuffer, ValueBuffer;
193   llvm::raw_string_ostream Name(NameBuffer);
194   llvm::raw_string_ostream Value(ValueBuffer);
195   writeMacroDefinition(*Id, *MD->getMacroInfo(), PP, Name, Value);
196   Gen->getCGDebugInfo()->CreateMacro(getCurrentScope(),
197                                      llvm::dwarf::DW_MACINFO_define, location,
198                                      Name.str(), Value.str());
199 }
200
201 void MacroPPCallbacks::MacroUndefined(const Token &MacroNameTok,
202                                       const MacroDefinition &MD,
203                                       const MacroDirective *Undef) {
204   IdentifierInfo *Id = MacroNameTok.getIdentifierInfo();
205   SourceLocation location = getCorrectLocation(MacroNameTok.getLocation());
206   Gen->getCGDebugInfo()->CreateMacro(getCurrentScope(),
207                                      llvm::dwarf::DW_MACINFO_undef, location,
208                                      Id->getName(), "");
209 }