1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | #include "clang/Lex/Pragma.h" |
15 | #include "clang/Basic/Diagnostic.h" |
16 | #include "clang/Basic/FileManager.h" |
17 | #include "clang/Basic/IdentifierTable.h" |
18 | #include "clang/Basic/LLVM.h" |
19 | #include "clang/Basic/LangOptions.h" |
20 | #include "clang/Basic/Module.h" |
21 | #include "clang/Basic/SourceLocation.h" |
22 | #include "clang/Basic/SourceManager.h" |
23 | #include "clang/Basic/TokenKinds.h" |
24 | #include "clang/Lex/HeaderSearch.h" |
25 | #include "clang/Lex/LexDiagnostic.h" |
26 | #include "clang/Lex/Lexer.h" |
27 | #include "clang/Lex/LiteralSupport.h" |
28 | #include "clang/Lex/MacroInfo.h" |
29 | #include "clang/Lex/ModuleLoader.h" |
30 | #include "clang/Lex/PPCallbacks.h" |
31 | #include "clang/Lex/Preprocessor.h" |
32 | #include "clang/Lex/PreprocessorLexer.h" |
33 | #include "clang/Lex/Token.h" |
34 | #include "clang/Lex/TokenLexer.h" |
35 | #include "llvm/ADT/ArrayRef.h" |
36 | #include "llvm/ADT/DenseMap.h" |
37 | #include "llvm/ADT/STLExtras.h" |
38 | #include "llvm/ADT/SmallString.h" |
39 | #include "llvm/ADT/SmallVector.h" |
40 | #include "llvm/ADT/StringSwitch.h" |
41 | #include "llvm/ADT/StringRef.h" |
42 | #include "llvm/Support/CrashRecoveryContext.h" |
43 | #include "llvm/Support/Compiler.h" |
44 | #include "llvm/Support/ErrorHandling.h" |
45 | #include <algorithm> |
46 | #include <cassert> |
47 | #include <cstddef> |
48 | #include <cstdint> |
49 | #include <limits> |
50 | #include <string> |
51 | #include <utility> |
52 | #include <vector> |
53 | |
54 | using namespace clang; |
55 | |
56 | |
57 | PragmaHandler::~PragmaHandler() = default; |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | EmptyPragmaHandler::EmptyPragmaHandler(StringRef Name) : PragmaHandler(Name) {} |
64 | |
65 | void EmptyPragmaHandler::HandlePragma(Preprocessor &PP, |
66 | PragmaIntroducerKind Introducer, |
67 | Token &FirstToken) {} |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | PragmaNamespace::~PragmaNamespace() { |
74 | llvm::DeleteContainerSeconds(Handlers); |
75 | } |
76 | |
77 | |
78 | |
79 | |
80 | |
81 | PragmaHandler *PragmaNamespace::FindHandler(StringRef Name, |
82 | bool IgnoreNull) const { |
83 | if (PragmaHandler *Handler = Handlers.lookup(Name)) |
84 | return Handler; |
85 | return IgnoreNull ? nullptr : Handlers.lookup(StringRef()); |
86 | } |
87 | |
88 | void PragmaNamespace::AddPragma(PragmaHandler *Handler) { |
89 | (0) . __assert_fail ("!Handlers.lookup(Handler->getName()) && \"A handler with this name is already registered in this namespace\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/Pragma.cpp", 90, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!Handlers.lookup(Handler->getName()) && |
90 | (0) . __assert_fail ("!Handlers.lookup(Handler->getName()) && \"A handler with this name is already registered in this namespace\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/Pragma.cpp", 90, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "A handler with this name is already registered in this namespace"); |
91 | Handlers[Handler->getName()] = Handler; |
92 | } |
93 | |
94 | void PragmaNamespace::RemovePragmaHandler(PragmaHandler *Handler) { |
95 | (0) . __assert_fail ("Handlers.lookup(Handler->getName()) && \"Handler not registered in this namespace\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/Pragma.cpp", 96, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Handlers.lookup(Handler->getName()) && |
96 | (0) . __assert_fail ("Handlers.lookup(Handler->getName()) && \"Handler not registered in this namespace\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/Pragma.cpp", 96, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "Handler not registered in this namespace"); |
97 | Handlers.erase(Handler->getName()); |
98 | } |
99 | |
100 | void PragmaNamespace::HandlePragma(Preprocessor &PP, |
101 | PragmaIntroducerKind Introducer, |
102 | Token &Tok) { |
103 | |
104 | |
105 | PP.LexUnexpandedToken(Tok); |
106 | |
107 | |
108 | PragmaHandler *Handler |
109 | = FindHandler(Tok.getIdentifierInfo() ? Tok.getIdentifierInfo()->getName() |
110 | : StringRef(), |
111 | ); |
112 | if (!Handler) { |
113 | PP.Diag(Tok, diag::warn_pragma_ignored); |
114 | return; |
115 | } |
116 | |
117 | |
118 | Handler->HandlePragma(PP, Introducer, Tok); |
119 | } |
120 | |
121 | |
122 | |
123 | |
124 | |
125 | |
126 | |
127 | void Preprocessor::HandlePragmaDirective(SourceLocation IntroducerLoc, |
128 | PragmaIntroducerKind Introducer) { |
129 | if (Callbacks) |
130 | Callbacks->PragmaDirective(IntroducerLoc, Introducer); |
131 | |
132 | if (!PragmasEnabled) |
133 | return; |
134 | |
135 | ++NumPragma; |
136 | |
137 | |
138 | Token Tok; |
139 | PragmaHandlers->HandlePragma(*this, Introducer, Tok); |
140 | |
141 | |
142 | if ((CurTokenLexer && CurTokenLexer->isParsingPreprocessorDirective()) |
143 | || (CurPPLexer && CurPPLexer->ParsingPreprocessorDirective)) |
144 | DiscardUntilEndOfDirective(); |
145 | } |
146 | |
147 | namespace { |
148 | |
149 | |
150 | class LexingFor_PragmaRAII { |
151 | Preprocessor &PP; |
152 | bool InMacroArgPreExpansion; |
153 | bool Failed = false; |
154 | Token &OutTok; |
155 | Token PragmaTok; |
156 | |
157 | public: |
158 | LexingFor_PragmaRAII(Preprocessor &PP, bool InMacroArgPreExpansion, |
159 | Token &Tok) |
160 | : PP(PP), InMacroArgPreExpansion(InMacroArgPreExpansion), OutTok(Tok) { |
161 | if (InMacroArgPreExpansion) { |
162 | PragmaTok = OutTok; |
163 | PP.EnableBacktrackAtThisPos(); |
164 | } |
165 | } |
166 | |
167 | ~LexingFor_PragmaRAII() { |
168 | if (InMacroArgPreExpansion) { |
169 | |
170 | |
171 | |
172 | |
173 | |
174 | |
175 | |
176 | |
177 | |
178 | auto CachedTokenRange = PP.LastCachedTokenRange(); |
179 | if (Failed) { |
180 | PP.CommitBacktrackedTokens(); |
181 | } else { |
182 | PP.Backtrack(); |
183 | OutTok = PragmaTok; |
184 | } |
185 | PP.EraseCachedTokens(CachedTokenRange); |
186 | } |
187 | } |
188 | |
189 | void failed() { |
190 | Failed = true; |
191 | } |
192 | }; |
193 | |
194 | } |
195 | |
196 | |
197 | |
198 | |
199 | void Preprocessor::Handle_Pragma(Token &Tok) { |
200 | |
201 | |
202 | |
203 | |
204 | |
205 | |
206 | |
207 | |
208 | |
209 | |
210 | |
211 | LexingFor_PragmaRAII _PragmaLexing(*this, InMacroArgPreExpansion, Tok); |
212 | |
213 | |
214 | SourceLocation PragmaLoc = Tok.getLocation(); |
215 | |
216 | |
217 | Lex(Tok); |
218 | if (Tok.isNot(tok::l_paren)) { |
219 | Diag(PragmaLoc, diag::err__Pragma_malformed); |
220 | return _PragmaLexing.failed(); |
221 | } |
222 | |
223 | |
224 | Lex(Tok); |
225 | if (!tok::isStringLiteral(Tok.getKind())) { |
226 | Diag(PragmaLoc, diag::err__Pragma_malformed); |
227 | |
228 | if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::eof)) |
229 | Lex(Tok); |
230 | while (Tok.isNot(tok::r_paren) && |
231 | !Tok.isAtStartOfLine() && |
232 | Tok.isNot(tok::eof)) |
233 | Lex(Tok); |
234 | if (Tok.is(tok::r_paren)) |
235 | Lex(Tok); |
236 | return _PragmaLexing.failed(); |
237 | } |
238 | |
239 | if (Tok.hasUDSuffix()) { |
240 | Diag(Tok, diag::err_invalid_string_udl); |
241 | |
242 | Lex(Tok); |
243 | if (Tok.is(tok::r_paren)) |
244 | Lex(Tok); |
245 | return _PragmaLexing.failed(); |
246 | } |
247 | |
248 | |
249 | Token StrTok = Tok; |
250 | |
251 | |
252 | Lex(Tok); |
253 | if (Tok.isNot(tok::r_paren)) { |
254 | Diag(PragmaLoc, diag::err__Pragma_malformed); |
255 | return _PragmaLexing.failed(); |
256 | } |
257 | |
258 | if (InMacroArgPreExpansion) |
259 | return; |
260 | |
261 | SourceLocation RParenLoc = Tok.getLocation(); |
262 | std::string StrVal = getSpelling(StrTok); |
263 | |
264 | |
265 | |
266 | |
267 | |
268 | |
269 | if (StrVal[0] == 'L' || StrVal[0] == 'U' || |
270 | (StrVal[0] == 'u' && StrVal[1] != '8')) |
271 | StrVal.erase(StrVal.begin()); |
272 | else if (StrVal[0] == 'u') |
273 | StrVal.erase(StrVal.begin(), StrVal.begin() + 2); |
274 | |
275 | if (StrVal[0] == 'R') { |
276 | |
277 | |
278 | (0) . __assert_fail ("StrVal[1] == '\"' && StrVal[StrVal.size() - 1] == '\"' && \"Invalid raw string token!\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/Pragma.cpp", 279, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(StrVal[1] == '"' && StrVal[StrVal.size() - 1] == '"' && |
279 | (0) . __assert_fail ("StrVal[1] == '\"' && StrVal[StrVal.size() - 1] == '\"' && \"Invalid raw string token!\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/Pragma.cpp", 279, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "Invalid raw string token!"); |
280 | |
281 | |
282 | unsigned NumDChars = 0; |
283 | while (StrVal[2 + NumDChars] != '(') { |
284 | (0) . __assert_fail ("NumDChars < (StrVal.size() - 5) / 2 && \"Invalid raw string token!\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/Pragma.cpp", 285, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(NumDChars < (StrVal.size() - 5) / 2 && |
285 | (0) . __assert_fail ("NumDChars < (StrVal.size() - 5) / 2 && \"Invalid raw string token!\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/Pragma.cpp", 285, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "Invalid raw string token!"); |
286 | ++NumDChars; |
287 | } |
288 | assert(StrVal[StrVal.size() - 2 - NumDChars] == ')'); |
289 | |
290 | |
291 | |
292 | StrVal.erase(0, 2 + NumDChars); |
293 | StrVal.erase(StrVal.size() - 1 - NumDChars); |
294 | } else { |
295 | (0) . __assert_fail ("StrVal[0] == '\"' && StrVal[StrVal.size()-1] == '\"' && \"Invalid string token!\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/Pragma.cpp", 296, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(StrVal[0] == '"' && StrVal[StrVal.size()-1] == '"' && |
296 | (0) . __assert_fail ("StrVal[0] == '\"' && StrVal[StrVal.size()-1] == '\"' && \"Invalid string token!\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/Pragma.cpp", 296, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "Invalid string token!"); |
297 | |
298 | |
299 | unsigned ResultPos = 1; |
300 | for (size_t i = 1, e = StrVal.size() - 1; i != e; ++i) { |
301 | |
302 | if (StrVal[i] == '\\' && i + 1 < e && |
303 | (StrVal[i + 1] == '\\' || StrVal[i + 1] == '"')) |
304 | ++i; |
305 | StrVal[ResultPos++] = StrVal[i]; |
306 | } |
307 | StrVal.erase(StrVal.begin() + ResultPos, StrVal.end() - 1); |
308 | } |
309 | |
310 | |
311 | |
312 | StrVal[0] = ' '; |
313 | |
314 | |
315 | StrVal[StrVal.size()-1] = '\n'; |
316 | |
317 | |
318 | |
319 | Token TmpTok; |
320 | TmpTok.startToken(); |
321 | CreateString(StrVal, TmpTok); |
322 | SourceLocation TokLoc = TmpTok.getLocation(); |
323 | |
324 | |
325 | |
326 | Lexer *TL = Lexer::Create_PragmaLexer(TokLoc, PragmaLoc, RParenLoc, |
327 | StrVal.size(), *this); |
328 | |
329 | EnterSourceFileWithLexer(TL, nullptr); |
330 | |
331 | |
332 | HandlePragmaDirective(PragmaLoc, PIK__Pragma); |
333 | |
334 | |
335 | return Lex(Tok); |
336 | } |
337 | |
338 | |
339 | |
340 | void Preprocessor::HandleMicrosoft__pragma(Token &Tok) { |
341 | |
342 | SourceLocation PragmaLoc = Tok.getLocation(); |
343 | |
344 | |
345 | Lex(Tok); |
346 | if (Tok.isNot(tok::l_paren)) { |
347 | Diag(PragmaLoc, diag::err__Pragma_malformed); |
348 | return; |
349 | } |
350 | |
351 | |
352 | SmallVector<Token, 32> PragmaToks; |
353 | int NumParens = 0; |
354 | Lex(Tok); |
355 | while (Tok.isNot(tok::eof)) { |
356 | PragmaToks.push_back(Tok); |
357 | if (Tok.is(tok::l_paren)) |
358 | NumParens++; |
359 | else if (Tok.is(tok::r_paren) && NumParens-- == 0) |
360 | break; |
361 | Lex(Tok); |
362 | } |
363 | |
364 | if (Tok.is(tok::eof)) { |
365 | Diag(PragmaLoc, diag::err_unterminated___pragma); |
366 | return; |
367 | } |
368 | |
369 | PragmaToks.front().setFlag(Token::LeadingSpace); |
370 | |
371 | |
372 | PragmaToks.back().setKind(tok::eod); |
373 | |
374 | Token *TokArray = new Token[PragmaToks.size()]; |
375 | std::copy(PragmaToks.begin(), PragmaToks.end(), TokArray); |
376 | |
377 | |
378 | EnterTokenStream(TokArray, PragmaToks.size(), true, true); |
379 | |
380 | |
381 | HandlePragmaDirective(PragmaLoc, PIK___pragma); |
382 | |
383 | |
384 | return Lex(Tok); |
385 | } |
386 | |
387 | |
388 | void Preprocessor::HandlePragmaOnce(Token &OnceTok) { |
389 | |
390 | |
391 | |
392 | |
393 | if (isInPrimaryFile() && TUKind != TU_Prefix && !getLangOpts().IsHeaderFile) { |
394 | Diag(OnceTok, diag::pp_pragma_once_in_main_file); |
395 | return; |
396 | } |
397 | |
398 | |
399 | |
400 | HeaderInfo.MarkFileIncludeOnce(getCurrentFileLexer()->getFileEntry()); |
401 | } |
402 | |
403 | void Preprocessor::HandlePragmaMark() { |
404 | (0) . __assert_fail ("CurPPLexer && \"No current lexer?\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/Pragma.cpp", 404, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(CurPPLexer && "No current lexer?"); |
405 | CurLexer->ReadToEndOfLine(); |
406 | } |
407 | |
408 | |
409 | void Preprocessor::HandlePragmaPoison() { |
410 | Token Tok; |
411 | |
412 | while (true) { |
413 | |
414 | |
415 | |
416 | |
417 | |
418 | if (CurPPLexer) CurPPLexer->LexingRawMode = true; |
419 | LexUnexpandedToken(Tok); |
420 | if (CurPPLexer) CurPPLexer->LexingRawMode = false; |
421 | |
422 | |
423 | if (Tok.is(tok::eod)) return; |
424 | |
425 | |
426 | if (Tok.isNot(tok::raw_identifier)) { |
427 | Diag(Tok, diag::err_pp_invalid_poison); |
428 | return; |
429 | } |
430 | |
431 | |
432 | |
433 | IdentifierInfo *II = LookUpIdentifierInfo(Tok); |
434 | |
435 | |
436 | if (II->isPoisoned()) continue; |
437 | |
438 | |
439 | if (isMacroDefined(II)) |
440 | Diag(Tok, diag::pp_poisoning_existing_macro); |
441 | |
442 | |
443 | II->setIsPoisoned(); |
444 | if (II->isFromAST()) |
445 | II->setChangedSinceDeserialization(); |
446 | } |
447 | } |
448 | |
449 | |
450 | |
451 | void Preprocessor::HandlePragmaSystemHeader(Token &) { |
452 | if (isInPrimaryFile()) { |
453 | Diag(SysHeaderTok, diag::pp_pragma_sysheader_in_main_file); |
454 | return; |
455 | } |
456 | |
457 | |
458 | PreprocessorLexer *TheLexer = getCurrentFileLexer(); |
459 | |
460 | |
461 | HeaderInfo.MarkFileSystemHeader(TheLexer->getFileEntry()); |
462 | |
463 | PresumedLoc PLoc = SourceMgr.getPresumedLoc(SysHeaderTok.getLocation()); |
464 | if (PLoc.isInvalid()) |
465 | return; |
466 | |
467 | unsigned FilenameID = SourceMgr.getLineTableFilenameID(PLoc.getFilename()); |
468 | |
469 | |
470 | if (Callbacks) |
471 | Callbacks->FileChanged(SysHeaderTok.getLocation(), |
472 | PPCallbacks::SystemHeaderPragma, SrcMgr::C_System); |
473 | |
474 | |
475 | |
476 | |
477 | SourceMgr.AddLineNote(SysHeaderTok.getLocation(), PLoc.getLine() + 1, |
478 | FilenameID, , , |
479 | SrcMgr::C_System); |
480 | } |
481 | |
482 | |
483 | void Preprocessor::HandlePragmaDependency(Token &DependencyTok) { |
484 | Token FilenameTok; |
485 | if (LexHeaderName(FilenameTok, )) |
486 | return; |
487 | |
488 | |
489 | if (FilenameTok.isNot(tok::header_name)) { |
490 | Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename); |
491 | return; |
492 | } |
493 | |
494 | |
495 | SmallString<128> FilenameBuffer; |
496 | bool Invalid = false; |
497 | StringRef Filename = getSpelling(FilenameTok, FilenameBuffer, &Invalid); |
498 | if (Invalid) |
499 | return; |
500 | |
501 | bool isAngled = |
502 | GetIncludeFilenameSpelling(FilenameTok.getLocation(), Filename); |
503 | |
504 | |
505 | if (Filename.empty()) |
506 | return; |
507 | |
508 | |
509 | const DirectoryLookup *CurDir; |
510 | const FileEntry *File = |
511 | LookupFile(FilenameTok.getLocation(), Filename, isAngled, nullptr, |
512 | nullptr, CurDir, nullptr, nullptr, nullptr, nullptr, nullptr); |
513 | if (!File) { |
514 | if (!SuppressIncludeNotFoundError) |
515 | Diag(FilenameTok, diag::err_pp_file_not_found) << Filename; |
516 | return; |
517 | } |
518 | |
519 | const FileEntry *CurFile = getCurrentFileLexer()->getFileEntry(); |
520 | |
521 | |
522 | if (CurFile && CurFile->getModificationTime() < File->getModificationTime()) { |
523 | |
524 | std::string Message; |
525 | Lex(DependencyTok); |
526 | while (DependencyTok.isNot(tok::eod)) { |
527 | Message += getSpelling(DependencyTok) + " "; |
528 | Lex(DependencyTok); |
529 | } |
530 | |
531 | |
532 | if (!Message.empty()) |
533 | Message.erase(Message.end()-1); |
534 | Diag(FilenameTok, diag::pp_out_of_date_dependency) << Message; |
535 | } |
536 | } |
537 | |
538 | |
539 | |
540 | IdentifierInfo *Preprocessor::ParsePragmaPushOrPopMacro(Token &Tok) { |
541 | |
542 | Token PragmaTok = Tok; |
543 | |
544 | |
545 | Lex(Tok); |
546 | if (Tok.isNot(tok::l_paren)) { |
547 | Diag(PragmaTok.getLocation(), diag::err_pragma_push_pop_macro_malformed) |
548 | << getSpelling(PragmaTok); |
549 | return nullptr; |
550 | } |
551 | |
552 | |
553 | Lex(Tok); |
554 | if (Tok.isNot(tok::string_literal)) { |
555 | Diag(PragmaTok.getLocation(), diag::err_pragma_push_pop_macro_malformed) |
556 | << getSpelling(PragmaTok); |
557 | return nullptr; |
558 | } |
559 | |
560 | if (Tok.hasUDSuffix()) { |
561 | Diag(Tok, diag::err_invalid_string_udl); |
562 | return nullptr; |
563 | } |
564 | |
565 | |
566 | std::string StrVal = getSpelling(Tok); |
567 | |
568 | |
569 | Lex(Tok); |
570 | if (Tok.isNot(tok::r_paren)) { |
571 | Diag(PragmaTok.getLocation(), diag::err_pragma_push_pop_macro_malformed) |
572 | << getSpelling(PragmaTok); |
573 | return nullptr; |
574 | } |
575 | |
576 | (0) . __assert_fail ("StrVal[0] == '\"' && StrVal[StrVal.size()-1] == '\"' && \"Invalid string token!\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/Pragma.cpp", 577, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(StrVal[0] == '"' && StrVal[StrVal.size()-1] == '"' && |
577 | (0) . __assert_fail ("StrVal[0] == '\"' && StrVal[StrVal.size()-1] == '\"' && \"Invalid string token!\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/Pragma.cpp", 577, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "Invalid string token!"); |
578 | |
579 | |
580 | Token MacroTok; |
581 | MacroTok.startToken(); |
582 | MacroTok.setKind(tok::raw_identifier); |
583 | CreateString(StringRef(&StrVal[1], StrVal.size() - 2), MacroTok); |
584 | |
585 | |
586 | return LookUpIdentifierInfo(MacroTok); |
587 | } |
588 | |
589 | |
590 | |
591 | |
592 | |
593 | |
594 | |
595 | void Preprocessor::HandlePragmaPushMacro(Token &PushMacroTok) { |
596 | |
597 | IdentifierInfo *IdentInfo = ParsePragmaPushOrPopMacro(PushMacroTok); |
598 | if (!IdentInfo) return; |
599 | |
600 | |
601 | MacroInfo *MI = getMacroInfo(IdentInfo); |
602 | |
603 | if (MI) { |
604 | |
605 | MI->setIsAllowRedefinitionsWithoutWarning(true); |
606 | } |
607 | |
608 | |
609 | PragmaPushMacroInfo[IdentInfo].push_back(MI); |
610 | } |
611 | |
612 | |
613 | |
614 | |
615 | |
616 | |
617 | |
618 | void Preprocessor::HandlePragmaPopMacro(Token &PopMacroTok) { |
619 | SourceLocation MessageLoc = PopMacroTok.getLocation(); |
620 | |
621 | |
622 | IdentifierInfo *IdentInfo = ParsePragmaPushOrPopMacro(PopMacroTok); |
623 | if (!IdentInfo) return; |
624 | |
625 | |
626 | llvm::DenseMap<IdentifierInfo *, std::vector<MacroInfo *>>::iterator iter = |
627 | PragmaPushMacroInfo.find(IdentInfo); |
628 | if (iter != PragmaPushMacroInfo.end()) { |
629 | |
630 | if (MacroInfo *MI = getMacroInfo(IdentInfo)) { |
631 | if (MI->isWarnIfUnused()) |
632 | WarnUnusedMacroLocs.erase(MI->getDefinitionLoc()); |
633 | appendMacroDirective(IdentInfo, AllocateUndefMacroDirective(MessageLoc)); |
634 | } |
635 | |
636 | |
637 | MacroInfo *MacroToReInstall = iter->second.back(); |
638 | |
639 | if (MacroToReInstall) |
640 | |
641 | appendDefMacroDirective(IdentInfo, MacroToReInstall, MessageLoc); |
642 | |
643 | |
644 | iter->second.pop_back(); |
645 | if (iter->second.empty()) |
646 | PragmaPushMacroInfo.erase(iter); |
647 | } else { |
648 | Diag(MessageLoc, diag::warn_pragma_pop_macro_no_push) |
649 | << IdentInfo->getName(); |
650 | } |
651 | } |
652 | |
653 | void Preprocessor::HandlePragmaIncludeAlias(Token &Tok) { |
654 | |
655 | |
656 | |
657 | |
658 | |
659 | |
660 | Lex(Tok); |
661 | if (Tok.isNot(tok::l_paren)) { |
662 | Diag(Tok, diag::warn_pragma_include_alias_expected) << "("; |
663 | return; |
664 | } |
665 | |
666 | |
667 | Token SourceFilenameTok; |
668 | if (LexHeaderName(SourceFilenameTok)) |
669 | return; |
670 | |
671 | StringRef SourceFileName; |
672 | SmallString<128> FileNameBuffer; |
673 | if (SourceFilenameTok.is(tok::header_name)) { |
674 | SourceFileName = getSpelling(SourceFilenameTok, FileNameBuffer); |
675 | } else { |
676 | Diag(Tok, diag::warn_pragma_include_alias_expected_filename); |
677 | return; |
678 | } |
679 | FileNameBuffer.clear(); |
680 | |
681 | |
682 | Lex(Tok); |
683 | if (Tok.isNot(tok::comma)) { |
684 | Diag(Tok, diag::warn_pragma_include_alias_expected) << ","; |
685 | return; |
686 | } |
687 | |
688 | Token ReplaceFilenameTok; |
689 | if (LexHeaderName(ReplaceFilenameTok)) |
690 | return; |
691 | |
692 | StringRef ReplaceFileName; |
693 | if (ReplaceFilenameTok.is(tok::header_name)) { |
694 | ReplaceFileName = getSpelling(ReplaceFilenameTok, FileNameBuffer); |
695 | } else { |
696 | Diag(Tok, diag::warn_pragma_include_alias_expected_filename); |
697 | return; |
698 | } |
699 | |
700 | |
701 | Lex(Tok); |
702 | if (Tok.isNot(tok::r_paren)) { |
703 | Diag(Tok, diag::warn_pragma_include_alias_expected) << ")"; |
704 | return; |
705 | } |
706 | |
707 | |
708 | |
709 | StringRef OriginalSource = SourceFileName; |
710 | |
711 | bool SourceIsAngled = |
712 | GetIncludeFilenameSpelling(SourceFilenameTok.getLocation(), |
713 | SourceFileName); |
714 | bool ReplaceIsAngled = |
715 | GetIncludeFilenameSpelling(ReplaceFilenameTok.getLocation(), |
716 | ReplaceFileName); |
717 | if (!SourceFileName.empty() && !ReplaceFileName.empty() && |
718 | (SourceIsAngled != ReplaceIsAngled)) { |
719 | unsigned int DiagID; |
720 | if (SourceIsAngled) |
721 | DiagID = diag::warn_pragma_include_alias_mismatch_angle; |
722 | else |
723 | DiagID = diag::warn_pragma_include_alias_mismatch_quote; |
724 | |
725 | Diag(SourceFilenameTok.getLocation(), DiagID) |
726 | << SourceFileName |
727 | << ReplaceFileName; |
728 | |
729 | return; |
730 | } |
731 | |
732 | |
733 | getHeaderSearchInfo().AddIncludeAlias(OriginalSource, ReplaceFileName); |
734 | } |
735 | |
736 | |
737 | |
738 | static bool LexModuleNameComponent( |
739 | Preprocessor &PP, Token &Tok, |
740 | std::pair<IdentifierInfo *, SourceLocation> &ModuleNameComponent, |
741 | bool First) { |
742 | PP.LexUnexpandedToken(Tok); |
743 | if (Tok.is(tok::string_literal) && !Tok.hasUDSuffix()) { |
744 | StringLiteralParser Literal(Tok, PP); |
745 | if (Literal.hadError) |
746 | return true; |
747 | ModuleNameComponent = std::make_pair( |
748 | PP.getIdentifierInfo(Literal.GetString()), Tok.getLocation()); |
749 | } else if (!Tok.isAnnotation() && Tok.getIdentifierInfo()) { |
750 | ModuleNameComponent = |
751 | std::make_pair(Tok.getIdentifierInfo(), Tok.getLocation()); |
752 | } else { |
753 | PP.Diag(Tok.getLocation(), diag::err_pp_expected_module_name) << First; |
754 | return true; |
755 | } |
756 | return false; |
757 | } |
758 | |
759 | static bool LexModuleName( |
760 | Preprocessor &PP, Token &Tok, |
761 | llvm::SmallVectorImpl<std::pair<IdentifierInfo *, SourceLocation>> |
762 | &ModuleName) { |
763 | while (true) { |
764 | std::pair<IdentifierInfo*, SourceLocation> NameComponent; |
765 | if (LexModuleNameComponent(PP, Tok, NameComponent, ModuleName.empty())) |
766 | return true; |
767 | ModuleName.push_back(NameComponent); |
768 | |
769 | PP.LexUnexpandedToken(Tok); |
770 | if (Tok.isNot(tok::period)) |
771 | return false; |
772 | } |
773 | } |
774 | |
775 | void Preprocessor::HandlePragmaModuleBuild(Token &Tok) { |
776 | SourceLocation Loc = Tok.getLocation(); |
777 | |
778 | std::pair<IdentifierInfo *, SourceLocation> ModuleNameLoc; |
779 | if (LexModuleNameComponent(*this, Tok, ModuleNameLoc, true)) |
780 | return; |
781 | IdentifierInfo *ModuleName = ModuleNameLoc.first; |
782 | |
783 | LexUnexpandedToken(Tok); |
784 | if (Tok.isNot(tok::eod)) { |
785 | Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma"; |
786 | DiscardUntilEndOfDirective(); |
787 | } |
788 | |
789 | CurLexer->LexingRawMode = true; |
790 | |
791 | auto TryConsumeIdentifier = [&](StringRef Ident) -> bool { |
792 | if (Tok.getKind() != tok::raw_identifier || |
793 | Tok.getRawIdentifier() != Ident) |
794 | return false; |
795 | CurLexer->Lex(Tok); |
796 | return true; |
797 | }; |
798 | |
799 | |
800 | const char *Start = CurLexer->getBufferLocation(); |
801 | const char *End = nullptr; |
802 | unsigned NestingLevel = 1; |
803 | while (true) { |
804 | End = CurLexer->getBufferLocation(); |
805 | CurLexer->Lex(Tok); |
806 | |
807 | if (Tok.is(tok::eof)) { |
808 | Diag(Loc, diag::err_pp_module_build_missing_end); |
809 | break; |
810 | } |
811 | |
812 | if (Tok.isNot(tok::hash) || !Tok.isAtStartOfLine()) { |
813 | |
814 | continue; |
815 | } |
816 | |
817 | |
818 | |
819 | CurLexer->ParsingPreprocessorDirective = true; |
820 | CurLexer->Lex(Tok); |
821 | if (TryConsumeIdentifier("pragma") && TryConsumeIdentifier("clang") && |
822 | TryConsumeIdentifier("module")) { |
823 | if (TryConsumeIdentifier("build")) |
824 | |
825 | ++NestingLevel; |
826 | else if (TryConsumeIdentifier("endbuild")) { |
827 | |
828 | if (--NestingLevel == 0) |
829 | break; |
830 | } |
831 | |
832 | |
833 | (0) . __assert_fail ("Tok.getKind() != tok..eof && \"missing EOD before EOF\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/Pragma.cpp", 833, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Tok.getKind() != tok::eof && "missing EOD before EOF"); |
834 | } |
835 | } |
836 | |
837 | CurLexer->LexingRawMode = false; |
838 | |
839 | |
840 | (0) . __assert_fail ("CurLexer->getBuffer().begin() <= Start && Start <= CurLexer->getBuffer().end() && CurLexer->getBuffer().begin() <= End && End <= CurLexer->getBuffer().end() && \"module source range not contained within same file buffer\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/Pragma.cpp", 844, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(CurLexer->getBuffer().begin() <= Start && |
841 | (0) . __assert_fail ("CurLexer->getBuffer().begin() <= Start && Start <= CurLexer->getBuffer().end() && CurLexer->getBuffer().begin() <= End && End <= CurLexer->getBuffer().end() && \"module source range not contained within same file buffer\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/Pragma.cpp", 844, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> Start <= CurLexer->getBuffer().end() && |
842 | (0) . __assert_fail ("CurLexer->getBuffer().begin() <= Start && Start <= CurLexer->getBuffer().end() && CurLexer->getBuffer().begin() <= End && End <= CurLexer->getBuffer().end() && \"module source range not contained within same file buffer\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/Pragma.cpp", 844, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> CurLexer->getBuffer().begin() <= End && |
843 | (0) . __assert_fail ("CurLexer->getBuffer().begin() <= Start && Start <= CurLexer->getBuffer().end() && CurLexer->getBuffer().begin() <= End && End <= CurLexer->getBuffer().end() && \"module source range not contained within same file buffer\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/Pragma.cpp", 844, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> End <= CurLexer->getBuffer().end() && |
844 | (0) . __assert_fail ("CurLexer->getBuffer().begin() <= Start && Start <= CurLexer->getBuffer().end() && CurLexer->getBuffer().begin() <= End && End <= CurLexer->getBuffer().end() && \"module source range not contained within same file buffer\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/Pragma.cpp", 844, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "module source range not contained within same file buffer"); |
845 | TheModuleLoader.loadModuleFromSource(Loc, ModuleName->getName(), |
846 | StringRef(Start, End - Start)); |
847 | } |
848 | |
849 | void Preprocessor::HandlePragmaHdrstop(Token &Tok) { |
850 | Lex(Tok); |
851 | if (Tok.is(tok::l_paren)) { |
852 | Diag(Tok.getLocation(), diag::warn_pp_hdrstop_filename_ignored); |
853 | |
854 | std::string FileName; |
855 | if (!LexStringLiteral(Tok, FileName, "pragma hdrstop", false)) |
856 | return; |
857 | |
858 | if (Tok.isNot(tok::r_paren)) { |
859 | Diag(Tok, diag::err_expected) << tok::r_paren; |
860 | return; |
861 | } |
862 | Lex(Tok); |
863 | } |
864 | if (Tok.isNot(tok::eod)) |
865 | Diag(Tok.getLocation(), diag::ext_pp_extra_tokens_at_eol) |
866 | << "pragma hdrstop"; |
867 | |
868 | if (creatingPCHWithPragmaHdrStop() && |
869 | SourceMgr.isInMainFile(Tok.getLocation())) { |
870 | (0) . __assert_fail ("CurLexer && \"no lexer for #pragma hdrstop processing\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/Pragma.cpp", 870, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(CurLexer && "no lexer for #pragma hdrstop processing"); |
871 | Token &Result = Tok; |
872 | Result.startToken(); |
873 | CurLexer->FormTokenWithChars(Result, CurLexer->BufferEnd, tok::eof); |
874 | CurLexer->cutOffLexing(); |
875 | } |
876 | if (usingPCHWithPragmaHdrStop()) |
877 | SkippingUntilPragmaHdrStop = false; |
878 | } |
879 | |
880 | |
881 | |
882 | |
883 | void Preprocessor::AddPragmaHandler(StringRef Namespace, |
884 | PragmaHandler *Handler) { |
885 | PragmaNamespace *InsertNS = PragmaHandlers.get(); |
886 | |
887 | |
888 | if (!Namespace.empty()) { |
889 | |
890 | |
891 | |
892 | if (PragmaHandler *Existing = PragmaHandlers->FindHandler(Namespace)) { |
893 | InsertNS = Existing->getIfNamespace(); |
894 | (0) . __assert_fail ("InsertNS != nullptr && \"Cannot have a pragma namespace and pragma\" \" handler with the same name!\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/Pragma.cpp", 895, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(InsertNS != nullptr && "Cannot have a pragma namespace and pragma" |
895 | (0) . __assert_fail ("InsertNS != nullptr && \"Cannot have a pragma namespace and pragma\" \" handler with the same name!\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/Pragma.cpp", 895, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> " handler with the same name!"); |
896 | } else { |
897 | |
898 | |
899 | InsertNS = new PragmaNamespace(Namespace); |
900 | PragmaHandlers->AddPragma(InsertNS); |
901 | } |
902 | } |
903 | |
904 | |
905 | (0) . __assert_fail ("!InsertNS->FindHandler(Handler->getName()) && \"Pragma handler already exists for this identifier!\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/Pragma.cpp", 906, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!InsertNS->FindHandler(Handler->getName()) && |
906 | (0) . __assert_fail ("!InsertNS->FindHandler(Handler->getName()) && \"Pragma handler already exists for this identifier!\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/Pragma.cpp", 906, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "Pragma handler already exists for this identifier!"); |
907 | InsertNS->AddPragma(Handler); |
908 | } |
909 | |
910 | |
911 | |
912 | |
913 | |
914 | void Preprocessor::RemovePragmaHandler(StringRef Namespace, |
915 | PragmaHandler *Handler) { |
916 | PragmaNamespace *NS = PragmaHandlers.get(); |
917 | |
918 | |
919 | if (!Namespace.empty()) { |
920 | PragmaHandler *Existing = PragmaHandlers->FindHandler(Namespace); |
921 | (0) . __assert_fail ("Existing && \"Namespace containing handler does not exist!\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/Pragma.cpp", 921, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Existing && "Namespace containing handler does not exist!"); |
922 | |
923 | NS = Existing->getIfNamespace(); |
924 | (0) . __assert_fail ("NS && \"Invalid namespace, registered as a regular pragma handler!\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/Pragma.cpp", 924, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(NS && "Invalid namespace, registered as a regular pragma handler!"); |
925 | } |
926 | |
927 | NS->RemovePragmaHandler(Handler); |
928 | |
929 | |
930 | if (NS != PragmaHandlers.get() && NS->IsEmpty()) { |
931 | PragmaHandlers->RemovePragmaHandler(NS); |
932 | delete NS; |
933 | } |
934 | } |
935 | |
936 | bool Preprocessor::LexOnOffSwitch(tok::OnOffSwitch &Result) { |
937 | Token Tok; |
938 | LexUnexpandedToken(Tok); |
939 | |
940 | if (Tok.isNot(tok::identifier)) { |
941 | Diag(Tok, diag::ext_on_off_switch_syntax); |
942 | return true; |
943 | } |
944 | IdentifierInfo *II = Tok.getIdentifierInfo(); |
945 | if (II->isStr("ON")) |
946 | Result = tok::OOS_ON; |
947 | else if (II->isStr("OFF")) |
948 | Result = tok::OOS_OFF; |
949 | else if (II->isStr("DEFAULT")) |
950 | Result = tok::OOS_DEFAULT; |
951 | else { |
952 | Diag(Tok, diag::ext_on_off_switch_syntax); |
953 | return true; |
954 | } |
955 | |
956 | |
957 | LexUnexpandedToken(Tok); |
958 | if (Tok.isNot(tok::eod)) |
959 | Diag(Tok, diag::ext_pragma_syntax_eod); |
960 | return false; |
961 | } |
962 | |
963 | namespace { |
964 | |
965 | |
966 | struct PragmaOnceHandler : public PragmaHandler { |
967 | PragmaOnceHandler() : PragmaHandler("once") {} |
968 | |
969 | void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, |
970 | Token &OnceTok) override { |
971 | PP.CheckEndOfDirective("pragma once"); |
972 | PP.HandlePragmaOnce(OnceTok); |
973 | } |
974 | }; |
975 | |
976 | |
977 | |
978 | struct PragmaMarkHandler : public PragmaHandler { |
979 | PragmaMarkHandler() : PragmaHandler("mark") {} |
980 | |
981 | void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, |
982 | Token &MarkTok) override { |
983 | PP.HandlePragmaMark(); |
984 | } |
985 | }; |
986 | |
987 | |
988 | struct PragmaPoisonHandler : public PragmaHandler { |
989 | PragmaPoisonHandler() : PragmaHandler("poison") {} |
990 | |
991 | void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, |
992 | Token &PoisonTok) override { |
993 | PP.HandlePragmaPoison(); |
994 | } |
995 | }; |
996 | |
997 | |
998 | |
999 | struct PragmaSystemHeaderHandler : public PragmaHandler { |
1000 | PragmaSystemHeaderHandler() : PragmaHandler("system_header") {} |
1001 | |
1002 | void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, |
1003 | Token &SHToken) override { |
1004 | PP.HandlePragmaSystemHeader(SHToken); |
1005 | PP.CheckEndOfDirective("pragma"); |
1006 | } |
1007 | }; |
1008 | |
1009 | struct PragmaDependencyHandler : public PragmaHandler { |
1010 | PragmaDependencyHandler() : PragmaHandler("dependency") {} |
1011 | |
1012 | void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, |
1013 | Token &DepToken) override { |
1014 | PP.HandlePragmaDependency(DepToken); |
1015 | } |
1016 | }; |
1017 | |
1018 | struct PragmaDebugHandler : public PragmaHandler { |
1019 | PragmaDebugHandler() : PragmaHandler("__debug") {} |
1020 | |
1021 | void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, |
1022 | Token &DepToken) override { |
1023 | Token Tok; |
1024 | PP.LexUnexpandedToken(Tok); |
1025 | if (Tok.isNot(tok::identifier)) { |
1026 | PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid); |
1027 | return; |
1028 | } |
1029 | IdentifierInfo *II = Tok.getIdentifierInfo(); |
1030 | |
1031 | if (II->isStr("assert")) { |
1032 | llvm_unreachable("This is an assertion!"); |
1033 | } else if (II->isStr("crash")) { |
1034 | LLVM_BUILTIN_TRAP; |
1035 | } else if (II->isStr("parser_crash")) { |
1036 | Token Crasher; |
1037 | Crasher.startToken(); |
1038 | Crasher.setKind(tok::annot_pragma_parser_crash); |
1039 | Crasher.setAnnotationRange(SourceRange(Tok.getLocation())); |
1040 | PP.EnterToken(Crasher); |
1041 | } else if (II->isStr("dump")) { |
1042 | Token Identifier; |
1043 | PP.LexUnexpandedToken(Identifier); |
1044 | if (auto *DumpII = Identifier.getIdentifierInfo()) { |
1045 | Token DumpAnnot; |
1046 | DumpAnnot.startToken(); |
1047 | DumpAnnot.setKind(tok::annot_pragma_dump); |
1048 | DumpAnnot.setAnnotationRange( |
1049 | SourceRange(Tok.getLocation(), Identifier.getLocation())); |
1050 | DumpAnnot.setAnnotationValue(DumpII); |
1051 | PP.DiscardUntilEndOfDirective(); |
1052 | PP.EnterToken(DumpAnnot); |
1053 | } else { |
1054 | PP.Diag(Identifier, diag::warn_pragma_debug_missing_argument) |
1055 | << II->getName(); |
1056 | } |
1057 | } else if (II->isStr("diag_mapping")) { |
1058 | Token DiagName; |
1059 | PP.LexUnexpandedToken(DiagName); |
1060 | if (DiagName.is(tok::eod)) |
1061 | PP.getDiagnostics().dump(); |
1062 | else if (DiagName.is(tok::string_literal) && !DiagName.hasUDSuffix()) { |
1063 | StringLiteralParser Literal(DiagName, PP); |
1064 | if (Literal.hadError) |
1065 | return; |
1066 | PP.getDiagnostics().dump(Literal.GetString()); |
1067 | } else { |
1068 | PP.Diag(DiagName, diag::warn_pragma_debug_missing_argument) |
1069 | << II->getName(); |
1070 | } |
1071 | } else if (II->isStr("llvm_fatal_error")) { |
1072 | llvm::report_fatal_error("#pragma clang __debug llvm_fatal_error"); |
1073 | } else if (II->isStr("llvm_unreachable")) { |
1074 | llvm_unreachable("#pragma clang __debug llvm_unreachable"); |
1075 | } else if (II->isStr("macro")) { |
1076 | Token MacroName; |
1077 | PP.LexUnexpandedToken(MacroName); |
1078 | auto *MacroII = MacroName.getIdentifierInfo(); |
1079 | if (MacroII) |
1080 | PP.dumpMacroInfo(MacroII); |
1081 | else |
1082 | PP.Diag(MacroName, diag::warn_pragma_debug_missing_argument) |
1083 | << II->getName(); |
1084 | } else if (II->isStr("overflow_stack")) { |
1085 | DebugOverflowStack(); |
1086 | } else if (II->isStr("handle_crash")) { |
1087 | llvm::CrashRecoveryContext *CRC =llvm::CrashRecoveryContext::GetCurrent(); |
1088 | if (CRC) |
1089 | CRC->HandleCrash(); |
1090 | } else if (II->isStr("captured")) { |
1091 | HandleCaptured(PP); |
1092 | } else { |
1093 | PP.Diag(Tok, diag::warn_pragma_debug_unexpected_command) |
1094 | << II->getName(); |
1095 | } |
1096 | |
1097 | PPCallbacks *Callbacks = PP.getPPCallbacks(); |
1098 | if (Callbacks) |
1099 | Callbacks->PragmaDebug(Tok.getLocation(), II->getName()); |
1100 | } |
1101 | |
1102 | void HandleCaptured(Preprocessor &PP) { |
1103 | Token Tok; |
1104 | PP.LexUnexpandedToken(Tok); |
1105 | |
1106 | if (Tok.isNot(tok::eod)) { |
1107 | PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) |
1108 | << "pragma clang __debug captured"; |
1109 | return; |
1110 | } |
1111 | |
1112 | SourceLocation NameLoc = Tok.getLocation(); |
1113 | MutableArrayRef<Token> Toks( |
1114 | PP.getPreprocessorAllocator().Allocate<Token>(1), 1); |
1115 | Toks[0].startToken(); |
1116 | Toks[0].setKind(tok::annot_pragma_captured); |
1117 | Toks[0].setLocation(NameLoc); |
1118 | |
1119 | PP.EnterTokenStream(Toks, ); |
1120 | } |
1121 | |
1122 | |
1123 | #ifdef _MSC_VER |
1124 | #pragma warning(disable : 4717) |
1125 | #endif |
1126 | static void DebugOverflowStack(void (*P)() = nullptr) { |
1127 | void (*volatile Self)(void(*P)()) = DebugOverflowStack; |
1128 | Self(reinterpret_cast<void(*)()>(Self)); |
1129 | } |
1130 | #ifdef _MSC_VER |
1131 | #pragma warning(default : 4717) |
1132 | #endif |
1133 | }; |
1134 | |
1135 | |
1136 | struct PragmaDiagnosticHandler : public PragmaHandler { |
1137 | private: |
1138 | const char *Namespace; |
1139 | |
1140 | public: |
1141 | explicit PragmaDiagnosticHandler(const char *NS) |
1142 | : PragmaHandler("diagnostic"), Namespace(NS) {} |
1143 | |
1144 | void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, |
1145 | Token &DiagToken) override { |
1146 | SourceLocation DiagLoc = DiagToken.getLocation(); |
1147 | Token Tok; |
1148 | PP.LexUnexpandedToken(Tok); |
1149 | if (Tok.isNot(tok::identifier)) { |
1150 | PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid); |
1151 | return; |
1152 | } |
1153 | IdentifierInfo *II = Tok.getIdentifierInfo(); |
1154 | PPCallbacks *Callbacks = PP.getPPCallbacks(); |
1155 | |
1156 | if (II->isStr("pop")) { |
1157 | if (!PP.getDiagnostics().popMappings(DiagLoc)) |
1158 | PP.Diag(Tok, diag::warn_pragma_diagnostic_cannot_pop); |
1159 | else if (Callbacks) |
1160 | Callbacks->PragmaDiagnosticPop(DiagLoc, Namespace); |
1161 | return; |
1162 | } else if (II->isStr("push")) { |
1163 | PP.getDiagnostics().pushMappings(DiagLoc); |
1164 | if (Callbacks) |
1165 | Callbacks->PragmaDiagnosticPush(DiagLoc, Namespace); |
1166 | return; |
1167 | } |
1168 | |
1169 | diag::Severity SV = llvm::StringSwitch<diag::Severity>(II->getName()) |
1170 | .Case("ignored", diag::Severity::Ignored) |
1171 | .Case("warning", diag::Severity::Warning) |
1172 | .Case("error", diag::Severity::Error) |
1173 | .Case("fatal", diag::Severity::Fatal) |
1174 | .Default(diag::Severity()); |
1175 | |
1176 | if (SV == diag::Severity()) { |
1177 | PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid); |
1178 | return; |
1179 | } |
1180 | |
1181 | PP.LexUnexpandedToken(Tok); |
1182 | SourceLocation StringLoc = Tok.getLocation(); |
1183 | |
1184 | std::string WarningName; |
1185 | if (!PP.FinishLexStringLiteral(Tok, WarningName, "pragma diagnostic", |
1186 | )) |
1187 | return; |
1188 | |
1189 | if (Tok.isNot(tok::eod)) { |
1190 | PP.Diag(Tok.getLocation(), diag::warn_pragma_diagnostic_invalid_token); |
1191 | return; |
1192 | } |
1193 | |
1194 | if (WarningName.size() < 3 || WarningName[0] != '-' || |
1195 | (WarningName[1] != 'W' && WarningName[1] != 'R')) { |
1196 | PP.Diag(StringLoc, diag::warn_pragma_diagnostic_invalid_option); |
1197 | return; |
1198 | } |
1199 | |
1200 | diag::Flavor Flavor = WarningName[1] == 'W' ? diag::Flavor::WarningOrError |
1201 | : diag::Flavor::Remark; |
1202 | StringRef Group = StringRef(WarningName).substr(2); |
1203 | bool unknownDiag = false; |
1204 | if (Group == "everything") { |
1205 | |
1206 | |
1207 | |
1208 | PP.getDiagnostics().setSeverityForAll(Flavor, SV, DiagLoc); |
1209 | } else |
1210 | unknownDiag = PP.getDiagnostics().setSeverityForGroup(Flavor, Group, SV, |
1211 | DiagLoc); |
1212 | if (unknownDiag) |
1213 | PP.Diag(StringLoc, diag::warn_pragma_diagnostic_unknown_warning) |
1214 | << WarningName; |
1215 | else if (Callbacks) |
1216 | Callbacks->PragmaDiagnostic(DiagLoc, Namespace, SV, WarningName); |
1217 | } |
1218 | }; |
1219 | |
1220 | |
1221 | struct PragmaHdrstopHandler : public PragmaHandler { |
1222 | PragmaHdrstopHandler() : PragmaHandler("hdrstop") {} |
1223 | void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, |
1224 | Token &DepToken) override { |
1225 | PP.HandlePragmaHdrstop(DepToken); |
1226 | } |
1227 | }; |
1228 | |
1229 | |
1230 | |
1231 | |
1232 | struct PragmaWarningHandler : public PragmaHandler { |
1233 | PragmaWarningHandler() : PragmaHandler("warning") {} |
1234 | |
1235 | void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, |
1236 | Token &Tok) override { |
1237 | |
1238 | |
1239 | |
1240 | |
1241 | SourceLocation DiagLoc = Tok.getLocation(); |
1242 | PPCallbacks *Callbacks = PP.getPPCallbacks(); |
1243 | |
1244 | PP.Lex(Tok); |
1245 | if (Tok.isNot(tok::l_paren)) { |
1246 | PP.Diag(Tok, diag::warn_pragma_warning_expected) << "("; |
1247 | return; |
1248 | } |
1249 | |
1250 | PP.Lex(Tok); |
1251 | IdentifierInfo *II = Tok.getIdentifierInfo(); |
1252 | |
1253 | if (II && II->isStr("push")) { |
1254 | |
1255 | int Level = -1; |
1256 | PP.Lex(Tok); |
1257 | if (Tok.is(tok::comma)) { |
1258 | PP.Lex(Tok); |
1259 | uint64_t Value; |
1260 | if (Tok.is(tok::numeric_constant) && |
1261 | PP.parseSimpleIntegerLiteral(Tok, Value)) |
1262 | Level = int(Value); |
1263 | if (Level < 0 || Level > 4) { |
1264 | PP.Diag(Tok, diag::warn_pragma_warning_push_level); |
1265 | return; |
1266 | } |
1267 | } |
1268 | if (Callbacks) |
1269 | Callbacks->PragmaWarningPush(DiagLoc, Level); |
1270 | } else if (II && II->isStr("pop")) { |
1271 | |
1272 | PP.Lex(Tok); |
1273 | if (Callbacks) |
1274 | Callbacks->PragmaWarningPop(DiagLoc); |
1275 | } else { |
1276 | |
1277 | |
1278 | while (true) { |
1279 | II = Tok.getIdentifierInfo(); |
1280 | if (!II && !Tok.is(tok::numeric_constant)) { |
1281 | PP.Diag(Tok, diag::warn_pragma_warning_spec_invalid); |
1282 | return; |
1283 | } |
1284 | |
1285 | |
1286 | bool SpecifierValid; |
1287 | StringRef Specifier; |
1288 | llvm::SmallString<1> SpecifierBuf; |
1289 | if (II) { |
1290 | Specifier = II->getName(); |
1291 | SpecifierValid = llvm::StringSwitch<bool>(Specifier) |
1292 | .Cases("default", "disable", "error", "once", |
1293 | "suppress", true) |
1294 | .Default(false); |
1295 | |
1296 | |
1297 | if (SpecifierValid) |
1298 | PP.Lex(Tok); |
1299 | } else { |
1300 | |
1301 | uint64_t Value; |
1302 | Specifier = PP.getSpelling(Tok, SpecifierBuf); |
1303 | if (PP.parseSimpleIntegerLiteral(Tok, Value)) { |
1304 | SpecifierValid = (Value >= 1) && (Value <= 4); |
1305 | } else |
1306 | SpecifierValid = false; |
1307 | |
1308 | } |
1309 | |
1310 | if (!SpecifierValid) { |
1311 | PP.Diag(Tok, diag::warn_pragma_warning_spec_invalid); |
1312 | return; |
1313 | } |
1314 | if (Tok.isNot(tok::colon)) { |
1315 | PP.Diag(Tok, diag::warn_pragma_warning_expected) << ":"; |
1316 | return; |
1317 | } |
1318 | |
1319 | |
1320 | SmallVector<int, 4> Ids; |
1321 | PP.Lex(Tok); |
1322 | while (Tok.is(tok::numeric_constant)) { |
1323 | uint64_t Value; |
1324 | if (!PP.parseSimpleIntegerLiteral(Tok, Value) || Value == 0 || |
1325 | Value > std::numeric_limits<int>::max()) { |
1326 | PP.Diag(Tok, diag::warn_pragma_warning_expected_number); |
1327 | return; |
1328 | } |
1329 | Ids.push_back(int(Value)); |
1330 | } |
1331 | if (Callbacks) |
1332 | Callbacks->PragmaWarning(DiagLoc, Specifier, Ids); |
1333 | |
1334 | |
1335 | if (Tok.isNot(tok::semi)) |
1336 | break; |
1337 | PP.Lex(Tok); |
1338 | } |
1339 | } |
1340 | |
1341 | if (Tok.isNot(tok::r_paren)) { |
1342 | PP.Diag(Tok, diag::warn_pragma_warning_expected) << ")"; |
1343 | return; |
1344 | } |
1345 | |
1346 | PP.Lex(Tok); |
1347 | if (Tok.isNot(tok::eod)) |
1348 | PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma warning"; |
1349 | } |
1350 | }; |
1351 | |
1352 | |
1353 | |
1354 | |
1355 | struct PragmaExecCharsetHandler : public PragmaHandler { |
1356 | PragmaExecCharsetHandler() : PragmaHandler("execution_character_set") {} |
1357 | |
1358 | void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, |
1359 | Token &Tok) override { |
1360 | |
1361 | |
1362 | |
1363 | SourceLocation DiagLoc = Tok.getLocation(); |
1364 | PPCallbacks *Callbacks = PP.getPPCallbacks(); |
1365 | |
1366 | PP.Lex(Tok); |
1367 | if (Tok.isNot(tok::l_paren)) { |
1368 | PP.Diag(Tok, diag::warn_pragma_exec_charset_expected) << "("; |
1369 | return; |
1370 | } |
1371 | |
1372 | PP.Lex(Tok); |
1373 | IdentifierInfo *II = Tok.getIdentifierInfo(); |
1374 | |
1375 | if (II && II->isStr("push")) { |
1376 | |
1377 | PP.Lex(Tok); |
1378 | if (Tok.is(tok::comma)) { |
1379 | PP.Lex(Tok); |
1380 | |
1381 | std::string ExecCharset; |
1382 | if (!PP.FinishLexStringLiteral(Tok, ExecCharset, |
1383 | "pragma execution_character_set", |
1384 | )) |
1385 | return; |
1386 | |
1387 | |
1388 | if (ExecCharset != "UTF-8" && ExecCharset != "utf-8") { |
1389 | PP.Diag(Tok, diag::warn_pragma_exec_charset_push_invalid) << ExecCharset; |
1390 | return; |
1391 | } |
1392 | } |
1393 | if (Callbacks) |
1394 | Callbacks->PragmaExecCharsetPush(DiagLoc, "UTF-8"); |
1395 | } else if (II && II->isStr("pop")) { |
1396 | |
1397 | PP.Lex(Tok); |
1398 | if (Callbacks) |
1399 | Callbacks->PragmaExecCharsetPop(DiagLoc); |
1400 | } else { |
1401 | PP.Diag(Tok, diag::warn_pragma_exec_charset_spec_invalid); |
1402 | return; |
1403 | } |
1404 | |
1405 | if (Tok.isNot(tok::r_paren)) { |
1406 | PP.Diag(Tok, diag::warn_pragma_exec_charset_expected) << ")"; |
1407 | return; |
1408 | } |
1409 | |
1410 | PP.Lex(Tok); |
1411 | if (Tok.isNot(tok::eod)) |
1412 | PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma execution_character_set"; |
1413 | } |
1414 | }; |
1415 | |
1416 | |
1417 | struct PragmaIncludeAliasHandler : public PragmaHandler { |
1418 | PragmaIncludeAliasHandler() : PragmaHandler("include_alias") {} |
1419 | |
1420 | void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, |
1421 | Token &IncludeAliasTok) override { |
1422 | PP.HandlePragmaIncludeAlias(IncludeAliasTok); |
1423 | } |
1424 | }; |
1425 | |
1426 | |
1427 | |
1428 | |
1429 | |
1430 | |
1431 | |
1432 | |
1433 | |
1434 | |
1435 | |
1436 | |
1437 | |
1438 | |
1439 | struct PragmaMessageHandler : public PragmaHandler { |
1440 | private: |
1441 | const PPCallbacks::PragmaMessageKind Kind; |
1442 | const StringRef Namespace; |
1443 | |
1444 | static const char* PragmaKind(PPCallbacks::PragmaMessageKind Kind, |
1445 | bool PragmaNameOnly = false) { |
1446 | switch (Kind) { |
1447 | case PPCallbacks::PMK_Message: |
1448 | return PragmaNameOnly ? "message" : "pragma message"; |
1449 | case PPCallbacks::PMK_Warning: |
1450 | return PragmaNameOnly ? "warning" : "pragma warning"; |
1451 | case PPCallbacks::PMK_Error: |
1452 | return PragmaNameOnly ? "error" : "pragma error"; |
1453 | } |
1454 | llvm_unreachable("Unknown PragmaMessageKind!"); |
1455 | } |
1456 | |
1457 | public: |
1458 | PragmaMessageHandler(PPCallbacks::PragmaMessageKind Kind, |
1459 | StringRef Namespace = StringRef()) |
1460 | : PragmaHandler(PragmaKind(Kind, true)), Kind(Kind), |
1461 | Namespace(Namespace) {} |
1462 | |
1463 | void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, |
1464 | Token &Tok) override { |
1465 | SourceLocation MessageLoc = Tok.getLocation(); |
1466 | PP.Lex(Tok); |
1467 | bool ExpectClosingParen = false; |
1468 | switch (Tok.getKind()) { |
1469 | case tok::l_paren: |
1470 | |
1471 | ExpectClosingParen = true; |
1472 | |
1473 | PP.Lex(Tok); |
1474 | break; |
1475 | case tok::string_literal: |
1476 | |
1477 | break; |
1478 | default: |
1479 | PP.Diag(MessageLoc, diag::err_pragma_message_malformed) << Kind; |
1480 | return; |
1481 | } |
1482 | |
1483 | std::string MessageString; |
1484 | if (!PP.FinishLexStringLiteral(Tok, MessageString, PragmaKind(Kind), |
1485 | )) |
1486 | return; |
1487 | |
1488 | if (ExpectClosingParen) { |
1489 | if (Tok.isNot(tok::r_paren)) { |
1490 | PP.Diag(Tok.getLocation(), diag::err_pragma_message_malformed) << Kind; |
1491 | return; |
1492 | } |
1493 | PP.Lex(Tok); |
1494 | } |
1495 | |
1496 | if (Tok.isNot(tok::eod)) { |
1497 | PP.Diag(Tok.getLocation(), diag::err_pragma_message_malformed) << Kind; |
1498 | return; |
1499 | } |
1500 | |
1501 | |
1502 | PP.Diag(MessageLoc, (Kind == PPCallbacks::PMK_Error) |
1503 | ? diag::err_pragma_message |
1504 | : diag::warn_pragma_message) << MessageString; |
1505 | |
1506 | |
1507 | if (PPCallbacks *Callbacks = PP.getPPCallbacks()) |
1508 | Callbacks->PragmaMessage(MessageLoc, Namespace, Kind, MessageString); |
1509 | } |
1510 | }; |
1511 | |
1512 | |
1513 | |
1514 | |
1515 | |
1516 | struct PragmaModuleImportHandler : public PragmaHandler { |
1517 | PragmaModuleImportHandler() : PragmaHandler("import") {} |
1518 | |
1519 | void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, |
1520 | Token &Tok) override { |
1521 | SourceLocation ImportLoc = Tok.getLocation(); |
1522 | |
1523 | |
1524 | llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 8> |
1525 | ModuleName; |
1526 | if (LexModuleName(PP, Tok, ModuleName)) |
1527 | return; |
1528 | |
1529 | if (Tok.isNot(tok::eod)) |
1530 | PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma"; |
1531 | |
1532 | |
1533 | Module *Imported = |
1534 | PP.getModuleLoader().loadModule(ImportLoc, ModuleName, Module::Hidden, |
1535 | ); |
1536 | if (!Imported) |
1537 | return; |
1538 | |
1539 | PP.makeModuleVisible(Imported, ImportLoc); |
1540 | PP.EnterAnnotationToken(SourceRange(ImportLoc, ModuleName.back().second), |
1541 | tok::annot_module_include, Imported); |
1542 | if (auto *CB = PP.getPPCallbacks()) |
1543 | CB->moduleImport(ImportLoc, ModuleName, Imported); |
1544 | } |
1545 | }; |
1546 | |
1547 | |
1548 | |
1549 | |
1550 | |
1551 | |
1552 | |
1553 | struct PragmaModuleBeginHandler : public PragmaHandler { |
1554 | PragmaModuleBeginHandler() : PragmaHandler("begin") {} |
1555 | |
1556 | void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, |
1557 | Token &Tok) override { |
1558 | SourceLocation BeginLoc = Tok.getLocation(); |
1559 | |
1560 | |
1561 | llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 8> |
1562 | ModuleName; |
1563 | if (LexModuleName(PP, Tok, ModuleName)) |
1564 | return; |
1565 | |
1566 | if (Tok.isNot(tok::eod)) |
1567 | PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma"; |
1568 | |
1569 | |
1570 | StringRef Current = PP.getLangOpts().CurrentModule; |
1571 | if (ModuleName.front().first->getName() != Current) { |
1572 | PP.Diag(ModuleName.front().second, diag::err_pp_module_begin_wrong_module) |
1573 | << ModuleName.front().first << (ModuleName.size() > 1) |
1574 | << Current.empty() << Current; |
1575 | return; |
1576 | } |
1577 | |
1578 | |
1579 | |
1580 | |
1581 | |
1582 | Module *M = PP.getHeaderSearchInfo().lookupModule(Current); |
1583 | if (!M) { |
1584 | PP.Diag(ModuleName.front().second, |
1585 | diag::err_pp_module_begin_no_module_map) << Current; |
1586 | return; |
1587 | } |
1588 | for (unsigned I = 1; I != ModuleName.size(); ++I) { |
1589 | auto *NewM = M->findSubmodule(ModuleName[I].first->getName()); |
1590 | if (!NewM) { |
1591 | PP.Diag(ModuleName[I].second, diag::err_pp_module_begin_no_submodule) |
1592 | << M->getFullModuleName() << ModuleName[I].first; |
1593 | return; |
1594 | } |
1595 | M = NewM; |
1596 | } |
1597 | |
1598 | |
1599 | if (Preprocessor::checkModuleIsAvailable( |
1600 | PP.getLangOpts(), PP.getTargetInfo(), PP.getDiagnostics(), M)) { |
1601 | PP.Diag(BeginLoc, diag::note_pp_module_begin_here) |
1602 | << M->getTopLevelModuleName(); |
1603 | return; |
1604 | } |
1605 | |
1606 | |
1607 | PP.EnterSubmodule(M, BeginLoc, ); |
1608 | PP.EnterAnnotationToken(SourceRange(BeginLoc, ModuleName.back().second), |
1609 | tok::annot_module_begin, M); |
1610 | } |
1611 | }; |
1612 | |
1613 | |
1614 | struct PragmaModuleEndHandler : public PragmaHandler { |
1615 | PragmaModuleEndHandler() : PragmaHandler("end") {} |
1616 | |
1617 | void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, |
1618 | Token &Tok) override { |
1619 | SourceLocation Loc = Tok.getLocation(); |
1620 | |
1621 | PP.LexUnexpandedToken(Tok); |
1622 | if (Tok.isNot(tok::eod)) |
1623 | PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma"; |
1624 | |
1625 | Module *M = PP.LeaveSubmodule(); |
1626 | if (M) |
1627 | PP.EnterAnnotationToken(SourceRange(Loc), tok::annot_module_end, M); |
1628 | else |
1629 | PP.Diag(Loc, diag::err_pp_module_end_without_module_begin); |
1630 | } |
1631 | }; |
1632 | |
1633 | |
1634 | struct PragmaModuleBuildHandler : public PragmaHandler { |
1635 | PragmaModuleBuildHandler() : PragmaHandler("build") {} |
1636 | |
1637 | void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, |
1638 | Token &Tok) override { |
1639 | PP.HandlePragmaModuleBuild(Tok); |
1640 | } |
1641 | }; |
1642 | |
1643 | |
1644 | struct PragmaModuleLoadHandler : public PragmaHandler { |
1645 | PragmaModuleLoadHandler() : PragmaHandler("load") {} |
1646 | |
1647 | void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, |
1648 | Token &Tok) override { |
1649 | SourceLocation Loc = Tok.getLocation(); |
1650 | |
1651 | |
1652 | llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 8> |
1653 | ModuleName; |
1654 | if (LexModuleName(PP, Tok, ModuleName)) |
1655 | return; |
1656 | |
1657 | if (Tok.isNot(tok::eod)) |
1658 | PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma"; |
1659 | |
1660 | |
1661 | PP.getModuleLoader().loadModule(Loc, ModuleName, Module::Hidden, |
1662 | ); |
1663 | } |
1664 | }; |
1665 | |
1666 | |
1667 | |
1668 | struct PragmaPushMacroHandler : public PragmaHandler { |
1669 | PragmaPushMacroHandler() : PragmaHandler("push_macro") {} |
1670 | |
1671 | void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, |
1672 | Token &PushMacroTok) override { |
1673 | PP.HandlePragmaPushMacro(PushMacroTok); |
1674 | } |
1675 | }; |
1676 | |
1677 | |
1678 | |
1679 | struct PragmaPopMacroHandler : public PragmaHandler { |
1680 | PragmaPopMacroHandler() : PragmaHandler("pop_macro") {} |
1681 | |
1682 | void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, |
1683 | Token &PopMacroTok) override { |
1684 | PP.HandlePragmaPopMacro(PopMacroTok); |
1685 | } |
1686 | }; |
1687 | |
1688 | |
1689 | |
1690 | struct PragmaARCCFCodeAuditedHandler : public PragmaHandler { |
1691 | PragmaARCCFCodeAuditedHandler() : PragmaHandler("arc_cf_code_audited") {} |
1692 | |
1693 | void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, |
1694 | Token &NameTok) override { |
1695 | SourceLocation Loc = NameTok.getLocation(); |
1696 | bool IsBegin; |
1697 | |
1698 | Token Tok; |
1699 | |
1700 | |
1701 | PP.LexUnexpandedToken(Tok); |
1702 | const IdentifierInfo *BeginEnd = Tok.getIdentifierInfo(); |
1703 | if (BeginEnd && BeginEnd->isStr("begin")) { |
1704 | IsBegin = true; |
1705 | } else if (BeginEnd && BeginEnd->isStr("end")) { |
1706 | IsBegin = false; |
1707 | } else { |
1708 | PP.Diag(Tok.getLocation(), diag::err_pp_arc_cf_code_audited_syntax); |
1709 | return; |
1710 | } |
1711 | |
1712 | |
1713 | PP.LexUnexpandedToken(Tok); |
1714 | if (Tok.isNot(tok::eod)) |
1715 | PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma"; |
1716 | |
1717 | |
1718 | SourceLocation BeginLoc = PP.getPragmaARCCFCodeAuditedLoc(); |
1719 | |
1720 | |
1721 | SourceLocation NewLoc; |
1722 | |
1723 | if (IsBegin) { |
1724 | |
1725 | if (BeginLoc.isValid()) { |
1726 | PP.Diag(Loc, diag::err_pp_double_begin_of_arc_cf_code_audited); |
1727 | PP.Diag(BeginLoc, diag::note_pragma_entered_here); |
1728 | } |
1729 | NewLoc = Loc; |
1730 | } else { |
1731 | |
1732 | if (!BeginLoc.isValid()) { |
1733 | PP.Diag(Loc, diag::err_pp_unmatched_end_of_arc_cf_code_audited); |
1734 | return; |
1735 | } |
1736 | NewLoc = SourceLocation(); |
1737 | } |
1738 | |
1739 | PP.setPragmaARCCFCodeAuditedLoc(NewLoc); |
1740 | } |
1741 | }; |
1742 | |
1743 | |
1744 | |
1745 | struct PragmaAssumeNonNullHandler : public PragmaHandler { |
1746 | PragmaAssumeNonNullHandler() : PragmaHandler("assume_nonnull") {} |
1747 | |
1748 | void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, |
1749 | Token &NameTok) override { |
1750 | SourceLocation Loc = NameTok.getLocation(); |
1751 | bool IsBegin; |
1752 | |
1753 | Token Tok; |
1754 | |
1755 | |
1756 | PP.LexUnexpandedToken(Tok); |
1757 | const IdentifierInfo *BeginEnd = Tok.getIdentifierInfo(); |
1758 | if (BeginEnd && BeginEnd->isStr("begin")) { |
1759 | IsBegin = true; |
1760 | } else if (BeginEnd && BeginEnd->isStr("end")) { |
1761 | IsBegin = false; |
1762 | } else { |
1763 | PP.Diag(Tok.getLocation(), diag::err_pp_assume_nonnull_syntax); |
1764 | return; |
1765 | } |
1766 | |
1767 | |
1768 | PP.LexUnexpandedToken(Tok); |
1769 | if (Tok.isNot(tok::eod)) |
1770 | PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma"; |
1771 | |
1772 | |
1773 | SourceLocation BeginLoc = PP.getPragmaAssumeNonNullLoc(); |
1774 | |
1775 | |
1776 | SourceLocation NewLoc; |
1777 | PPCallbacks *Callbacks = PP.getPPCallbacks(); |
1778 | |
1779 | if (IsBegin) { |
1780 | |
1781 | if (BeginLoc.isValid()) { |
1782 | PP.Diag(Loc, diag::err_pp_double_begin_of_assume_nonnull); |
1783 | PP.Diag(BeginLoc, diag::note_pragma_entered_here); |
1784 | } |
1785 | NewLoc = Loc; |
1786 | if (Callbacks) |
1787 | Callbacks->PragmaAssumeNonNullBegin(NewLoc); |
1788 | } else { |
1789 | |
1790 | if (!BeginLoc.isValid()) { |
1791 | PP.Diag(Loc, diag::err_pp_unmatched_end_of_assume_nonnull); |
1792 | return; |
1793 | } |
1794 | NewLoc = SourceLocation(); |
1795 | if (Callbacks) |
1796 | Callbacks->PragmaAssumeNonNullEnd(NewLoc); |
1797 | } |
1798 | |
1799 | PP.setPragmaAssumeNonNullLoc(NewLoc); |
1800 | } |
1801 | }; |
1802 | |
1803 | |
1804 | |
1805 | |
1806 | |
1807 | |
1808 | |
1809 | |
1810 | |
1811 | |
1812 | |
1813 | |
1814 | struct PragmaRegionHandler : public PragmaHandler { |
1815 | PragmaRegionHandler(const char *pragma) : PragmaHandler(pragma) {} |
1816 | |
1817 | void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, |
1818 | Token &NameTok) override { |
1819 | |
1820 | |
1821 | |
1822 | |
1823 | } |
1824 | }; |
1825 | |
1826 | } |
1827 | |
1828 | |
1829 | |
1830 | void Preprocessor::RegisterBuiltinPragmas() { |
1831 | AddPragmaHandler(new PragmaOnceHandler()); |
1832 | AddPragmaHandler(new PragmaMarkHandler()); |
1833 | AddPragmaHandler(new PragmaPushMacroHandler()); |
1834 | AddPragmaHandler(new PragmaPopMacroHandler()); |
1835 | AddPragmaHandler(new PragmaMessageHandler(PPCallbacks::PMK_Message)); |
1836 | |
1837 | |
1838 | AddPragmaHandler("GCC", new PragmaPoisonHandler()); |
1839 | AddPragmaHandler("GCC", new PragmaSystemHeaderHandler()); |
1840 | AddPragmaHandler("GCC", new PragmaDependencyHandler()); |
1841 | AddPragmaHandler("GCC", new PragmaDiagnosticHandler("GCC")); |
1842 | AddPragmaHandler("GCC", new PragmaMessageHandler(PPCallbacks::PMK_Warning, |
1843 | "GCC")); |
1844 | AddPragmaHandler("GCC", new PragmaMessageHandler(PPCallbacks::PMK_Error, |
1845 | "GCC")); |
1846 | |
1847 | AddPragmaHandler("clang", new PragmaPoisonHandler()); |
1848 | AddPragmaHandler("clang", new PragmaSystemHeaderHandler()); |
1849 | AddPragmaHandler("clang", new PragmaDebugHandler()); |
1850 | AddPragmaHandler("clang", new PragmaDependencyHandler()); |
1851 | AddPragmaHandler("clang", new PragmaDiagnosticHandler("clang")); |
1852 | AddPragmaHandler("clang", new PragmaARCCFCodeAuditedHandler()); |
1853 | AddPragmaHandler("clang", new PragmaAssumeNonNullHandler()); |
1854 | |
1855 | |
1856 | auto *ModuleHandler = new PragmaNamespace("module"); |
1857 | AddPragmaHandler("clang", ModuleHandler); |
1858 | ModuleHandler->AddPragma(new PragmaModuleImportHandler()); |
1859 | ModuleHandler->AddPragma(new PragmaModuleBeginHandler()); |
1860 | ModuleHandler->AddPragma(new PragmaModuleEndHandler()); |
1861 | ModuleHandler->AddPragma(new PragmaModuleBuildHandler()); |
1862 | ModuleHandler->AddPragma(new PragmaModuleLoadHandler()); |
1863 | |
1864 | |
1865 | AddPragmaHandler(new PragmaRegionHandler("region")); |
1866 | AddPragmaHandler(new PragmaRegionHandler("endregion")); |
1867 | |
1868 | |
1869 | if (LangOpts.MicrosoftExt) { |
1870 | AddPragmaHandler(new PragmaWarningHandler()); |
1871 | AddPragmaHandler(new PragmaExecCharsetHandler()); |
1872 | AddPragmaHandler(new PragmaIncludeAliasHandler()); |
1873 | AddPragmaHandler(new PragmaHdrstopHandler()); |
1874 | } |
1875 | |
1876 | |
1877 | for (PragmaHandlerRegistry::iterator it = PragmaHandlerRegistry::begin(), |
1878 | ie = PragmaHandlerRegistry::end(); |
1879 | it != ie; ++it) { |
1880 | AddPragmaHandler(it->instantiate().release()); |
1881 | } |
1882 | } |
1883 | |
1884 | |
1885 | |
1886 | void Preprocessor::IgnorePragmas() { |
1887 | AddPragmaHandler(new EmptyPragmaHandler()); |
1888 | |
1889 | |
1890 | AddPragmaHandler("GCC", new EmptyPragmaHandler()); |
1891 | AddPragmaHandler("clang", new EmptyPragmaHandler()); |
1892 | } |
1893 | |