• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
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 language specific #pragma handlers.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "ParsePragma.h"
15 #include "clang/Lex/Preprocessor.h"
16 #include "clang/Parse/ParseDiagnostic.h"
17 #include "clang/Parse/Parser.h"
18 using namespace clang;
19 
20 /// \brief Handle the annotation token produced for #pragma unused(...)
21 ///
22 /// Each annot_pragma_unused is followed by the argument token so e.g.
23 /// "#pragma unused(x,y)" becomes:
24 /// annot_pragma_unused 'x' annot_pragma_unused 'y'
HandlePragmaUnused()25 void Parser::HandlePragmaUnused() {
26   assert(Tok.is(tok::annot_pragma_unused));
27   SourceLocation UnusedLoc = ConsumeToken();
28   Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
29   ConsumeToken(); // The argument token.
30 }
31 
HandlePragmaVisibility()32 void Parser::HandlePragmaVisibility() {
33   assert(Tok.is(tok::annot_pragma_vis));
34   const IdentifierInfo *VisType =
35     static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
36   SourceLocation VisLoc = ConsumeToken();
37   Actions.ActOnPragmaVisibility(VisType, VisLoc);
38 }
39 
40 struct PragmaPackInfo {
41   Sema::PragmaPackKind Kind;
42   IdentifierInfo *Name;
43   Token Alignment;
44   SourceLocation LParenLoc;
45   SourceLocation RParenLoc;
46 };
47 
HandlePragmaPack()48 void Parser::HandlePragmaPack() {
49   assert(Tok.is(tok::annot_pragma_pack));
50   PragmaPackInfo *Info =
51     static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
52   SourceLocation PragmaLoc = ConsumeToken();
53   ExprResult Alignment;
54   if (Info->Alignment.is(tok::numeric_constant)) {
55     Alignment = Actions.ActOnNumericConstant(Info->Alignment);
56     if (Alignment.isInvalid())
57       return;
58   }
59   Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc,
60                           Info->LParenLoc, Info->RParenLoc);
61 }
62 
HandlePragmaMSStruct()63 void Parser::HandlePragmaMSStruct() {
64   assert(Tok.is(tok::annot_pragma_msstruct));
65   Sema::PragmaMSStructKind Kind =
66     static_cast<Sema::PragmaMSStructKind>(
67     reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
68   Actions.ActOnPragmaMSStruct(Kind);
69   ConsumeToken(); // The annotation token.
70 }
71 
HandlePragmaAlign()72 void Parser::HandlePragmaAlign() {
73   assert(Tok.is(tok::annot_pragma_align));
74   Sema::PragmaOptionsAlignKind Kind =
75     static_cast<Sema::PragmaOptionsAlignKind>(
76     reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
77   SourceLocation PragmaLoc = ConsumeToken();
78   Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
79 }
80 
HandlePragmaWeak()81 void Parser::HandlePragmaWeak() {
82   assert(Tok.is(tok::annot_pragma_weak));
83   SourceLocation PragmaLoc = ConsumeToken();
84   Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
85                             Tok.getLocation());
86   ConsumeToken(); // The weak name.
87 }
88 
HandlePragmaWeakAlias()89 void Parser::HandlePragmaWeakAlias() {
90   assert(Tok.is(tok::annot_pragma_weakalias));
91   SourceLocation PragmaLoc = ConsumeToken();
92   IdentifierInfo *WeakName = Tok.getIdentifierInfo();
93   SourceLocation WeakNameLoc = Tok.getLocation();
94   ConsumeToken();
95   IdentifierInfo *AliasName = Tok.getIdentifierInfo();
96   SourceLocation AliasNameLoc = Tok.getLocation();
97   ConsumeToken();
98   Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
99                                WeakNameLoc, AliasNameLoc);
100 
101 }
102 
HandlePragmaRedefineExtname()103 void Parser::HandlePragmaRedefineExtname() {
104   assert(Tok.is(tok::annot_pragma_redefine_extname));
105   SourceLocation RedefLoc = ConsumeToken();
106   IdentifierInfo *RedefName = Tok.getIdentifierInfo();
107   SourceLocation RedefNameLoc = Tok.getLocation();
108   ConsumeToken();
109   IdentifierInfo *AliasName = Tok.getIdentifierInfo();
110   SourceLocation AliasNameLoc = Tok.getLocation();
111   ConsumeToken();
112   Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
113                                      RedefNameLoc, AliasNameLoc);
114 }
115 
HandlePragmaFPContract()116 void Parser::HandlePragmaFPContract() {
117   assert(Tok.is(tok::annot_pragma_fp_contract));
118   tok::OnOffSwitch OOS =
119     static_cast<tok::OnOffSwitch>(
120     reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
121   Actions.ActOnPragmaFPContract(OOS);
122   ConsumeToken(); // The annotation token.
123 }
124 
125 namespace {
126   typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
127 }
128 
HandlePragmaOpenCLExtension()129 void Parser::HandlePragmaOpenCLExtension() {
130   assert(Tok.is(tok::annot_pragma_opencl_extension));
131   OpenCLExtData data =
132       OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
133   unsigned state = data.getInt();
134   IdentifierInfo *ename = data.getPointer();
135   SourceLocation NameLoc = Tok.getLocation();
136   ConsumeToken(); // The annotation token.
137 
138   OpenCLOptions &f = Actions.getOpenCLOptions();
139   // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
140   // overriding all previously issued extension directives, but only if the
141   // behavior is set to disable."
142   if (state == 0 && ename->isStr("all")) {
143 #define OPENCLEXT(nm)   f.nm = 0;
144 #include "clang/Basic/OpenCLExtensions.def"
145   }
146 #define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
147 #include "clang/Basic/OpenCLExtensions.def"
148   else {
149     PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
150     return;
151   }
152 }
153 
154 // #pragma GCC visibility comes in two variants:
155 //   'push' '(' [visibility] ')'
156 //   'pop'
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & VisTok)157 void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
158                                               PragmaIntroducerKind Introducer,
159                                               Token &VisTok) {
160   SourceLocation VisLoc = VisTok.getLocation();
161 
162   Token Tok;
163   PP.LexUnexpandedToken(Tok);
164 
165   const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
166 
167   const IdentifierInfo *VisType;
168   if (PushPop && PushPop->isStr("pop")) {
169     VisType = 0;
170   } else if (PushPop && PushPop->isStr("push")) {
171     PP.LexUnexpandedToken(Tok);
172     if (Tok.isNot(tok::l_paren)) {
173       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
174         << "visibility";
175       return;
176     }
177     PP.LexUnexpandedToken(Tok);
178     VisType = Tok.getIdentifierInfo();
179     if (!VisType) {
180       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
181         << "visibility";
182       return;
183     }
184     PP.LexUnexpandedToken(Tok);
185     if (Tok.isNot(tok::r_paren)) {
186       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
187         << "visibility";
188       return;
189     }
190   } else {
191     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
192       << "visibility";
193     return;
194   }
195   PP.LexUnexpandedToken(Tok);
196   if (Tok.isNot(tok::eod)) {
197     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
198       << "visibility";
199     return;
200   }
201 
202   Token *Toks = new Token[1];
203   Toks[0].startToken();
204   Toks[0].setKind(tok::annot_pragma_vis);
205   Toks[0].setLocation(VisLoc);
206   Toks[0].setAnnotationValue(
207                           const_cast<void*>(static_cast<const void*>(VisType)));
208   PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
209                       /*OwnsTokens=*/true);
210 }
211 
212 // #pragma pack(...) comes in the following delicious flavors:
213 //   pack '(' [integer] ')'
214 //   pack '(' 'show' ')'
215 //   pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & PackTok)216 void PragmaPackHandler::HandlePragma(Preprocessor &PP,
217                                      PragmaIntroducerKind Introducer,
218                                      Token &PackTok) {
219   SourceLocation PackLoc = PackTok.getLocation();
220 
221   Token Tok;
222   PP.Lex(Tok);
223   if (Tok.isNot(tok::l_paren)) {
224     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
225     return;
226   }
227 
228   Sema::PragmaPackKind Kind = Sema::PPK_Default;
229   IdentifierInfo *Name = 0;
230   Token Alignment;
231   Alignment.startToken();
232   SourceLocation LParenLoc = Tok.getLocation();
233   PP.Lex(Tok);
234   if (Tok.is(tok::numeric_constant)) {
235     Alignment = Tok;
236 
237     PP.Lex(Tok);
238 
239     // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
240     // the push/pop stack.
241     // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
242     if (PP.getLangOpts().ApplePragmaPack)
243       Kind = Sema::PPK_Push;
244   } else if (Tok.is(tok::identifier)) {
245     const IdentifierInfo *II = Tok.getIdentifierInfo();
246     if (II->isStr("show")) {
247       Kind = Sema::PPK_Show;
248       PP.Lex(Tok);
249     } else {
250       if (II->isStr("push")) {
251         Kind = Sema::PPK_Push;
252       } else if (II->isStr("pop")) {
253         Kind = Sema::PPK_Pop;
254       } else {
255         PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
256         return;
257       }
258       PP.Lex(Tok);
259 
260       if (Tok.is(tok::comma)) {
261         PP.Lex(Tok);
262 
263         if (Tok.is(tok::numeric_constant)) {
264           Alignment = Tok;
265 
266           PP.Lex(Tok);
267         } else if (Tok.is(tok::identifier)) {
268           Name = Tok.getIdentifierInfo();
269           PP.Lex(Tok);
270 
271           if (Tok.is(tok::comma)) {
272             PP.Lex(Tok);
273 
274             if (Tok.isNot(tok::numeric_constant)) {
275               PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
276               return;
277             }
278 
279             Alignment = Tok;
280 
281             PP.Lex(Tok);
282           }
283         } else {
284           PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
285           return;
286         }
287       }
288     }
289   } else if (PP.getLangOpts().ApplePragmaPack) {
290     // In MSVC/gcc, #pragma pack() resets the alignment without affecting
291     // the push/pop stack.
292     // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
293     Kind = Sema::PPK_Pop;
294   }
295 
296   if (Tok.isNot(tok::r_paren)) {
297     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
298     return;
299   }
300 
301   SourceLocation RParenLoc = Tok.getLocation();
302   PP.Lex(Tok);
303   if (Tok.isNot(tok::eod)) {
304     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
305     return;
306   }
307 
308   PragmaPackInfo *Info =
309     (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate(
310       sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>());
311   new (Info) PragmaPackInfo();
312   Info->Kind = Kind;
313   Info->Name = Name;
314   Info->Alignment = Alignment;
315   Info->LParenLoc = LParenLoc;
316   Info->RParenLoc = RParenLoc;
317 
318   Token *Toks =
319     (Token*) PP.getPreprocessorAllocator().Allocate(
320       sizeof(Token) * 1, llvm::alignOf<Token>());
321   new (Toks) Token();
322   Toks[0].startToken();
323   Toks[0].setKind(tok::annot_pragma_pack);
324   Toks[0].setLocation(PackLoc);
325   Toks[0].setAnnotationValue(static_cast<void*>(Info));
326   PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
327                       /*OwnsTokens=*/false);
328 }
329 
330 // #pragma ms_struct on
331 // #pragma ms_struct off
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & MSStructTok)332 void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
333                                          PragmaIntroducerKind Introducer,
334                                          Token &MSStructTok) {
335   Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
336 
337   Token Tok;
338   PP.Lex(Tok);
339   if (Tok.isNot(tok::identifier)) {
340     PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
341     return;
342   }
343   const IdentifierInfo *II = Tok.getIdentifierInfo();
344   if (II->isStr("on")) {
345     Kind = Sema::PMSST_ON;
346     PP.Lex(Tok);
347   }
348   else if (II->isStr("off") || II->isStr("reset"))
349     PP.Lex(Tok);
350   else {
351     PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
352     return;
353   }
354 
355   if (Tok.isNot(tok::eod)) {
356     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
357       << "ms_struct";
358     return;
359   }
360 
361   Token *Toks =
362     (Token*) PP.getPreprocessorAllocator().Allocate(
363       sizeof(Token) * 1, llvm::alignOf<Token>());
364   new (Toks) Token();
365   Toks[0].startToken();
366   Toks[0].setKind(tok::annot_pragma_msstruct);
367   Toks[0].setLocation(MSStructTok.getLocation());
368   Toks[0].setAnnotationValue(reinterpret_cast<void*>(
369                              static_cast<uintptr_t>(Kind)));
370   PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
371                       /*OwnsTokens=*/false);
372 }
373 
374 // #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
375 // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
ParseAlignPragma(Preprocessor & PP,Token & FirstTok,bool IsOptions)376 static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
377                              bool IsOptions) {
378   Token Tok;
379 
380   if (IsOptions) {
381     PP.Lex(Tok);
382     if (Tok.isNot(tok::identifier) ||
383         !Tok.getIdentifierInfo()->isStr("align")) {
384       PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
385       return;
386     }
387   }
388 
389   PP.Lex(Tok);
390   if (Tok.isNot(tok::equal)) {
391     PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
392       << IsOptions;
393     return;
394   }
395 
396   PP.Lex(Tok);
397   if (Tok.isNot(tok::identifier)) {
398     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
399       << (IsOptions ? "options" : "align");
400     return;
401   }
402 
403   Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
404   const IdentifierInfo *II = Tok.getIdentifierInfo();
405   if (II->isStr("native"))
406     Kind = Sema::POAK_Native;
407   else if (II->isStr("natural"))
408     Kind = Sema::POAK_Natural;
409   else if (II->isStr("packed"))
410     Kind = Sema::POAK_Packed;
411   else if (II->isStr("power"))
412     Kind = Sema::POAK_Power;
413   else if (II->isStr("mac68k"))
414     Kind = Sema::POAK_Mac68k;
415   else if (II->isStr("reset"))
416     Kind = Sema::POAK_Reset;
417   else {
418     PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
419       << IsOptions;
420     return;
421   }
422 
423   PP.Lex(Tok);
424   if (Tok.isNot(tok::eod)) {
425     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
426       << (IsOptions ? "options" : "align");
427     return;
428   }
429 
430   Token *Toks =
431     (Token*) PP.getPreprocessorAllocator().Allocate(
432       sizeof(Token) * 1, llvm::alignOf<Token>());
433   new (Toks) Token();
434   Toks[0].startToken();
435   Toks[0].setKind(tok::annot_pragma_align);
436   Toks[0].setLocation(FirstTok.getLocation());
437   Toks[0].setAnnotationValue(reinterpret_cast<void*>(
438                              static_cast<uintptr_t>(Kind)));
439   PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
440                       /*OwnsTokens=*/false);
441 }
442 
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & AlignTok)443 void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
444                                       PragmaIntroducerKind Introducer,
445                                       Token &AlignTok) {
446   ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
447 }
448 
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & OptionsTok)449 void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
450                                         PragmaIntroducerKind Introducer,
451                                         Token &OptionsTok) {
452   ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
453 }
454 
455 // #pragma unused(identifier)
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & UnusedTok)456 void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
457                                        PragmaIntroducerKind Introducer,
458                                        Token &UnusedTok) {
459   // FIXME: Should we be expanding macros here? My guess is no.
460   SourceLocation UnusedLoc = UnusedTok.getLocation();
461 
462   // Lex the left '('.
463   Token Tok;
464   PP.Lex(Tok);
465   if (Tok.isNot(tok::l_paren)) {
466     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
467     return;
468   }
469 
470   // Lex the declaration reference(s).
471   SmallVector<Token, 5> Identifiers;
472   SourceLocation RParenLoc;
473   bool LexID = true;
474 
475   while (true) {
476     PP.Lex(Tok);
477 
478     if (LexID) {
479       if (Tok.is(tok::identifier)) {
480         Identifiers.push_back(Tok);
481         LexID = false;
482         continue;
483       }
484 
485       // Illegal token!
486       PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
487       return;
488     }
489 
490     // We are execting a ')' or a ','.
491     if (Tok.is(tok::comma)) {
492       LexID = true;
493       continue;
494     }
495 
496     if (Tok.is(tok::r_paren)) {
497       RParenLoc = Tok.getLocation();
498       break;
499     }
500 
501     // Illegal token!
502     PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
503     return;
504   }
505 
506   PP.Lex(Tok);
507   if (Tok.isNot(tok::eod)) {
508     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
509         "unused";
510     return;
511   }
512 
513   // Verify that we have a location for the right parenthesis.
514   assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
515   assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
516 
517   // For each identifier token, insert into the token stream a
518   // annot_pragma_unused token followed by the identifier token.
519   // This allows us to cache a "#pragma unused" that occurs inside an inline
520   // C++ member function.
521 
522   Token *Toks =
523     (Token*) PP.getPreprocessorAllocator().Allocate(
524       sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>());
525   for (unsigned i=0; i != Identifiers.size(); i++) {
526     Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
527     pragmaUnusedTok.startToken();
528     pragmaUnusedTok.setKind(tok::annot_pragma_unused);
529     pragmaUnusedTok.setLocation(UnusedLoc);
530     idTok = Identifiers[i];
531   }
532   PP.EnterTokenStream(Toks, 2*Identifiers.size(),
533                       /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
534 }
535 
536 // #pragma weak identifier
537 // #pragma weak identifier '=' identifier
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & WeakTok)538 void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
539                                      PragmaIntroducerKind Introducer,
540                                      Token &WeakTok) {
541   SourceLocation WeakLoc = WeakTok.getLocation();
542 
543   Token Tok;
544   PP.Lex(Tok);
545   if (Tok.isNot(tok::identifier)) {
546     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
547     return;
548   }
549 
550   Token WeakName = Tok;
551   bool HasAlias = false;
552   Token AliasName;
553 
554   PP.Lex(Tok);
555   if (Tok.is(tok::equal)) {
556     HasAlias = true;
557     PP.Lex(Tok);
558     if (Tok.isNot(tok::identifier)) {
559       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
560           << "weak";
561       return;
562     }
563     AliasName = Tok;
564     PP.Lex(Tok);
565   }
566 
567   if (Tok.isNot(tok::eod)) {
568     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
569     return;
570   }
571 
572   if (HasAlias) {
573     Token *Toks =
574       (Token*) PP.getPreprocessorAllocator().Allocate(
575         sizeof(Token) * 3, llvm::alignOf<Token>());
576     Token &pragmaUnusedTok = Toks[0];
577     pragmaUnusedTok.startToken();
578     pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
579     pragmaUnusedTok.setLocation(WeakLoc);
580     Toks[1] = WeakName;
581     Toks[2] = AliasName;
582     PP.EnterTokenStream(Toks, 3,
583                         /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
584   } else {
585     Token *Toks =
586       (Token*) PP.getPreprocessorAllocator().Allocate(
587         sizeof(Token) * 2, llvm::alignOf<Token>());
588     Token &pragmaUnusedTok = Toks[0];
589     pragmaUnusedTok.startToken();
590     pragmaUnusedTok.setKind(tok::annot_pragma_weak);
591     pragmaUnusedTok.setLocation(WeakLoc);
592     Toks[1] = WeakName;
593     PP.EnterTokenStream(Toks, 2,
594                         /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
595   }
596 }
597 
598 // #pragma redefine_extname identifier identifier
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & RedefToken)599 void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
600                                                PragmaIntroducerKind Introducer,
601                                                 Token &RedefToken) {
602   SourceLocation RedefLoc = RedefToken.getLocation();
603 
604   Token Tok;
605   PP.Lex(Tok);
606   if (Tok.isNot(tok::identifier)) {
607     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
608       "redefine_extname";
609     return;
610   }
611 
612   Token RedefName = Tok;
613   PP.Lex(Tok);
614 
615   if (Tok.isNot(tok::identifier)) {
616     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
617         << "redefine_extname";
618     return;
619   }
620 
621   Token AliasName = Tok;
622   PP.Lex(Tok);
623 
624   if (Tok.isNot(tok::eod)) {
625     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
626       "redefine_extname";
627     return;
628   }
629 
630   Token *Toks =
631     (Token*) PP.getPreprocessorAllocator().Allocate(
632       sizeof(Token) * 3, llvm::alignOf<Token>());
633   Token &pragmaRedefTok = Toks[0];
634   pragmaRedefTok.startToken();
635   pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
636   pragmaRedefTok.setLocation(RedefLoc);
637   Toks[1] = RedefName;
638   Toks[2] = AliasName;
639   PP.EnterTokenStream(Toks, 3,
640                       /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
641 }
642 
643 
644 void
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)645 PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
646                                       PragmaIntroducerKind Introducer,
647                                       Token &Tok) {
648   tok::OnOffSwitch OOS;
649   if (PP.LexOnOffSwitch(OOS))
650     return;
651 
652   Token *Toks =
653     (Token*) PP.getPreprocessorAllocator().Allocate(
654       sizeof(Token) * 1, llvm::alignOf<Token>());
655   new (Toks) Token();
656   Toks[0].startToken();
657   Toks[0].setKind(tok::annot_pragma_fp_contract);
658   Toks[0].setLocation(Tok.getLocation());
659   Toks[0].setAnnotationValue(reinterpret_cast<void*>(
660                              static_cast<uintptr_t>(OOS)));
661   PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
662                       /*OwnsTokens=*/false);
663 }
664 
665 void
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)666 PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
667                                            PragmaIntroducerKind Introducer,
668                                            Token &Tok) {
669   PP.LexUnexpandedToken(Tok);
670   if (Tok.isNot(tok::identifier)) {
671     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
672       "OPENCL";
673     return;
674   }
675   IdentifierInfo *ename = Tok.getIdentifierInfo();
676   SourceLocation NameLoc = Tok.getLocation();
677 
678   PP.Lex(Tok);
679   if (Tok.isNot(tok::colon)) {
680     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
681     return;
682   }
683 
684   PP.Lex(Tok);
685   if (Tok.isNot(tok::identifier)) {
686     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
687     return;
688   }
689   IdentifierInfo *op = Tok.getIdentifierInfo();
690 
691   unsigned state;
692   if (op->isStr("enable")) {
693     state = 1;
694   } else if (op->isStr("disable")) {
695     state = 0;
696   } else {
697     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
698     return;
699   }
700 
701   PP.Lex(Tok);
702   if (Tok.isNot(tok::eod)) {
703     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
704       "OPENCL EXTENSION";
705     return;
706   }
707 
708   OpenCLExtData data(ename, state);
709   Token *Toks =
710     (Token*) PP.getPreprocessorAllocator().Allocate(
711       sizeof(Token) * 1, llvm::alignOf<Token>());
712   new (Toks) Token();
713   Toks[0].startToken();
714   Toks[0].setKind(tok::annot_pragma_opencl_extension);
715   Toks[0].setLocation(NameLoc);
716   Toks[0].setAnnotationValue(data.getOpaqueValue());
717   PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
718                       /*OwnsTokens=*/false);
719 }
720 
721