1 //===--- Pragma.cpp - Pragma registration and handling --------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the PragmaHandler/PragmaTable interfaces and implements
11 // pragma related methods of the Preprocessor class.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "clang/Lex/Pragma.h"
16 #include "clang/Lex/HeaderSearch.h"
17 #include "clang/Lex/LiteralSupport.h"
18 #include "clang/Lex/Preprocessor.h"
19 #include "clang/Lex/LexDiagnostic.h"
20 #include "clang/Basic/FileManager.h"
21 #include "clang/Basic/SourceManager.h"
22 #include <algorithm>
23 using namespace clang;
24 
25 // Out-of-line destructor to provide a home for the class.
26 PragmaHandler::~PragmaHandler() {
27 }
28 
29 //===----------------------------------------------------------------------===//
30 // PragmaNamespace Implementation.
31 //===----------------------------------------------------------------------===//
32 
33 
34 PragmaNamespace::~PragmaNamespace() {
35   for (unsigned i = 0, e = Handlers.size(); i != e; ++i)
36     delete Handlers[i];
37 }
38 
39 /// FindHandler - Check to see if there is already a handler for the
40 /// specified name.  If not, return the handler for the null identifier if it
41 /// exists, otherwise return null.  If IgnoreNull is true (the default) then
42 /// the null handler isn't returned on failure to match.
43 PragmaHandler *PragmaNamespace::FindHandler(const IdentifierInfo *Name,
44                                             bool IgnoreNull) const {
45   PragmaHandler *NullHandler = 0;
46   for (unsigned i = 0, e = Handlers.size(); i != e; ++i) {
47     if (Handlers[i]->getName() == Name)
48       return Handlers[i];
49 
50     if (Handlers[i]->getName() == 0)
51       NullHandler = Handlers[i];
52   }
53   return IgnoreNull ? 0 : NullHandler;
54 }
55 
56 void PragmaNamespace::RemovePragmaHandler(PragmaHandler *Handler) {
57   for (unsigned i = 0, e = Handlers.size(); i != e; ++i) {
58     if (Handlers[i] == Handler) {
59       Handlers[i] = Handlers.back();
60       Handlers.pop_back();
61       return;
62     }
63   }
64   assert(0 && "Handler not registered in this namespace");
65 }
66 
67 void PragmaNamespace::HandlePragma(Preprocessor &PP, Token &Tok) {
68   // Read the 'namespace' that the directive is in, e.g. STDC.  Do not macro
69   // expand it, the user can have a STDC #define, that should not affect this.
70   PP.LexUnexpandedToken(Tok);
71 
72   // Get the handler for this token.  If there is no handler, ignore the pragma.
73   PragmaHandler *Handler = FindHandler(Tok.getIdentifierInfo(), false);
74   if (Handler == 0) {
75     PP.Diag(Tok, diag::warn_pragma_ignored);
76     return;
77   }
78 
79   // Otherwise, pass it down.
80   Handler->HandlePragma(PP, Tok);
81 }
82 
83 //===----------------------------------------------------------------------===//
84 // Preprocessor Pragma Directive Handling.
85 //===----------------------------------------------------------------------===//
86 
87 /// HandlePragmaDirective - The "#pragma" directive has been parsed.  Lex the
88 /// rest of the pragma, passing it to the registered pragma handlers.
89 void Preprocessor::HandlePragmaDirective() {
90   ++NumPragma;
91 
92   // Invoke the first level of pragma handlers which reads the namespace id.
93   Token Tok;
94   PragmaHandlers->HandlePragma(*this, Tok);
95 
96   // If the pragma handler didn't read the rest of the line, consume it now.
97   if (CurPPLexer && CurPPLexer->ParsingPreprocessorDirective)
98     DiscardUntilEndOfDirective();
99 }
100 
101 /// Handle_Pragma - Read a _Pragma directive, slice it up, process it, then
102 /// return the first token after the directive.  The _Pragma token has just
103 /// been read into 'Tok'.
104 void Preprocessor::Handle_Pragma(Token &Tok) {
105   // Remember the pragma token location.
106   SourceLocation PragmaLoc = Tok.getLocation();
107 
108   // Read the '('.
109   Lex(Tok);
110   if (Tok.isNot(tok::l_paren)) {
111     Diag(PragmaLoc, diag::err__Pragma_malformed);
112     return;
113   }
114 
115   // Read the '"..."'.
116   Lex(Tok);
117   if (Tok.isNot(tok::string_literal) && Tok.isNot(tok::wide_string_literal)) {
118     Diag(PragmaLoc, diag::err__Pragma_malformed);
119     return;
120   }
121 
122   // Remember the string.
123   std::string StrVal = getSpelling(Tok);
124 
125   // Read the ')'.
126   Lex(Tok);
127   if (Tok.isNot(tok::r_paren)) {
128     Diag(PragmaLoc, diag::err__Pragma_malformed);
129     return;
130   }
131 
132   SourceLocation RParenLoc = Tok.getLocation();
133 
134   // The _Pragma is lexically sound.  Destringize according to C99 6.10.9.1:
135   // "The string literal is destringized by deleting the L prefix, if present,
136   // deleting the leading and trailing double-quotes, replacing each escape
137   // sequence \" by a double-quote, and replacing each escape sequence \\ by a
138   // single backslash."
139   if (StrVal[0] == 'L')  // Remove L prefix.
140     StrVal.erase(StrVal.begin());
141   assert(StrVal[0] == '"' && StrVal[StrVal.size()-1] == '"' &&
142          "Invalid string token!");
143 
144   // Remove the front quote, replacing it with a space, so that the pragma
145   // contents appear to have a space before them.
146   StrVal[0] = ' ';
147 
148   // Replace the terminating quote with a \n.
149   StrVal[StrVal.size()-1] = '\n';
150 
151   // Remove escaped quotes and escapes.
152   for (unsigned i = 0, e = StrVal.size(); i != e-1; ++i) {
153     if (StrVal[i] == '\\' &&
154         (StrVal[i+1] == '\\' || StrVal[i+1] == '"')) {
155       // \\ -> '\' and \" -> '"'.
156       StrVal.erase(StrVal.begin()+i);
157       --e;
158     }
159   }
160 
161   // Plop the string (including the newline and trailing null) into a buffer
162   // where we can lex it.
163   Token TmpTok;
164   TmpTok.startToken();
165   CreateString(&StrVal[0], StrVal.size(), TmpTok);
166   SourceLocation TokLoc = TmpTok.getLocation();
167 
168   // Make and enter a lexer object so that we lex and expand the tokens just
169   // like any others.
170   Lexer *TL = Lexer::Create_PragmaLexer(TokLoc, PragmaLoc, RParenLoc,
171                                         StrVal.size(), *this);
172 
173   EnterSourceFileWithLexer(TL, 0);
174 
175   // With everything set up, lex this as a #pragma directive.
176   HandlePragmaDirective();
177 
178   // Finally, return whatever came after the pragma directive.
179   return Lex(Tok);
180 }
181 
182 
183 
184 /// HandlePragmaOnce - Handle #pragma once.  OnceTok is the 'once'.
185 ///
186 void Preprocessor::HandlePragmaOnce(Token &OnceTok) {
187   if (isInPrimaryFile()) {
188     Diag(OnceTok, diag::pp_pragma_once_in_main_file);
189     return;
190   }
191 
192   // Get the current file lexer we're looking at.  Ignore _Pragma 'files' etc.
193   // Mark the file as a once-only file now.
194   HeaderInfo.MarkFileIncludeOnce(getCurrentFileLexer()->getFileEntry());
195 }
196 
197 void Preprocessor::HandlePragmaMark() {
198   assert(CurPPLexer && "No current lexer?");
199   if (CurLexer)
200     CurLexer->ReadToEndOfLine();
201   else
202     CurPTHLexer->DiscardToEndOfLine();
203 }
204 
205 
206 /// HandlePragmaPoison - Handle #pragma GCC poison.  PoisonTok is the 'poison'.
207 ///
208 void Preprocessor::HandlePragmaPoison(Token &PoisonTok) {
209   Token Tok;
210 
211   while (1) {
212     // Read the next token to poison.  While doing this, pretend that we are
213     // skipping while reading the identifier to poison.
214     // This avoids errors on code like:
215     //   #pragma GCC poison X
216     //   #pragma GCC poison X
217     if (CurPPLexer) CurPPLexer->LexingRawMode = true;
218     LexUnexpandedToken(Tok);
219     if (CurPPLexer) CurPPLexer->LexingRawMode = false;
220 
221     // If we reached the end of line, we're done.
222     if (Tok.is(tok::eom)) return;
223 
224     // Can only poison identifiers.
225     if (Tok.isNot(tok::identifier)) {
226       Diag(Tok, diag::err_pp_invalid_poison);
227       return;
228     }
229 
230     // Look up the identifier info for the token.  We disabled identifier lookup
231     // by saying we're skipping contents, so we need to do this manually.
232     IdentifierInfo *II = LookUpIdentifierInfo(Tok);
233 
234     // Already poisoned.
235     if (II->isPoisoned()) continue;
236 
237     // If this is a macro identifier, emit a warning.
238     if (II->hasMacroDefinition())
239       Diag(Tok, diag::pp_poisoning_existing_macro);
240 
241     // Finally, poison it!
242     II->setIsPoisoned();
243   }
244 }
245 
246 /// HandlePragmaSystemHeader - Implement #pragma GCC system_header.  We know
247 /// that the whole directive has been parsed.
248 void Preprocessor::HandlePragmaSystemHeader(Token &SysHeaderTok) {
249   if (isInPrimaryFile()) {
250     Diag(SysHeaderTok, diag::pp_pragma_sysheader_in_main_file);
251     return;
252   }
253 
254   // Get the current file lexer we're looking at.  Ignore _Pragma 'files' etc.
255   PreprocessorLexer *TheLexer = getCurrentFileLexer();
256 
257   // Mark the file as a system header.
258   HeaderInfo.MarkFileSystemHeader(TheLexer->getFileEntry());
259 
260 
261   PresumedLoc PLoc = SourceMgr.getPresumedLoc(SysHeaderTok.getLocation());
262   unsigned FilenameLen = strlen(PLoc.getFilename());
263   unsigned FilenameID = SourceMgr.getLineTableFilenameID(PLoc.getFilename(),
264                                                          FilenameLen);
265 
266   // Emit a line marker.  This will change any source locations from this point
267   // forward to realize they are in a system header.
268   // Create a line note with this information.
269   SourceMgr.AddLineNote(SysHeaderTok.getLocation(), PLoc.getLine(), FilenameID,
270                         false, false, true, false);
271 
272   // Notify the client, if desired, that we are in a new source file.
273   if (Callbacks)
274     Callbacks->FileChanged(SysHeaderTok.getLocation(),
275                            PPCallbacks::SystemHeaderPragma, SrcMgr::C_System);
276 }
277 
278 /// HandlePragmaDependency - Handle #pragma GCC dependency "foo" blah.
279 ///
280 void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
281   Token FilenameTok;
282   CurPPLexer->LexIncludeFilename(FilenameTok);
283 
284   // If the token kind is EOM, the error has already been diagnosed.
285   if (FilenameTok.is(tok::eom))
286     return;
287 
288   // Reserve a buffer to get the spelling.
289   llvm::SmallVector<char, 128> FilenameBuffer;
290   FilenameBuffer.resize(FilenameTok.getLength());
291 
292   const char *FilenameStart = &FilenameBuffer[0];
293   unsigned Len = getSpelling(FilenameTok, FilenameStart);
294   const char *FilenameEnd = FilenameStart+Len;
295   bool isAngled = GetIncludeFilenameSpelling(FilenameTok.getLocation(),
296                                              FilenameStart, FilenameEnd);
297   // If GetIncludeFilenameSpelling set the start ptr to null, there was an
298   // error.
299   if (FilenameStart == 0)
300     return;
301 
302   // Search include directories for this file.
303   const DirectoryLookup *CurDir;
304   const FileEntry *File = LookupFile(FilenameStart, FilenameEnd,
305                                      isAngled, 0, CurDir);
306   if (File == 0) {
307     Diag(FilenameTok, diag::err_pp_file_not_found)
308       << std::string(FilenameStart, FilenameEnd);
309     return;
310   }
311 
312   const FileEntry *CurFile = getCurrentFileLexer()->getFileEntry();
313 
314   // If this file is older than the file it depends on, emit a diagnostic.
315   if (CurFile && CurFile->getModificationTime() < File->getModificationTime()) {
316     // Lex tokens at the end of the message and include them in the message.
317     std::string Message;
318     Lex(DependencyTok);
319     while (DependencyTok.isNot(tok::eom)) {
320       Message += getSpelling(DependencyTok) + " ";
321       Lex(DependencyTok);
322     }
323 
324     Message.erase(Message.end()-1);
325     Diag(FilenameTok, diag::pp_out_of_date_dependency) << Message;
326   }
327 }
328 
329 /// HandlePragmaComment - Handle the microsoft #pragma comment extension.  The
330 /// syntax is:
331 ///   #pragma comment(linker, "foo")
332 /// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
333 /// "foo" is a string, which is fully macro expanded, and permits string
334 /// concatenation, embedded escape characters etc.  See MSDN for more details.
335 void Preprocessor::HandlePragmaComment(Token &Tok) {
336   SourceLocation CommentLoc = Tok.getLocation();
337   Lex(Tok);
338   if (Tok.isNot(tok::l_paren)) {
339     Diag(CommentLoc, diag::err_pragma_comment_malformed);
340     return;
341   }
342 
343   // Read the identifier.
344   Lex(Tok);
345   if (Tok.isNot(tok::identifier)) {
346     Diag(CommentLoc, diag::err_pragma_comment_malformed);
347     return;
348   }
349 
350   // Verify that this is one of the 5 whitelisted options.
351   // FIXME: warn that 'exestr' is deprecated.
352   const IdentifierInfo *II = Tok.getIdentifierInfo();
353   if (!II->isStr("compiler") && !II->isStr("exestr") && !II->isStr("lib") &&
354       !II->isStr("linker") && !II->isStr("user")) {
355     Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
356     return;
357   }
358 
359   // Read the optional string if present.
360   Lex(Tok);
361   std::string ArgumentString;
362   if (Tok.is(tok::comma)) {
363     Lex(Tok); // eat the comma.
364 
365     // We need at least one string.
366     if (Tok.isNot(tok::string_literal)) {
367       Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
368       return;
369     }
370 
371     // String concatenation allows multiple strings, which can even come from
372     // macro expansion.
373     // "foo " "bar" "Baz"
374     llvm::SmallVector<Token, 4> StrToks;
375     while (Tok.is(tok::string_literal)) {
376       StrToks.push_back(Tok);
377       Lex(Tok);
378     }
379 
380     // Concatenate and parse the strings.
381     StringLiteralParser Literal(&StrToks[0], StrToks.size(), *this);
382     assert(!Literal.AnyWide && "Didn't allow wide strings in");
383     if (Literal.hadError)
384       return;
385     if (Literal.Pascal) {
386       Diag(StrToks[0].getLocation(), diag::err_pragma_comment_malformed);
387       return;
388     }
389 
390     ArgumentString = std::string(Literal.GetString(),
391                                  Literal.GetString()+Literal.GetStringLength());
392   }
393 
394   // FIXME: If the kind is "compiler" warn if the string is present (it is
395   // ignored).
396   // FIXME: 'lib' requires a comment string.
397   // FIXME: 'linker' requires a comment string, and has a specific list of
398   // things that are allowable.
399 
400   if (Tok.isNot(tok::r_paren)) {
401     Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
402     return;
403   }
404   Lex(Tok);  // eat the r_paren.
405 
406   if (Tok.isNot(tok::eom)) {
407     Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
408     return;
409   }
410 
411   // If the pragma is lexically sound, notify any interested PPCallbacks.
412   if (Callbacks)
413     Callbacks->PragmaComment(CommentLoc, II, ArgumentString);
414 }
415 
416 
417 
418 
419 /// AddPragmaHandler - Add the specified pragma handler to the preprocessor.
420 /// If 'Namespace' is non-null, then it is a token required to exist on the
421 /// pragma line before the pragma string starts, e.g. "STDC" or "GCC".
422 void Preprocessor::AddPragmaHandler(const char *Namespace,
423                                     PragmaHandler *Handler) {
424   PragmaNamespace *InsertNS = PragmaHandlers;
425 
426   // If this is specified to be in a namespace, step down into it.
427   if (Namespace) {
428     IdentifierInfo *NSID = getIdentifierInfo(Namespace);
429 
430     // If there is already a pragma handler with the name of this namespace,
431     // we either have an error (directive with the same name as a namespace) or
432     // we already have the namespace to insert into.
433     if (PragmaHandler *Existing = PragmaHandlers->FindHandler(NSID)) {
434       InsertNS = Existing->getIfNamespace();
435       assert(InsertNS != 0 && "Cannot have a pragma namespace and pragma"
436              " handler with the same name!");
437     } else {
438       // Otherwise, this namespace doesn't exist yet, create and insert the
439       // handler for it.
440       InsertNS = new PragmaNamespace(NSID);
441       PragmaHandlers->AddPragma(InsertNS);
442     }
443   }
444 
445   // Check to make sure we don't already have a pragma for this identifier.
446   assert(!InsertNS->FindHandler(Handler->getName()) &&
447          "Pragma handler already exists for this identifier!");
448   InsertNS->AddPragma(Handler);
449 }
450 
451 /// RemovePragmaHandler - Remove the specific pragma handler from the
452 /// preprocessor. If \arg Namespace is non-null, then it should be the
453 /// namespace that \arg Handler was added to. It is an error to remove
454 /// a handler that has not been registered.
455 void Preprocessor::RemovePragmaHandler(const char *Namespace,
456                                        PragmaHandler *Handler) {
457   PragmaNamespace *NS = PragmaHandlers;
458 
459   // If this is specified to be in a namespace, step down into it.
460   if (Namespace) {
461     IdentifierInfo *NSID = getIdentifierInfo(Namespace);
462     PragmaHandler *Existing = PragmaHandlers->FindHandler(NSID);
463     assert(Existing && "Namespace containing handler does not exist!");
464 
465     NS = Existing->getIfNamespace();
466     assert(NS && "Invalid namespace, registered as a regular pragma handler!");
467   }
468 
469   NS->RemovePragmaHandler(Handler);
470 
471   // If this is a non-default namespace and it is now empty, remove
472   // it.
473   if (NS != PragmaHandlers && NS->IsEmpty())
474     PragmaHandlers->RemovePragmaHandler(NS);
475 }
476 
477 namespace {
478 /// PragmaOnceHandler - "#pragma once" marks the file as atomically included.
479 struct PragmaOnceHandler : public PragmaHandler {
480   PragmaOnceHandler(const IdentifierInfo *OnceID) : PragmaHandler(OnceID) {}
481   virtual void HandlePragma(Preprocessor &PP, Token &OnceTok) {
482     PP.CheckEndOfDirective("pragma once");
483     PP.HandlePragmaOnce(OnceTok);
484   }
485 };
486 
487 /// PragmaMarkHandler - "#pragma mark ..." is ignored by the compiler, and the
488 /// rest of the line is not lexed.
489 struct PragmaMarkHandler : public PragmaHandler {
490   PragmaMarkHandler(const IdentifierInfo *MarkID) : PragmaHandler(MarkID) {}
491   virtual void HandlePragma(Preprocessor &PP, Token &MarkTok) {
492     PP.HandlePragmaMark();
493   }
494 };
495 
496 /// PragmaPoisonHandler - "#pragma poison x" marks x as not usable.
497 struct PragmaPoisonHandler : public PragmaHandler {
498   PragmaPoisonHandler(const IdentifierInfo *ID) : PragmaHandler(ID) {}
499   virtual void HandlePragma(Preprocessor &PP, Token &PoisonTok) {
500     PP.HandlePragmaPoison(PoisonTok);
501   }
502 };
503 
504 /// PragmaSystemHeaderHandler - "#pragma system_header" marks the current file
505 /// as a system header, which silences warnings in it.
506 struct PragmaSystemHeaderHandler : public PragmaHandler {
507   PragmaSystemHeaderHandler(const IdentifierInfo *ID) : PragmaHandler(ID) {}
508   virtual void HandlePragma(Preprocessor &PP, Token &SHToken) {
509     PP.HandlePragmaSystemHeader(SHToken);
510     PP.CheckEndOfDirective("pragma");
511   }
512 };
513 struct PragmaDependencyHandler : public PragmaHandler {
514   PragmaDependencyHandler(const IdentifierInfo *ID) : PragmaHandler(ID) {}
515   virtual void HandlePragma(Preprocessor &PP, Token &DepToken) {
516     PP.HandlePragmaDependency(DepToken);
517   }
518 };
519 
520 /// PragmaDiagnosticHandler - e.g. '#pragma GCC diagnostic ignored "-Wformat"'
521 /// Since clang's diagnostic supports extended functionality beyond GCC's
522 /// the constructor takes a clangMode flag to tell it whether or not to allow
523 /// clang's extended functionality, or whether to reject it.
524 struct PragmaDiagnosticHandler : public PragmaHandler {
525 private:
526   const bool ClangMode;
527 public:
528   PragmaDiagnosticHandler(const IdentifierInfo *ID,
529                           const bool clangMode) : PragmaHandler(ID),
530                                                   ClangMode(clangMode) {}
531   virtual void HandlePragma(Preprocessor &PP, Token &DiagToken) {
532     Token Tok;
533     PP.LexUnexpandedToken(Tok);
534     if (Tok.isNot(tok::identifier)) {
535       unsigned Diag = ClangMode ? diag::warn_pragma_diagnostic_clang_invalid
536                                  : diag::warn_pragma_diagnostic_gcc_invalid;
537       PP.Diag(Tok, Diag);
538       return;
539     }
540     IdentifierInfo *II = Tok.getIdentifierInfo();
541 
542     diag::Mapping Map;
543     if (II->isStr("warning"))
544       Map = diag::MAP_WARNING;
545     else if (II->isStr("error"))
546       Map = diag::MAP_ERROR;
547     else if (II->isStr("ignored"))
548       Map = diag::MAP_IGNORE;
549     else if (II->isStr("fatal"))
550       Map = diag::MAP_FATAL;
551     else if (ClangMode) {
552       if (II->isStr("pop")) {
553         if(!PP.getDiagnostics().popMappings())
554           PP.Diag(Tok, diag::warn_pragma_diagnostic_clang_cannot_ppp);
555         return;
556       }
557 
558       if (II->isStr("push")) {
559         PP.getDiagnostics().pushMappings();
560 				return;
561       }
562 
563       PP.Diag(Tok, diag::warn_pragma_diagnostic_clang_invalid);
564       return;
565     } else {
566       PP.Diag(Tok, diag::warn_pragma_diagnostic_gcc_invalid);
567       return;
568     }
569 
570     PP.LexUnexpandedToken(Tok);
571 
572     // We need at least one string.
573     if (Tok.isNot(tok::string_literal)) {
574       PP.Diag(Tok.getLocation(), diag::warn_pragma_diagnostic_invalid_token);
575       return;
576     }
577 
578     // String concatenation allows multiple strings, which can even come from
579     // macro expansion.
580     // "foo " "bar" "Baz"
581     llvm::SmallVector<Token, 4> StrToks;
582     while (Tok.is(tok::string_literal)) {
583       StrToks.push_back(Tok);
584       PP.LexUnexpandedToken(Tok);
585     }
586 
587     if (Tok.isNot(tok::eom)) {
588       PP.Diag(Tok.getLocation(), diag::warn_pragma_diagnostic_invalid_token);
589       return;
590     }
591 
592     // Concatenate and parse the strings.
593     StringLiteralParser Literal(&StrToks[0], StrToks.size(), PP);
594     assert(!Literal.AnyWide && "Didn't allow wide strings in");
595     if (Literal.hadError)
596       return;
597     if (Literal.Pascal) {
598       unsigned Diag = ClangMode ? diag::warn_pragma_diagnostic_clang_invalid
599                                  : diag::warn_pragma_diagnostic_gcc_invalid;
600       PP.Diag(Tok, Diag);
601       return;
602     }
603 
604     std::string WarningName(Literal.GetString(),
605                             Literal.GetString()+Literal.GetStringLength());
606 
607     if (WarningName.size() < 3 || WarningName[0] != '-' ||
608         WarningName[1] != 'W') {
609       PP.Diag(StrToks[0].getLocation(),
610               diag::warn_pragma_diagnostic_invalid_option);
611       return;
612     }
613 
614     if (PP.getDiagnostics().setDiagnosticGroupMapping(WarningName.c_str()+2,
615                                                       Map))
616       PP.Diag(StrToks[0].getLocation(),
617               diag::warn_pragma_diagnostic_unknown_warning) << WarningName;
618   }
619 };
620 
621 /// PragmaCommentHandler - "#pragma comment ...".
622 struct PragmaCommentHandler : public PragmaHandler {
623   PragmaCommentHandler(const IdentifierInfo *ID) : PragmaHandler(ID) {}
624   virtual void HandlePragma(Preprocessor &PP, Token &CommentTok) {
625     PP.HandlePragmaComment(CommentTok);
626   }
627 };
628 
629 // Pragma STDC implementations.
630 
631 enum STDCSetting {
632   STDC_ON, STDC_OFF, STDC_DEFAULT, STDC_INVALID
633 };
634 
635 static STDCSetting LexOnOffSwitch(Preprocessor &PP) {
636   Token Tok;
637   PP.LexUnexpandedToken(Tok);
638 
639   if (Tok.isNot(tok::identifier)) {
640     PP.Diag(Tok, diag::ext_stdc_pragma_syntax);
641     return STDC_INVALID;
642   }
643   IdentifierInfo *II = Tok.getIdentifierInfo();
644   STDCSetting Result;
645   if (II->isStr("ON"))
646     Result = STDC_ON;
647   else if (II->isStr("OFF"))
648     Result = STDC_OFF;
649   else if (II->isStr("DEFAULT"))
650     Result = STDC_DEFAULT;
651   else {
652     PP.Diag(Tok, diag::ext_stdc_pragma_syntax);
653     return STDC_INVALID;
654   }
655 
656   // Verify that this is followed by EOM.
657   PP.LexUnexpandedToken(Tok);
658   if (Tok.isNot(tok::eom))
659     PP.Diag(Tok, diag::ext_stdc_pragma_syntax_eom);
660   return Result;
661 }
662 
663 /// PragmaSTDC_FP_CONTRACTHandler - "#pragma STDC FP_CONTRACT ...".
664 struct PragmaSTDC_FP_CONTRACTHandler : public PragmaHandler {
665   PragmaSTDC_FP_CONTRACTHandler(const IdentifierInfo *ID) : PragmaHandler(ID) {}
666   virtual void HandlePragma(Preprocessor &PP, Token &Tok) {
667     // We just ignore the setting of FP_CONTRACT. Since we don't do contractions
668     // at all, our default is OFF and setting it to ON is an optimization hint
669     // we can safely ignore.  When we support -ffma or something, we would need
670     // to diagnose that we are ignoring FMA.
671     LexOnOffSwitch(PP);
672   }
673 };
674 
675 /// PragmaSTDC_FENV_ACCESSHandler - "#pragma STDC FENV_ACCESS ...".
676 struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {
677   PragmaSTDC_FENV_ACCESSHandler(const IdentifierInfo *ID) : PragmaHandler(ID) {}
678   virtual void HandlePragma(Preprocessor &PP, Token &Tok) {
679     if (LexOnOffSwitch(PP) == STDC_ON)
680       PP.Diag(Tok, diag::warn_stdc_fenv_access_not_supported);
681   }
682 };
683 
684 /// PragmaSTDC_CX_LIMITED_RANGEHandler - "#pragma STDC CX_LIMITED_RANGE ...".
685 struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {
686   PragmaSTDC_CX_LIMITED_RANGEHandler(const IdentifierInfo *ID)
687     : PragmaHandler(ID) {}
688   virtual void HandlePragma(Preprocessor &PP, Token &Tok) {
689     LexOnOffSwitch(PP);
690   }
691 };
692 
693 /// PragmaSTDC_UnknownHandler - "#pragma STDC ...".
694 struct PragmaSTDC_UnknownHandler : public PragmaHandler {
695   PragmaSTDC_UnknownHandler() : PragmaHandler(0) {}
696   virtual void HandlePragma(Preprocessor &PP, Token &UnknownTok) {
697     // C99 6.10.6p2, unknown forms are not allowed.
698     PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored);
699   }
700 };
701 
702 }  // end anonymous namespace
703 
704 
705 /// RegisterBuiltinPragmas - Install the standard preprocessor pragmas:
706 /// #pragma GCC poison/system_header/dependency and #pragma once.
707 void Preprocessor::RegisterBuiltinPragmas() {
708   AddPragmaHandler(0, new PragmaOnceHandler(getIdentifierInfo("once")));
709   AddPragmaHandler(0, new PragmaMarkHandler(getIdentifierInfo("mark")));
710 
711   // #pragma GCC ...
712   AddPragmaHandler("GCC", new PragmaPoisonHandler(getIdentifierInfo("poison")));
713   AddPragmaHandler("GCC", new PragmaSystemHeaderHandler(
714                                           getIdentifierInfo("system_header")));
715   AddPragmaHandler("GCC", new PragmaDependencyHandler(
716                                           getIdentifierInfo("dependency")));
717   AddPragmaHandler("GCC", new PragmaDiagnosticHandler(
718                                               getIdentifierInfo("diagnostic"),
719                                               false));
720   // #pragma clang ...
721   AddPragmaHandler("clang", new PragmaPoisonHandler(
722                                           getIdentifierInfo("poison")));
723   AddPragmaHandler("clang", new PragmaSystemHeaderHandler(
724                                           getIdentifierInfo("system_header")));
725   AddPragmaHandler("clang", new PragmaDependencyHandler(
726                                           getIdentifierInfo("dependency")));
727   AddPragmaHandler("clang", new PragmaDiagnosticHandler(
728                                           getIdentifierInfo("diagnostic"),
729                                           true));
730 
731   AddPragmaHandler("STDC", new PragmaSTDC_FP_CONTRACTHandler(
732                                              getIdentifierInfo("FP_CONTRACT")));
733   AddPragmaHandler("STDC", new PragmaSTDC_FENV_ACCESSHandler(
734                                              getIdentifierInfo("FENV_ACCESS")));
735   AddPragmaHandler("STDC", new PragmaSTDC_CX_LIMITED_RANGEHandler(
736                                         getIdentifierInfo("CX_LIMITED_RANGE")));
737   AddPragmaHandler("STDC", new PragmaSTDC_UnknownHandler());
738 
739   // MS extensions.
740   if (Features.Microsoft)
741     AddPragmaHandler(0, new PragmaCommentHandler(getIdentifierInfo("comment")));
742 }
743