/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Frontend/PrintPreprocessedOutput.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- PrintPreprocessedOutput.cpp - Implement the -E mode --------------===// |
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 code simply runs the preprocessor on the input file and prints out the |
10 | | // result. This is the traditional behavior of the -E option. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "clang/Frontend/Utils.h" |
15 | | #include "clang/Basic/CharInfo.h" |
16 | | #include "clang/Basic/Diagnostic.h" |
17 | | #include "clang/Basic/SourceManager.h" |
18 | | #include "clang/Frontend/PreprocessorOutputOptions.h" |
19 | | #include "clang/Lex/MacroInfo.h" |
20 | | #include "clang/Lex/PPCallbacks.h" |
21 | | #include "clang/Lex/Pragma.h" |
22 | | #include "clang/Lex/Preprocessor.h" |
23 | | #include "clang/Lex/TokenConcatenation.h" |
24 | | #include "llvm/ADT/STLExtras.h" |
25 | | #include "llvm/ADT/SmallString.h" |
26 | | #include "llvm/ADT/StringRef.h" |
27 | | #include "llvm/Support/ErrorHandling.h" |
28 | | #include "llvm/Support/raw_ostream.h" |
29 | | #include <cstdio> |
30 | | using namespace clang; |
31 | | |
32 | | /// PrintMacroDefinition - Print a macro definition in a form that will be |
33 | | /// properly accepted back as a definition. |
34 | | static void PrintMacroDefinition(const IdentifierInfo &II, const MacroInfo &MI, |
35 | 654k | Preprocessor &PP, raw_ostream &OS) { |
36 | 654k | OS << "#define " << II.getName(); |
37 | | |
38 | 654k | if (MI.isFunctionLike()) { |
39 | 6.49k | OS << '('; |
40 | 6.49k | if (!MI.param_empty()) { |
41 | 6.49k | MacroInfo::param_iterator AI = MI.param_begin(), E = MI.param_end(); |
42 | 6.68k | for (; AI+1 != E; ++AI191 ) { |
43 | 191 | OS << (*AI)->getName(); |
44 | 191 | OS << ','; |
45 | 191 | } |
46 | | |
47 | | // Last argument. |
48 | 6.49k | if ((*AI)->getName() == "__VA_ARGS__") |
49 | 2 | OS << "..."; |
50 | 6.48k | else |
51 | 6.48k | OS << (*AI)->getName(); |
52 | 6.49k | } |
53 | | |
54 | 6.49k | if (MI.isGNUVarargs()) |
55 | 1 | OS << "..."; // #define foo(x...) |
56 | | |
57 | 6.49k | OS << ')'; |
58 | 6.49k | } |
59 | | |
60 | | // GCC always emits a space, even if the macro body is empty. However, do not |
61 | | // want to emit two spaces if the first token has a leading space. |
62 | 654k | if (MI.tokens_empty() || !MI.tokens_begin()->hasLeadingSpace()642k ) |
63 | 648k | OS << ' '; |
64 | | |
65 | 654k | SmallString<128> SpellingBuffer; |
66 | 809k | for (const auto &T : MI.tokens()) { |
67 | 809k | if (T.hasLeadingSpace()) |
68 | 76.1k | OS << ' '; |
69 | | |
70 | 809k | OS << PP.getSpelling(T, SpellingBuffer); |
71 | 809k | } |
72 | 654k | } |
73 | | |
74 | | //===----------------------------------------------------------------------===// |
75 | | // Preprocessed token printer |
76 | | //===----------------------------------------------------------------------===// |
77 | | |
78 | | namespace { |
79 | | class PrintPPOutputPPCallbacks : public PPCallbacks { |
80 | | Preprocessor &PP; |
81 | | SourceManager &SM; |
82 | | TokenConcatenation ConcatInfo; |
83 | | public: |
84 | | raw_ostream &OS; |
85 | | private: |
86 | | unsigned CurLine; |
87 | | |
88 | | bool EmittedTokensOnThisLine; |
89 | | bool EmittedDirectiveOnThisLine; |
90 | | SrcMgr::CharacteristicKind FileType; |
91 | | SmallString<512> CurFilename; |
92 | | bool Initialized; |
93 | | bool DisableLineMarkers; |
94 | | bool DumpDefines; |
95 | | bool DumpIncludeDirectives; |
96 | | bool UseLineDirectives; |
97 | | bool IsFirstFileEntered; |
98 | | bool MinimizeWhitespace; |
99 | | bool DirectivesOnly; |
100 | | |
101 | | Token PrevTok; |
102 | | Token PrevPrevTok; |
103 | | |
104 | | public: |
105 | | PrintPPOutputPPCallbacks(Preprocessor &pp, raw_ostream &os, bool lineMarkers, |
106 | | bool defines, bool DumpIncludeDirectives, |
107 | | bool UseLineDirectives, bool MinimizeWhitespace, |
108 | | bool DirectivesOnly) |
109 | | : PP(pp), SM(PP.getSourceManager()), ConcatInfo(PP), OS(os), |
110 | | DisableLineMarkers(lineMarkers), DumpDefines(defines), |
111 | | DumpIncludeDirectives(DumpIncludeDirectives), |
112 | | UseLineDirectives(UseLineDirectives), |
113 | 584 | MinimizeWhitespace(MinimizeWhitespace), DirectivesOnly(DirectivesOnly) { |
114 | 584 | CurLine = 0; |
115 | 584 | CurFilename += "<uninit>"; |
116 | 584 | EmittedTokensOnThisLine = false; |
117 | 584 | EmittedDirectiveOnThisLine = false; |
118 | 584 | FileType = SrcMgr::C_User; |
119 | 584 | Initialized = false; |
120 | 584 | IsFirstFileEntered = false; |
121 | | |
122 | 584 | PrevTok.startToken(); |
123 | 584 | PrevPrevTok.startToken(); |
124 | 584 | } |
125 | | |
126 | 0 | bool isMinimizeWhitespace() const { return MinimizeWhitespace; } |
127 | | |
128 | 272k | void setEmittedTokensOnThisLine() { EmittedTokensOnThisLine = true; } |
129 | 0 | bool hasEmittedTokensOnThisLine() const { return EmittedTokensOnThisLine; } |
130 | | |
131 | 17.7k | void setEmittedDirectiveOnThisLine() { EmittedDirectiveOnThisLine = true; } |
132 | 0 | bool hasEmittedDirectiveOnThisLine() const { |
133 | 0 | return EmittedDirectiveOnThisLine; |
134 | 0 | } |
135 | | |
136 | | /// Ensure that the output stream position is at the beginning of a new line |
137 | | /// and inserts one if it does not. It is intended to ensure that directives |
138 | | /// inserted by the directives not from the input source (such as #line) are |
139 | | /// in the first column. To insert newlines that represent the input, use |
140 | | /// MoveToLine(/*...*/, /*RequireStartOfLine=*/true). |
141 | | void startNewLineIfNeeded(); |
142 | | |
143 | | void FileChanged(SourceLocation Loc, FileChangeReason Reason, |
144 | | SrcMgr::CharacteristicKind FileType, |
145 | | FileID PrevFID) override; |
146 | | void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, |
147 | | StringRef FileName, bool IsAngled, |
148 | | CharSourceRange FilenameRange, |
149 | | Optional<FileEntryRef> File, StringRef SearchPath, |
150 | | StringRef RelativePath, const Module *Imported, |
151 | | SrcMgr::CharacteristicKind FileType) override; |
152 | | void Ident(SourceLocation Loc, StringRef str) override; |
153 | | void PragmaMessage(SourceLocation Loc, StringRef Namespace, |
154 | | PragmaMessageKind Kind, StringRef Str) override; |
155 | | void PragmaDebug(SourceLocation Loc, StringRef DebugType) override; |
156 | | void PragmaDiagnosticPush(SourceLocation Loc, StringRef Namespace) override; |
157 | | void PragmaDiagnosticPop(SourceLocation Loc, StringRef Namespace) override; |
158 | | void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace, |
159 | | diag::Severity Map, StringRef Str) override; |
160 | | void PragmaWarning(SourceLocation Loc, PragmaWarningSpecifier WarningSpec, |
161 | | ArrayRef<int> Ids) override; |
162 | | void PragmaWarningPush(SourceLocation Loc, int Level) override; |
163 | | void PragmaWarningPop(SourceLocation Loc) override; |
164 | | void PragmaExecCharsetPush(SourceLocation Loc, StringRef Str) override; |
165 | | void PragmaExecCharsetPop(SourceLocation Loc) override; |
166 | | void PragmaAssumeNonNullBegin(SourceLocation Loc) override; |
167 | | void PragmaAssumeNonNullEnd(SourceLocation Loc) override; |
168 | | |
169 | | /// Insert whitespace before emitting the next token. |
170 | | /// |
171 | | /// @param Tok Next token to be emitted. |
172 | | /// @param RequireSpace Ensure at least one whitespace is emitted. Useful |
173 | | /// if non-tokens have been emitted to the stream. |
174 | | /// @param RequireSameLine Never emit newlines. Useful when semantics depend |
175 | | /// on being on the same line, such as directives. |
176 | | void HandleWhitespaceBeforeTok(const Token &Tok, bool RequireSpace, |
177 | | bool RequireSameLine); |
178 | | |
179 | | /// Move to the line of the provided source location. This will |
180 | | /// return true if a newline was inserted or if |
181 | | /// the requested location is the first token on the first line. |
182 | | /// In these cases the next output will be the first column on the line and |
183 | | /// make it possible to insert indention. The newline was inserted |
184 | | /// implicitly when at the beginning of the file. |
185 | | /// |
186 | | /// @param Tok Token where to move to. |
187 | | /// @param RequireStartOfLine Whether the next line depends on being in the |
188 | | /// first column, such as a directive. |
189 | | /// |
190 | | /// @return Whether column adjustments are necessary. |
191 | 46.4k | bool MoveToLine(const Token &Tok, bool RequireStartOfLine) { |
192 | 46.4k | PresumedLoc PLoc = SM.getPresumedLoc(Tok.getLocation()); |
193 | 46.4k | unsigned TargetLine = PLoc.isValid() ? PLoc.getLine()46.4k : CurLine2 ; |
194 | 46.4k | bool IsFirstInFile = |
195 | 46.4k | Tok.isAtStartOfLine() && PLoc.isValid()46.3k && PLoc.getLine() == 146.3k ; |
196 | 46.4k | return MoveToLine(TargetLine, RequireStartOfLine) || IsFirstInFile429 ; |
197 | 46.4k | } |
198 | | |
199 | | /// Move to the line of the provided source location. Returns true if a new |
200 | | /// line was inserted. |
201 | 2.42k | bool MoveToLine(SourceLocation Loc, bool RequireStartOfLine) { |
202 | 2.42k | PresumedLoc PLoc = SM.getPresumedLoc(Loc); |
203 | 2.42k | unsigned TargetLine = PLoc.isValid() ? PLoc.getLine()2.42k : CurLine5 ; |
204 | 2.42k | return MoveToLine(TargetLine, RequireStartOfLine); |
205 | 2.42k | } |
206 | | bool MoveToLine(unsigned LineNo, bool RequireStartOfLine); |
207 | | |
208 | | bool AvoidConcat(const Token &PrevPrevTok, const Token &PrevTok, |
209 | 155k | const Token &Tok) { |
210 | 155k | return ConcatInfo.AvoidConcat(PrevPrevTok, PrevTok, Tok); |
211 | 155k | } |
212 | | void WriteLineInfo(unsigned LineNo, const char *Extra=nullptr, |
213 | | unsigned ExtraLen=0); |
214 | 0 | bool LineMarkersAreDisabled() const { return DisableLineMarkers; } |
215 | | void HandleNewlinesInToken(const char *TokStr, unsigned Len); |
216 | | |
217 | | /// MacroDefined - This hook is called whenever a macro definition is seen. |
218 | | void MacroDefined(const Token &MacroNameTok, |
219 | | const MacroDirective *MD) override; |
220 | | |
221 | | /// MacroUndefined - This hook is called whenever a macro #undef is seen. |
222 | | void MacroUndefined(const Token &MacroNameTok, |
223 | | const MacroDefinition &MD, |
224 | | const MacroDirective *Undef) override; |
225 | | |
226 | | void BeginModule(const Module *M); |
227 | | void EndModule(const Module *M); |
228 | | }; |
229 | | } // end anonymous namespace |
230 | | |
231 | | void PrintPPOutputPPCallbacks::WriteLineInfo(unsigned LineNo, |
232 | | const char *Extra, |
233 | 5.86k | unsigned ExtraLen) { |
234 | 5.86k | startNewLineIfNeeded(); |
235 | | |
236 | | // Emit #line directives or GNU line markers depending on what mode we're in. |
237 | 5.86k | if (UseLineDirectives) { |
238 | 21 | OS << "#line" << ' ' << LineNo << ' ' << '"'; |
239 | 21 | OS.write_escaped(CurFilename); |
240 | 21 | OS << '"'; |
241 | 5.84k | } else { |
242 | 5.84k | OS << '#' << ' ' << LineNo << ' ' << '"'; |
243 | 5.84k | OS.write_escaped(CurFilename); |
244 | 5.84k | OS << '"'; |
245 | | |
246 | 5.84k | if (ExtraLen) |
247 | 3.14k | OS.write(Extra, ExtraLen); |
248 | | |
249 | 5.84k | if (FileType == SrcMgr::C_System) |
250 | 1.64k | OS.write(" 3", 2); |
251 | 4.19k | else if (FileType == SrcMgr::C_ExternCSystem) |
252 | 15 | OS.write(" 3 4", 4); |
253 | 5.84k | } |
254 | 5.86k | OS << '\n'; |
255 | 5.86k | } |
256 | | |
257 | | /// MoveToLine - Move the output to the source line specified by the location |
258 | | /// object. We can do this by emitting some number of \n's, or be emitting a |
259 | | /// #line directive. This returns false if already at the specified line, true |
260 | | /// if some newlines were emitted. |
261 | | bool PrintPPOutputPPCallbacks::MoveToLine(unsigned LineNo, |
262 | 48.8k | bool RequireStartOfLine) { |
263 | | // If it is required to start a new line or finish the current, insert |
264 | | // vertical whitespace now and take it into account when moving to the |
265 | | // expected line. |
266 | 48.8k | bool StartedNewLine = false; |
267 | 48.8k | if ((RequireStartOfLine && EmittedTokensOnThisLine17.7k ) || |
268 | 48.8k | EmittedDirectiveOnThisLine32.4k ) { |
269 | 17.7k | OS << '\n'; |
270 | 17.7k | StartedNewLine = true; |
271 | 17.7k | CurLine += 1; |
272 | 17.7k | EmittedTokensOnThisLine = false; |
273 | 17.7k | EmittedDirectiveOnThisLine = false; |
274 | 17.7k | } |
275 | | |
276 | | // If this line is "close enough" to the original line, just print newlines, |
277 | | // otherwise print a #line directive. |
278 | 48.8k | if (CurLine == LineNo) { |
279 | | // Nothing to do if we are already on the correct line. |
280 | 31.0k | } else if (MinimizeWhitespace && DisableLineMarkers90 ) { |
281 | | // With -E -P -fminimize-whitespace, don't emit anything if not necessary. |
282 | 30.9k | } else if (!StartedNewLine && LineNo - CurLine == 130.5k ) { |
283 | | // Printing a single line has priority over printing a #line directive, even |
284 | | // when minimizing whitespace which otherwise would print #line directives |
285 | | // for every single line. |
286 | 23.4k | OS << '\n'; |
287 | 23.4k | StartedNewLine = true; |
288 | 23.4k | } else if (7.57k !DisableLineMarkers7.57k ) { |
289 | 7.42k | if (LineNo - CurLine <= 8) { |
290 | 5.93k | const char *NewLines = "\n\n\n\n\n\n\n\n"; |
291 | 5.93k | OS.write(NewLines, LineNo - CurLine); |
292 | 5.93k | } else { |
293 | | // Emit a #line or line marker. |
294 | 1.49k | WriteLineInfo(LineNo, nullptr, 0); |
295 | 1.49k | } |
296 | 7.42k | StartedNewLine = true; |
297 | 7.42k | } else if (147 EmittedTokensOnThisLine147 ) { |
298 | | // If we are not on the correct line and don't need to be line-correct, |
299 | | // at least ensure we start on a new line. |
300 | 103 | OS << '\n'; |
301 | 103 | StartedNewLine = true; |
302 | 103 | } |
303 | | |
304 | 48.8k | if (StartedNewLine) { |
305 | 48.2k | EmittedTokensOnThisLine = false; |
306 | 48.2k | EmittedDirectiveOnThisLine = false; |
307 | 48.2k | } |
308 | | |
309 | 48.8k | CurLine = LineNo; |
310 | 48.8k | return StartedNewLine; |
311 | 48.8k | } |
312 | | |
313 | 6.08k | void PrintPPOutputPPCallbacks::startNewLineIfNeeded() { |
314 | 6.08k | if (EmittedTokensOnThisLine || EmittedDirectiveOnThisLine5.21k ) { |
315 | 895 | OS << '\n'; |
316 | 895 | EmittedTokensOnThisLine = false; |
317 | 895 | EmittedDirectiveOnThisLine = false; |
318 | 895 | } |
319 | 6.08k | } |
320 | | |
321 | | /// FileChanged - Whenever the preprocessor enters or exits a #include file |
322 | | /// it invokes this handler. Update our conception of the current source |
323 | | /// position. |
324 | | void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc, |
325 | | FileChangeReason Reason, |
326 | | SrcMgr::CharacteristicKind NewFileType, |
327 | 4.57k | FileID PrevFID) { |
328 | | // Unless we are exiting a #include, make sure to skip ahead to the line the |
329 | | // #include directive was at. |
330 | 4.57k | SourceManager &SourceMgr = SM; |
331 | | |
332 | 4.57k | PresumedLoc UserLoc = SourceMgr.getPresumedLoc(Loc); |
333 | 4.57k | if (UserLoc.isInvalid()) |
334 | 0 | return; |
335 | | |
336 | 4.57k | unsigned NewLine = UserLoc.getLine(); |
337 | | |
338 | 4.57k | if (Reason == PPCallbacks::EnterFile) { |
339 | 2.23k | SourceLocation IncludeLoc = UserLoc.getIncludeLoc(); |
340 | 2.23k | if (IncludeLoc.isValid()) |
341 | 1.06k | MoveToLine(IncludeLoc, /*RequireStartOfLine=*/false); |
342 | 2.34k | } else if (Reason == PPCallbacks::SystemHeaderPragma) { |
343 | | // GCC emits the # directive for this directive on the line AFTER the |
344 | | // directive and emits a bunch of spaces that aren't needed. This is because |
345 | | // otherwise we will emit a line marker for THIS line, which requires an |
346 | | // extra blank line after the directive to avoid making all following lines |
347 | | // off by one. We can do better by simply incrementing NewLine here. |
348 | 2 | NewLine += 1; |
349 | 2 | } |
350 | | |
351 | 4.57k | CurLine = NewLine; |
352 | | |
353 | 4.57k | CurFilename.clear(); |
354 | 4.57k | CurFilename += UserLoc.getFilename(); |
355 | 4.57k | FileType = NewFileType; |
356 | | |
357 | 4.57k | if (DisableLineMarkers) { |
358 | 203 | if (!MinimizeWhitespace) |
359 | 145 | startNewLineIfNeeded(); |
360 | 203 | return; |
361 | 203 | } |
362 | | |
363 | 4.37k | if (!Initialized) { |
364 | 554 | WriteLineInfo(CurLine); |
365 | 554 | Initialized = true; |
366 | 554 | } |
367 | | |
368 | | // Do not emit an enter marker for the main file (which we expect is the first |
369 | | // entered file). This matches gcc, and improves compatibility with some tools |
370 | | // which track the # line markers as a way to determine when the preprocessed |
371 | | // output is in the context of the main file. |
372 | 4.37k | if (Reason == PPCallbacks::EnterFile && !IsFirstFileEntered2.13k ) { |
373 | 554 | IsFirstFileEntered = true; |
374 | 554 | return; |
375 | 554 | } |
376 | | |
377 | 3.82k | switch (Reason) { |
378 | 1.57k | case PPCallbacks::EnterFile: |
379 | 1.57k | WriteLineInfo(CurLine, " 1", 2); |
380 | 1.57k | break; |
381 | 1.57k | case PPCallbacks::ExitFile: |
382 | 1.57k | WriteLineInfo(CurLine, " 2", 2); |
383 | 1.57k | break; |
384 | 2 | case PPCallbacks::SystemHeaderPragma: |
385 | 668 | case PPCallbacks::RenameFile: |
386 | 668 | WriteLineInfo(CurLine); |
387 | 668 | break; |
388 | 3.82k | } |
389 | 3.82k | } |
390 | | |
391 | | void PrintPPOutputPPCallbacks::InclusionDirective( |
392 | | SourceLocation HashLoc, |
393 | | const Token &IncludeTok, |
394 | | StringRef FileName, |
395 | | bool IsAngled, |
396 | | CharSourceRange FilenameRange, |
397 | | Optional<FileEntryRef> File, |
398 | | StringRef SearchPath, |
399 | | StringRef RelativePath, |
400 | | const Module *Imported, |
401 | 656 | SrcMgr::CharacteristicKind FileType) { |
402 | | // In -dI mode, dump #include directives prior to dumping their content or |
403 | | // interpretation. |
404 | 656 | if (DumpIncludeDirectives) { |
405 | 5 | MoveToLine(HashLoc, /*RequireStartOfLine=*/true); |
406 | 5 | const std::string TokenText = PP.getSpelling(IncludeTok); |
407 | 5 | assert(!TokenText.empty()); |
408 | 0 | OS << "#" << TokenText << " " |
409 | 5 | << (IsAngled ? '<'1 : '"'4 ) << FileName << (IsAngled ? '>'1 : '"'4 ) |
410 | 5 | << " /* clang -E -dI */"; |
411 | 5 | setEmittedDirectiveOnThisLine(); |
412 | 5 | } |
413 | | |
414 | | // When preprocessing, turn implicit imports into module import pragmas. |
415 | 656 | if (Imported) { |
416 | 43 | switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) { |
417 | 31 | case tok::pp_include: |
418 | 43 | case tok::pp_import: |
419 | 43 | case tok::pp_include_next: |
420 | 43 | MoveToLine(HashLoc, /*RequireStartOfLine=*/true); |
421 | 43 | OS << "#pragma clang module import " << Imported->getFullModuleName(true) |
422 | 43 | << " /* clang -E: implicit import for " |
423 | 43 | << "#" << PP.getSpelling(IncludeTok) << " " |
424 | 43 | << (IsAngled ? '<'10 : '"'33 ) << FileName << (IsAngled ? '>'10 : '"'33 ) |
425 | 43 | << " */"; |
426 | 43 | setEmittedDirectiveOnThisLine(); |
427 | 43 | break; |
428 | | |
429 | 0 | case tok::pp___include_macros: |
430 | | // #__include_macros has no effect on a user of a preprocessed source |
431 | | // file; the only effect is on preprocessing. |
432 | | // |
433 | | // FIXME: That's not *quite* true: it causes the module in question to |
434 | | // be loaded, which can affect downstream diagnostics. |
435 | 0 | break; |
436 | | |
437 | 0 | default: |
438 | 0 | llvm_unreachable("unknown include directive kind"); |
439 | 0 | break; |
440 | 43 | } |
441 | 43 | } |
442 | 656 | } |
443 | | |
444 | | /// Handle entering the scope of a module during a module compilation. |
445 | 37 | void PrintPPOutputPPCallbacks::BeginModule(const Module *M) { |
446 | 37 | startNewLineIfNeeded(); |
447 | 37 | OS << "#pragma clang module begin " << M->getFullModuleName(true); |
448 | 37 | setEmittedDirectiveOnThisLine(); |
449 | 37 | } |
450 | | |
451 | | /// Handle leaving the scope of a module during a module compilation. |
452 | 37 | void PrintPPOutputPPCallbacks::EndModule(const Module *M) { |
453 | 37 | startNewLineIfNeeded(); |
454 | 37 | OS << "#pragma clang module end /*" << M->getFullModuleName(true) << "*/"; |
455 | 37 | setEmittedDirectiveOnThisLine(); |
456 | 37 | } |
457 | | |
458 | | /// Ident - Handle #ident directives when read by the preprocessor. |
459 | | /// |
460 | 0 | void PrintPPOutputPPCallbacks::Ident(SourceLocation Loc, StringRef S) { |
461 | 0 | MoveToLine(Loc, /*RequireStartOfLine=*/true); |
462 | |
|
463 | 0 | OS.write("#ident ", strlen("#ident ")); |
464 | 0 | OS.write(S.begin(), S.size()); |
465 | 0 | setEmittedTokensOnThisLine(); |
466 | 0 | } |
467 | | |
468 | | /// MacroDefined - This hook is called whenever a macro definition is seen. |
469 | | void PrintPPOutputPPCallbacks::MacroDefined(const Token &MacroNameTok, |
470 | 522k | const MacroDirective *MD) { |
471 | 522k | const MacroInfo *MI = MD->getMacroInfo(); |
472 | | // Print out macro definitions in -dD mode and when we have -fdirectives-only |
473 | | // for C++20 header units. |
474 | 522k | if ((!DumpDefines && !DirectivesOnly521k ) || |
475 | | // Ignore __FILE__ etc. |
476 | 522k | MI->isBuiltinMacro()1.50k ) |
477 | 521k | return; |
478 | | |
479 | 1.50k | SourceLocation DefLoc = MI->getDefinitionLoc(); |
480 | 1.50k | if (DirectivesOnly && !MI->isUsed()417 ) { |
481 | 417 | SourceManager &SM = PP.getSourceManager(); |
482 | 417 | if (SM.isWrittenInBuiltinFile(DefLoc) || |
483 | 417 | SM.isWrittenInCommandLineFile(DefLoc)3 ) |
484 | 414 | return; |
485 | 417 | } |
486 | 1.09k | MoveToLine(DefLoc, /*RequireStartOfLine=*/true); |
487 | 1.09k | PrintMacroDefinition(*MacroNameTok.getIdentifierInfo(), *MI, PP, OS); |
488 | 1.09k | setEmittedDirectiveOnThisLine(); |
489 | 1.09k | } |
490 | | |
491 | | void PrintPPOutputPPCallbacks::MacroUndefined(const Token &MacroNameTok, |
492 | | const MacroDefinition &MD, |
493 | 248 | const MacroDirective *Undef) { |
494 | | // Print out macro definitions in -dD mode and when we have -fdirectives-only |
495 | | // for C++20 header units. |
496 | 248 | if (!DumpDefines && !DirectivesOnly247 ) |
497 | 246 | return; |
498 | | |
499 | 2 | MoveToLine(MacroNameTok.getLocation(), /*RequireStartOfLine=*/true); |
500 | 2 | OS << "#undef " << MacroNameTok.getIdentifierInfo()->getName(); |
501 | 2 | setEmittedDirectiveOnThisLine(); |
502 | 2 | } |
503 | | |
504 | 7 | static void outputPrintable(raw_ostream &OS, StringRef Str) { |
505 | 43 | for (unsigned char Char : Str) { |
506 | 43 | if (isPrintable(Char) && Char != '\\'41 && Char != '"'39 ) |
507 | 33 | OS << (char)Char; |
508 | 10 | else // Output anything hard as an octal escape. |
509 | 10 | OS << '\\' |
510 | 10 | << (char)('0' + ((Char >> 6) & 7)) |
511 | 10 | << (char)('0' + ((Char >> 3) & 7)) |
512 | 10 | << (char)('0' + ((Char >> 0) & 7)); |
513 | 43 | } |
514 | 7 | } |
515 | | |
516 | | void PrintPPOutputPPCallbacks::PragmaMessage(SourceLocation Loc, |
517 | | StringRef Namespace, |
518 | | PragmaMessageKind Kind, |
519 | 7 | StringRef Str) { |
520 | 7 | MoveToLine(Loc, /*RequireStartOfLine=*/true); |
521 | 7 | OS << "#pragma "; |
522 | 7 | if (!Namespace.empty()) |
523 | 4 | OS << Namespace << ' '; |
524 | 7 | switch (Kind) { |
525 | 3 | case PMK_Message: |
526 | 3 | OS << "message(\""; |
527 | 3 | break; |
528 | 2 | case PMK_Warning: |
529 | 2 | OS << "warning \""; |
530 | 2 | break; |
531 | 2 | case PMK_Error: |
532 | 2 | OS << "error \""; |
533 | 2 | break; |
534 | 7 | } |
535 | | |
536 | 7 | outputPrintable(OS, Str); |
537 | 7 | OS << '"'; |
538 | 7 | if (Kind == PMK_Message) |
539 | 3 | OS << ')'; |
540 | 7 | setEmittedDirectiveOnThisLine(); |
541 | 7 | } |
542 | | |
543 | | void PrintPPOutputPPCallbacks::PragmaDebug(SourceLocation Loc, |
544 | 8 | StringRef DebugType) { |
545 | 8 | MoveToLine(Loc, /*RequireStartOfLine=*/true); |
546 | | |
547 | 8 | OS << "#pragma clang __debug "; |
548 | 8 | OS << DebugType; |
549 | | |
550 | 8 | setEmittedDirectiveOnThisLine(); |
551 | 8 | } |
552 | | |
553 | | void PrintPPOutputPPCallbacks:: |
554 | 15 | PragmaDiagnosticPush(SourceLocation Loc, StringRef Namespace) { |
555 | 15 | MoveToLine(Loc, /*RequireStartOfLine=*/true); |
556 | 15 | OS << "#pragma " << Namespace << " diagnostic push"; |
557 | 15 | setEmittedDirectiveOnThisLine(); |
558 | 15 | } |
559 | | |
560 | | void PrintPPOutputPPCallbacks:: |
561 | 15 | PragmaDiagnosticPop(SourceLocation Loc, StringRef Namespace) { |
562 | 15 | MoveToLine(Loc, /*RequireStartOfLine=*/true); |
563 | 15 | OS << "#pragma " << Namespace << " diagnostic pop"; |
564 | 15 | setEmittedDirectiveOnThisLine(); |
565 | 15 | } |
566 | | |
567 | | void PrintPPOutputPPCallbacks::PragmaDiagnostic(SourceLocation Loc, |
568 | | StringRef Namespace, |
569 | | diag::Severity Map, |
570 | 23 | StringRef Str) { |
571 | 23 | MoveToLine(Loc, /*RequireStartOfLine=*/true); |
572 | 23 | OS << "#pragma " << Namespace << " diagnostic "; |
573 | 23 | switch (Map) { |
574 | 0 | case diag::Severity::Remark: |
575 | 0 | OS << "remark"; |
576 | 0 | break; |
577 | 5 | case diag::Severity::Warning: |
578 | 5 | OS << "warning"; |
579 | 5 | break; |
580 | 3 | case diag::Severity::Error: |
581 | 3 | OS << "error"; |
582 | 3 | break; |
583 | 13 | case diag::Severity::Ignored: |
584 | 13 | OS << "ignored"; |
585 | 13 | break; |
586 | 2 | case diag::Severity::Fatal: |
587 | 2 | OS << "fatal"; |
588 | 2 | break; |
589 | 23 | } |
590 | 23 | OS << " \"" << Str << '"'; |
591 | 23 | setEmittedDirectiveOnThisLine(); |
592 | 23 | } |
593 | | |
594 | | void PrintPPOutputPPCallbacks::PragmaWarning(SourceLocation Loc, |
595 | | PragmaWarningSpecifier WarningSpec, |
596 | 15 | ArrayRef<int> Ids) { |
597 | 15 | MoveToLine(Loc, /*RequireStartOfLine=*/true); |
598 | | |
599 | 15 | OS << "#pragma warning("; |
600 | 15 | switch(WarningSpec) { |
601 | 1 | case PWS_Default: OS << "default"; break; |
602 | 5 | case PWS_Disable: OS << "disable"; break; |
603 | 2 | case PWS_Error: OS << "error"; break; |
604 | 1 | case PWS_Once: OS << "once"; break; |
605 | 2 | case PWS_Suppress: OS << "suppress"; break; |
606 | 1 | case PWS_Level1: OS << '1'; break; |
607 | 1 | case PWS_Level2: OS << '2'; break; |
608 | 1 | case PWS_Level3: OS << '3'; break; |
609 | 1 | case PWS_Level4: OS << '4'; break; |
610 | 15 | } |
611 | 15 | OS << ':'; |
612 | | |
613 | 39 | for (ArrayRef<int>::iterator I = Ids.begin(), E = Ids.end(); I != E; ++I24 ) |
614 | 24 | OS << ' ' << *I; |
615 | 15 | OS << ')'; |
616 | 15 | setEmittedDirectiveOnThisLine(); |
617 | 15 | } |
618 | | |
619 | | void PrintPPOutputPPCallbacks::PragmaWarningPush(SourceLocation Loc, |
620 | 17 | int Level) { |
621 | 17 | MoveToLine(Loc, /*RequireStartOfLine=*/true); |
622 | 17 | OS << "#pragma warning(push"; |
623 | 17 | if (Level >= 0) |
624 | 9 | OS << ", " << Level; |
625 | 17 | OS << ')'; |
626 | 17 | setEmittedDirectiveOnThisLine(); |
627 | 17 | } |
628 | | |
629 | 6 | void PrintPPOutputPPCallbacks::PragmaWarningPop(SourceLocation Loc) { |
630 | 6 | MoveToLine(Loc, /*RequireStartOfLine=*/true); |
631 | 6 | OS << "#pragma warning(pop)"; |
632 | 6 | setEmittedDirectiveOnThisLine(); |
633 | 6 | } |
634 | | |
635 | | void PrintPPOutputPPCallbacks::PragmaExecCharsetPush(SourceLocation Loc, |
636 | 4 | StringRef Str) { |
637 | 4 | MoveToLine(Loc, /*RequireStartOfLine=*/true); |
638 | 4 | OS << "#pragma character_execution_set(push"; |
639 | 4 | if (!Str.empty()) |
640 | 4 | OS << ", " << Str; |
641 | 4 | OS << ')'; |
642 | 4 | setEmittedDirectiveOnThisLine(); |
643 | 4 | } |
644 | | |
645 | 3 | void PrintPPOutputPPCallbacks::PragmaExecCharsetPop(SourceLocation Loc) { |
646 | 3 | MoveToLine(Loc, /*RequireStartOfLine=*/true); |
647 | 3 | OS << "#pragma character_execution_set(pop)"; |
648 | 3 | setEmittedDirectiveOnThisLine(); |
649 | 3 | } |
650 | | |
651 | | void PrintPPOutputPPCallbacks:: |
652 | 5 | PragmaAssumeNonNullBegin(SourceLocation Loc) { |
653 | 5 | MoveToLine(Loc, /*RequireStartOfLine=*/true); |
654 | 5 | OS << "#pragma clang assume_nonnull begin"; |
655 | 5 | setEmittedDirectiveOnThisLine(); |
656 | 5 | } |
657 | | |
658 | | void PrintPPOutputPPCallbacks:: |
659 | 5 | PragmaAssumeNonNullEnd(SourceLocation Loc) { |
660 | 5 | MoveToLine(Loc, /*RequireStartOfLine=*/true); |
661 | 5 | OS << "#pragma clang assume_nonnull end"; |
662 | 5 | setEmittedDirectiveOnThisLine(); |
663 | 5 | } |
664 | | |
665 | | void PrintPPOutputPPCallbacks::HandleWhitespaceBeforeTok(const Token &Tok, |
666 | | bool RequireSpace, |
667 | 272k | bool RequireSameLine) { |
668 | | // These tokens are not expanded to anything and don't need whitespace before |
669 | | // them. |
670 | 272k | if (Tok.is(tok::eof) || |
671 | 272k | (271k Tok.isAnnotation()271k && !Tok.is(tok::annot_header_unit)135 && |
672 | 271k | !Tok.is(tok::annot_module_begin)128 && !Tok.is(tok::annot_module_end)91 )) |
673 | 638 | return; |
674 | | |
675 | | // EmittedDirectiveOnThisLine takes priority over RequireSameLine. |
676 | 271k | if ((!RequireSameLine || EmittedDirectiveOnThisLine225k ) && |
677 | 271k | MoveToLine(Tok, /*RequireStartOfLine=*/EmittedDirectiveOnThisLine)46.4k ) { |
678 | 46.2k | if (MinimizeWhitespace) { |
679 | | // Avoid interpreting hash as a directive under -fpreprocessed. |
680 | 125 | if (Tok.is(tok::hash)) |
681 | 4 | OS << ' '; |
682 | 46.1k | } else { |
683 | | // Print out space characters so that the first token on a line is |
684 | | // indented for easy reading. |
685 | 46.1k | unsigned ColNo = SM.getExpansionColumnNumber(Tok.getLocation()); |
686 | | |
687 | | // The first token on a line can have a column number of 1, yet still |
688 | | // expect leading white space, if a macro expansion in column 1 starts |
689 | | // with an empty macro argument, or an empty nested macro expansion. In |
690 | | // this case, move the token to column 2. |
691 | 46.1k | if (ColNo == 1 && Tok.hasLeadingSpace()34.9k ) |
692 | 2 | ColNo = 2; |
693 | | |
694 | | // This hack prevents stuff like: |
695 | | // #define HASH # |
696 | | // HASH define foo bar |
697 | | // From having the # character end up at column 1, which makes it so it |
698 | | // is not handled as a #define next time through the preprocessor if in |
699 | | // -fpreprocessed mode. |
700 | 46.1k | if (ColNo <= 1 && Tok.is(tok::hash)34.9k ) |
701 | 15 | OS << ' '; |
702 | | |
703 | | // Otherwise, indent the appropriate number of spaces. |
704 | 239k | for (; ColNo > 1; --ColNo193k ) |
705 | 193k | OS << ' '; |
706 | 46.1k | } |
707 | 225k | } else { |
708 | | // Insert whitespace between the previous and next token if either |
709 | | // - The caller requires it |
710 | | // - The input had whitespace between them and we are not in |
711 | | // whitespace-minimization mode |
712 | | // - The whitespace is necessary to keep the tokens apart and there is not |
713 | | // already a newline between them |
714 | 225k | if (RequireSpace || (225k !MinimizeWhitespace225k && Tok.hasLeadingSpace()224k ) || |
715 | 225k | (155k (155k EmittedTokensOnThisLine155k || EmittedDirectiveOnThisLine105 ) && |
716 | 155k | AvoidConcat(PrevPrevTok, PrevTok, Tok)155k )) |
717 | 70.2k | OS << ' '; |
718 | 225k | } |
719 | | |
720 | 271k | PrevPrevTok = PrevTok; |
721 | 271k | PrevTok = Tok; |
722 | 271k | } |
723 | | |
724 | | void PrintPPOutputPPCallbacks::HandleNewlinesInToken(const char *TokStr, |
725 | 16.9k | unsigned Len) { |
726 | 16.9k | unsigned NumNewlines = 0; |
727 | 752k | for (; Len; --Len, ++TokStr735k ) { |
728 | 735k | if (*TokStr != '\n' && |
729 | 735k | *TokStr != '\r'734k ) |
730 | 734k | continue; |
731 | | |
732 | 1.19k | ++NumNewlines; |
733 | | |
734 | | // If we have \n\r or \r\n, skip both and count as one line. |
735 | 1.19k | if (Len != 1 && |
736 | 1.19k | (1.08k TokStr[1] == '\n'1.08k || TokStr[1] == '\r'1.02k ) && |
737 | 1.19k | TokStr[0] != TokStr[1]56 ) { |
738 | 0 | ++TokStr; |
739 | 0 | --Len; |
740 | 0 | } |
741 | 1.19k | } |
742 | | |
743 | 16.9k | if (NumNewlines == 0) return16.6k ; |
744 | | |
745 | 281 | CurLine += NumNewlines; |
746 | 281 | } |
747 | | |
748 | | |
749 | | namespace { |
750 | | struct UnknownPragmaHandler : public PragmaHandler { |
751 | | const char *Prefix; |
752 | | PrintPPOutputPPCallbacks *Callbacks; |
753 | | |
754 | | // Set to true if tokens should be expanded |
755 | | bool ShouldExpandTokens; |
756 | | |
757 | | UnknownPragmaHandler(const char *prefix, PrintPPOutputPPCallbacks *callbacks, |
758 | | bool RequireTokenExpansion) |
759 | | : Prefix(prefix), Callbacks(callbacks), |
760 | 2.33k | ShouldExpandTokens(RequireTokenExpansion) {} |
761 | | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
762 | 102 | Token &PragmaTok) override { |
763 | | // Figure out what line we went to and insert the appropriate number of |
764 | | // newline characters. |
765 | 102 | Callbacks->MoveToLine(PragmaTok.getLocation(), /*RequireStartOfLine=*/true); |
766 | 102 | Callbacks->OS.write(Prefix, strlen(Prefix)); |
767 | 102 | Callbacks->setEmittedTokensOnThisLine(); |
768 | | |
769 | 102 | if (ShouldExpandTokens) { |
770 | | // The first token does not have expanded macros. Expand them, if |
771 | | // required. |
772 | 77 | auto Toks = std::make_unique<Token[]>(1); |
773 | 77 | Toks[0] = PragmaTok; |
774 | 77 | PP.EnterTokenStream(std::move(Toks), /*NumToks=*/1, |
775 | 77 | /*DisableMacroExpansion=*/false, |
776 | 77 | /*IsReinject=*/false); |
777 | 77 | PP.Lex(PragmaTok); |
778 | 77 | } |
779 | | |
780 | | // Read and print all of the pragma tokens. |
781 | 102 | bool IsFirst = true; |
782 | 532 | while (PragmaTok.isNot(tok::eod)) { |
783 | 430 | Callbacks->HandleWhitespaceBeforeTok(PragmaTok, /*RequireSpace=*/IsFirst, |
784 | 430 | /*RequireSameLine=*/true); |
785 | 430 | IsFirst = false; |
786 | 430 | std::string TokSpell = PP.getSpelling(PragmaTok); |
787 | 430 | Callbacks->OS.write(&TokSpell[0], TokSpell.size()); |
788 | 430 | Callbacks->setEmittedTokensOnThisLine(); |
789 | | |
790 | 430 | if (ShouldExpandTokens) |
791 | 363 | PP.Lex(PragmaTok); |
792 | 67 | else |
793 | 67 | PP.LexUnexpandedToken(PragmaTok); |
794 | 430 | } |
795 | 102 | Callbacks->setEmittedDirectiveOnThisLine(); |
796 | 102 | } |
797 | | }; |
798 | | } // end anonymous namespace |
799 | | |
800 | | |
801 | | static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok, |
802 | | PrintPPOutputPPCallbacks *Callbacks, |
803 | 584 | raw_ostream &OS) { |
804 | 584 | bool DropComments = PP.getLangOpts().TraditionalCPP && |
805 | 584 | !PP.getCommentRetentionState()3 ; |
806 | | |
807 | 584 | bool IsStartOfLine = false; |
808 | 584 | char Buffer[256]; |
809 | 271k | while (true) { |
810 | | // Two lines joined with line continuation ('\' as last character on the |
811 | | // line) must be emitted as one line even though Tok.getLine() returns two |
812 | | // different values. In this situation Tok.isAtStartOfLine() is false even |
813 | | // though it may be the first token on the lexical line. When |
814 | | // dropping/skipping a token that is at the start of a line, propagate the |
815 | | // start-of-line-ness to the next token to not append it to the previous |
816 | | // line. |
817 | 271k | IsStartOfLine = IsStartOfLine || Tok.isAtStartOfLine()271k ; |
818 | | |
819 | 271k | Callbacks->HandleWhitespaceBeforeTok(Tok, /*RequireSpace=*/false, |
820 | 271k | /*RequireSameLine=*/!IsStartOfLine); |
821 | | |
822 | 271k | if (DropComments && Tok.is(tok::comment)275 ) { |
823 | | // Skip comments. Normally the preprocessor does not generate |
824 | | // tok::comment nodes at all when not keeping comments, but under |
825 | | // -traditional-cpp the lexer keeps /all/ whitespace, including comments. |
826 | 50 | PP.Lex(Tok); |
827 | 50 | continue; |
828 | 271k | } else if (Tok.is(tok::eod)) { |
829 | | // Don't print end of directive tokens, since they are typically newlines |
830 | | // that mess up our line tracking. These come from unknown pre-processor |
831 | | // directives or hash-prefixed comments in standalone assembly files. |
832 | 27 | PP.Lex(Tok); |
833 | | // FIXME: The token on the next line after #include should have |
834 | | // Tok.isAtStartOfLine() set. |
835 | 27 | IsStartOfLine = true; |
836 | 27 | continue; |
837 | 271k | } else if (Tok.is(tok::annot_module_include)) { |
838 | | // PrintPPOutputPPCallbacks::InclusionDirective handles producing |
839 | | // appropriate output here. Ignore this token entirely. |
840 | 51 | PP.Lex(Tok); |
841 | 51 | IsStartOfLine = true; |
842 | 51 | continue; |
843 | 271k | } else if (Tok.is(tok::annot_module_begin)) { |
844 | | // FIXME: We retrieve this token after the FileChanged callback, and |
845 | | // retrieve the module_end token before the FileChanged callback, so |
846 | | // we render this within the file and render the module end outside the |
847 | | // file, but this is backwards from the token locations: the module_begin |
848 | | // token is at the include location (outside the file) and the module_end |
849 | | // token is at the EOF location (within the file). |
850 | 37 | Callbacks->BeginModule( |
851 | 37 | reinterpret_cast<Module *>(Tok.getAnnotationValue())); |
852 | 37 | PP.Lex(Tok); |
853 | 37 | IsStartOfLine = true; |
854 | 37 | continue; |
855 | 271k | } else if (Tok.is(tok::annot_module_end)) { |
856 | 37 | Callbacks->EndModule( |
857 | 37 | reinterpret_cast<Module *>(Tok.getAnnotationValue())); |
858 | 37 | PP.Lex(Tok); |
859 | 37 | IsStartOfLine = true; |
860 | 37 | continue; |
861 | 271k | } else if (Tok.is(tok::annot_header_unit)) { |
862 | | // This is a header-name that has been (effectively) converted into a |
863 | | // module-name. |
864 | | // FIXME: The module name could contain non-identifier module name |
865 | | // components. We don't have a good way to round-trip those. |
866 | 7 | Module *M = reinterpret_cast<Module *>(Tok.getAnnotationValue()); |
867 | 7 | std::string Name = M->getFullModuleName(); |
868 | 7 | OS.write(Name.data(), Name.size()); |
869 | 7 | Callbacks->HandleNewlinesInToken(Name.data(), Name.size()); |
870 | 271k | } else if (Tok.isAnnotation()) { |
871 | | // Ignore annotation tokens created by pragmas - the pragmas themselves |
872 | | // will be reproduced in the preprocessed output. |
873 | 3 | PP.Lex(Tok); |
874 | 3 | continue; |
875 | 271k | } else if (IdentifierInfo *II = Tok.getIdentifierInfo()) { |
876 | 103k | OS << II->getName(); |
877 | 168k | } else if (Tok.isLiteral() && !Tok.needsCleaning()13.7k && |
878 | 168k | Tok.getLiteralData()13.7k ) { |
879 | 13.7k | OS.write(Tok.getLiteralData(), Tok.getLength()); |
880 | 154k | } else if (Tok.getLength() < llvm::array_lengthof(Buffer)) { |
881 | 154k | const char *TokPtr = Buffer; |
882 | 154k | unsigned Len = PP.getSpelling(Tok, TokPtr); |
883 | 154k | OS.write(TokPtr, Len); |
884 | | |
885 | | // Tokens that can contain embedded newlines need to adjust our current |
886 | | // line number. |
887 | | // FIXME: The token may end with a newline in which case |
888 | | // setEmittedDirectiveOnThisLine/setEmittedTokensOnThisLine afterwards is |
889 | | // wrong. |
890 | 154k | if (Tok.getKind() == tok::comment || Tok.getKind() == tok::unknown137k ) |
891 | 16.8k | Callbacks->HandleNewlinesInToken(TokPtr, Len); |
892 | 154k | if (Tok.is(tok::comment) && Len >= 216.5k && TokPtr[0] == '/'16.5k && |
893 | 154k | TokPtr[1] == '/'16.5k ) { |
894 | | // It's a line comment; |
895 | | // Ensure that we don't concatenate anything behind it. |
896 | 16.3k | Callbacks->setEmittedDirectiveOnThisLine(); |
897 | 16.3k | } |
898 | 154k | } else { |
899 | 112 | std::string S = PP.getSpelling(Tok); |
900 | 112 | OS.write(S.data(), S.size()); |
901 | | |
902 | | // Tokens that can contain embedded newlines need to adjust our current |
903 | | // line number. |
904 | 112 | if (Tok.getKind() == tok::comment || Tok.getKind() == tok::unknown0 ) |
905 | 112 | Callbacks->HandleNewlinesInToken(S.data(), S.size()); |
906 | 112 | if (Tok.is(tok::comment) && S.size() >= 2 && S[0] == '/' && S[1] == '/') { |
907 | | // It's a line comment; |
908 | | // Ensure that we don't concatenate anything behind it. |
909 | 0 | Callbacks->setEmittedDirectiveOnThisLine(); |
910 | 0 | } |
911 | 112 | } |
912 | 271k | Callbacks->setEmittedTokensOnThisLine(); |
913 | 271k | IsStartOfLine = false; |
914 | | |
915 | 271k | if (Tok.is(tok::eof)) break584 ; |
916 | | |
917 | 271k | PP.Lex(Tok); |
918 | 271k | } |
919 | 584 | } |
920 | | |
921 | | typedef std::pair<const IdentifierInfo *, MacroInfo *> id_macro_pair; |
922 | 6.00M | static int MacroIDCompare(const id_macro_pair *LHS, const id_macro_pair *RHS) { |
923 | 6.00M | return LHS->first->getName().compare(RHS->first->getName()); |
924 | 6.00M | } |
925 | | |
926 | 1.71k | static void DoPrintMacros(Preprocessor &PP, raw_ostream *OS) { |
927 | | // Ignore unknown pragmas. |
928 | 1.71k | PP.IgnorePragmas(); |
929 | | |
930 | | // -dM mode just scans and ignores all tokens in the files, then dumps out |
931 | | // the macro table at the end. |
932 | 1.71k | PP.EnterMainSourceFile(); |
933 | | |
934 | 1.71k | Token Tok; |
935 | 72.5k | do PP.Lex(Tok); |
936 | 72.5k | while (Tok.isNot(tok::eof)); |
937 | | |
938 | 1.71k | SmallVector<id_macro_pair, 128> MacrosByID; |
939 | 1.71k | for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end(); |
940 | 699k | I != E; ++I698k ) { |
941 | 698k | auto *MD = I->second.getLatest(); |
942 | 698k | if (MD && MD->isDefined()) |
943 | 698k | MacrosByID.push_back(id_macro_pair(I->first, MD->getMacroInfo())); |
944 | 698k | } |
945 | 1.71k | llvm::array_pod_sort(MacrosByID.begin(), MacrosByID.end(), MacroIDCompare); |
946 | | |
947 | 699k | for (unsigned i = 0, e = MacrosByID.size(); i != e; ++i698k ) { |
948 | 698k | MacroInfo &MI = *MacrosByID[i].second; |
949 | | // Ignore computed macros like __LINE__ and friends. |
950 | 698k | if (MI.isBuiltinMacro()) continue44.5k ; |
951 | | |
952 | 653k | PrintMacroDefinition(*MacrosByID[i].first, MI, PP, *OS); |
953 | 653k | *OS << '\n'; |
954 | 653k | } |
955 | 1.71k | } |
956 | | |
957 | | /// DoPrintPreprocessedInput - This implements -E mode. |
958 | | /// |
959 | | void clang::DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS, |
960 | 2.29k | const PreprocessorOutputOptions &Opts) { |
961 | | // Show macros with no output is handled specially. |
962 | 2.29k | if (!Opts.ShowCPP) { |
963 | 1.71k | assert(Opts.ShowMacros && "Not yet implemented!"); |
964 | 0 | DoPrintMacros(PP, OS); |
965 | 1.71k | return; |
966 | 1.71k | } |
967 | | |
968 | | // Inform the preprocessor whether we want it to retain comments or not, due |
969 | | // to -C or -CC. |
970 | 584 | PP.SetCommentRetentionState(Opts.ShowComments, Opts.ShowMacroComments); |
971 | | |
972 | 584 | PrintPPOutputPPCallbacks *Callbacks = new PrintPPOutputPPCallbacks( |
973 | 584 | PP, *OS, !Opts.ShowLineMarkers, Opts.ShowMacros, |
974 | 584 | Opts.ShowIncludeDirectives, Opts.UseLineDirectives, |
975 | 584 | Opts.MinimizeWhitespace, Opts.DirectivesOnly); |
976 | | |
977 | | // Expand macros in pragmas with -fms-extensions. The assumption is that |
978 | | // the majority of pragmas in such a file will be Microsoft pragmas. |
979 | | // Remember the handlers we will add so that we can remove them later. |
980 | 584 | std::unique_ptr<UnknownPragmaHandler> MicrosoftExtHandler( |
981 | 584 | new UnknownPragmaHandler( |
982 | 584 | "#pragma", Callbacks, |
983 | 584 | /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt)); |
984 | | |
985 | 584 | std::unique_ptr<UnknownPragmaHandler> GCCHandler(new UnknownPragmaHandler( |
986 | 584 | "#pragma GCC", Callbacks, |
987 | 584 | /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt)); |
988 | | |
989 | 584 | std::unique_ptr<UnknownPragmaHandler> ClangHandler(new UnknownPragmaHandler( |
990 | 584 | "#pragma clang", Callbacks, |
991 | 584 | /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt)); |
992 | | |
993 | 584 | PP.AddPragmaHandler(MicrosoftExtHandler.get()); |
994 | 584 | PP.AddPragmaHandler("GCC", GCCHandler.get()); |
995 | 584 | PP.AddPragmaHandler("clang", ClangHandler.get()); |
996 | | |
997 | | // The tokens after pragma omp need to be expanded. |
998 | | // |
999 | | // OpenMP [2.1, Directive format] |
1000 | | // Preprocessing tokens following the #pragma omp are subject to macro |
1001 | | // replacement. |
1002 | 584 | std::unique_ptr<UnknownPragmaHandler> OpenMPHandler( |
1003 | 584 | new UnknownPragmaHandler("#pragma omp", Callbacks, |
1004 | 584 | /*RequireTokenExpansion=*/true)); |
1005 | 584 | PP.AddPragmaHandler("omp", OpenMPHandler.get()); |
1006 | | |
1007 | 584 | PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callbacks)); |
1008 | | |
1009 | | // After we have configured the preprocessor, enter the main file. |
1010 | 584 | PP.EnterMainSourceFile(); |
1011 | 584 | if (Opts.DirectivesOnly) |
1012 | 1 | PP.SetMacroExpansionOnlyInDirectives(); |
1013 | | |
1014 | | // Consume all of the tokens that come from the predefines buffer. Those |
1015 | | // should not be emitted into the output and are guaranteed to be at the |
1016 | | // start. |
1017 | 584 | const SourceManager &SourceMgr = PP.getSourceManager(); |
1018 | 584 | Token Tok; |
1019 | 584 | do { |
1020 | 584 | PP.Lex(Tok); |
1021 | 584 | if (Tok.is(tok::eof) || !Tok.getLocation().isFileID()484 ) |
1022 | 148 | break; |
1023 | | |
1024 | 436 | PresumedLoc PLoc = SourceMgr.getPresumedLoc(Tok.getLocation()); |
1025 | 436 | if (PLoc.isInvalid()) |
1026 | 0 | break; |
1027 | | |
1028 | 436 | if (strcmp(PLoc.getFilename(), "<built-in>")) |
1029 | 436 | break; |
1030 | 436 | } while (true0 ); |
1031 | | |
1032 | | // Read all the preprocessed tokens, printing them out to the stream. |
1033 | 0 | PrintPreprocessedTokens(PP, Tok, Callbacks, *OS); |
1034 | 584 | *OS << '\n'; |
1035 | | |
1036 | | // Remove the handlers we just added to leave the preprocessor in a sane state |
1037 | | // so that it can be reused (for example by a clang::Parser instance). |
1038 | 584 | PP.RemovePragmaHandler(MicrosoftExtHandler.get()); |
1039 | 584 | PP.RemovePragmaHandler("GCC", GCCHandler.get()); |
1040 | 584 | PP.RemovePragmaHandler("clang", ClangHandler.get()); |
1041 | 584 | PP.RemovePragmaHandler("omp", OpenMPHandler.get()); |
1042 | 584 | } |