ParsePragma.cpp revision 263508
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#include "clang/Sema/Scope.h"
19#include "llvm/ADT/StringSwitch.h"
20using namespace clang;
21
22/// \brief Handle the annotation token produced for #pragma unused(...)
23///
24/// Each annot_pragma_unused is followed by the argument token so e.g.
25/// "#pragma unused(x,y)" becomes:
26/// annot_pragma_unused 'x' annot_pragma_unused 'y'
27void Parser::HandlePragmaUnused() {
28  assert(Tok.is(tok::annot_pragma_unused));
29  SourceLocation UnusedLoc = ConsumeToken();
30  Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
31  ConsumeToken(); // The argument token.
32}
33
34void Parser::HandlePragmaVisibility() {
35  assert(Tok.is(tok::annot_pragma_vis));
36  const IdentifierInfo *VisType =
37    static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
38  SourceLocation VisLoc = ConsumeToken();
39  Actions.ActOnPragmaVisibility(VisType, VisLoc);
40}
41
42struct PragmaPackInfo {
43  Sema::PragmaPackKind Kind;
44  IdentifierInfo *Name;
45  Token Alignment;
46  SourceLocation LParenLoc;
47  SourceLocation RParenLoc;
48};
49
50void Parser::HandlePragmaPack() {
51  assert(Tok.is(tok::annot_pragma_pack));
52  PragmaPackInfo *Info =
53    static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
54  SourceLocation PragmaLoc = ConsumeToken();
55  ExprResult Alignment;
56  if (Info->Alignment.is(tok::numeric_constant)) {
57    Alignment = Actions.ActOnNumericConstant(Info->Alignment);
58    if (Alignment.isInvalid())
59      return;
60  }
61  Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc,
62                          Info->LParenLoc, Info->RParenLoc);
63}
64
65void Parser::HandlePragmaMSStruct() {
66  assert(Tok.is(tok::annot_pragma_msstruct));
67  Sema::PragmaMSStructKind Kind =
68    static_cast<Sema::PragmaMSStructKind>(
69    reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
70  Actions.ActOnPragmaMSStruct(Kind);
71  ConsumeToken(); // The annotation token.
72}
73
74void Parser::HandlePragmaAlign() {
75  assert(Tok.is(tok::annot_pragma_align));
76  Sema::PragmaOptionsAlignKind Kind =
77    static_cast<Sema::PragmaOptionsAlignKind>(
78    reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
79  SourceLocation PragmaLoc = ConsumeToken();
80  Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
81}
82
83void Parser::HandlePragmaWeak() {
84  assert(Tok.is(tok::annot_pragma_weak));
85  SourceLocation PragmaLoc = ConsumeToken();
86  Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
87                            Tok.getLocation());
88  ConsumeToken(); // The weak name.
89}
90
91void Parser::HandlePragmaWeakAlias() {
92  assert(Tok.is(tok::annot_pragma_weakalias));
93  SourceLocation PragmaLoc = ConsumeToken();
94  IdentifierInfo *WeakName = Tok.getIdentifierInfo();
95  SourceLocation WeakNameLoc = Tok.getLocation();
96  ConsumeToken();
97  IdentifierInfo *AliasName = Tok.getIdentifierInfo();
98  SourceLocation AliasNameLoc = Tok.getLocation();
99  ConsumeToken();
100  Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
101                               WeakNameLoc, AliasNameLoc);
102
103}
104
105void Parser::HandlePragmaRedefineExtname() {
106  assert(Tok.is(tok::annot_pragma_redefine_extname));
107  SourceLocation RedefLoc = ConsumeToken();
108  IdentifierInfo *RedefName = Tok.getIdentifierInfo();
109  SourceLocation RedefNameLoc = Tok.getLocation();
110  ConsumeToken();
111  IdentifierInfo *AliasName = Tok.getIdentifierInfo();
112  SourceLocation AliasNameLoc = Tok.getLocation();
113  ConsumeToken();
114  Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
115                                     RedefNameLoc, AliasNameLoc);
116}
117
118void Parser::HandlePragmaFPContract() {
119  assert(Tok.is(tok::annot_pragma_fp_contract));
120  tok::OnOffSwitch OOS =
121    static_cast<tok::OnOffSwitch>(
122    reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
123  Actions.ActOnPragmaFPContract(OOS);
124  ConsumeToken(); // The annotation token.
125}
126
127StmtResult Parser::HandlePragmaCaptured()
128{
129  assert(Tok.is(tok::annot_pragma_captured));
130  ConsumeToken();
131
132  if (Tok.isNot(tok::l_brace)) {
133    PP.Diag(Tok, diag::err_expected_lbrace);
134    return StmtError();
135  }
136
137  SourceLocation Loc = Tok.getLocation();
138
139  ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope);
140  Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
141                                   /*NumParams=*/1);
142
143  StmtResult R = ParseCompoundStatement();
144  CapturedRegionScope.Exit();
145
146  if (R.isInvalid()) {
147    Actions.ActOnCapturedRegionError();
148    return StmtError();
149  }
150
151  return Actions.ActOnCapturedRegionEnd(R.get());
152}
153
154namespace {
155  typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
156}
157
158void Parser::HandlePragmaOpenCLExtension() {
159  assert(Tok.is(tok::annot_pragma_opencl_extension));
160  OpenCLExtData data =
161      OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
162  unsigned state = data.getInt();
163  IdentifierInfo *ename = data.getPointer();
164  SourceLocation NameLoc = Tok.getLocation();
165  ConsumeToken(); // The annotation token.
166
167  OpenCLOptions &f = Actions.getOpenCLOptions();
168  // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
169  // overriding all previously issued extension directives, but only if the
170  // behavior is set to disable."
171  if (state == 0 && ename->isStr("all")) {
172#define OPENCLEXT(nm)   f.nm = 0;
173#include "clang/Basic/OpenCLExtensions.def"
174  }
175#define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
176#include "clang/Basic/OpenCLExtensions.def"
177  else {
178    PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
179    return;
180  }
181}
182
183
184
185// #pragma GCC visibility comes in two variants:
186//   'push' '(' [visibility] ')'
187//   'pop'
188void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
189                                              PragmaIntroducerKind Introducer,
190                                              Token &VisTok) {
191  SourceLocation VisLoc = VisTok.getLocation();
192
193  Token Tok;
194  PP.LexUnexpandedToken(Tok);
195
196  const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
197
198  const IdentifierInfo *VisType;
199  if (PushPop && PushPop->isStr("pop")) {
200    VisType = 0;
201  } else if (PushPop && PushPop->isStr("push")) {
202    PP.LexUnexpandedToken(Tok);
203    if (Tok.isNot(tok::l_paren)) {
204      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
205        << "visibility";
206      return;
207    }
208    PP.LexUnexpandedToken(Tok);
209    VisType = Tok.getIdentifierInfo();
210    if (!VisType) {
211      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
212        << "visibility";
213      return;
214    }
215    PP.LexUnexpandedToken(Tok);
216    if (Tok.isNot(tok::r_paren)) {
217      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
218        << "visibility";
219      return;
220    }
221  } else {
222    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
223      << "visibility";
224    return;
225  }
226  PP.LexUnexpandedToken(Tok);
227  if (Tok.isNot(tok::eod)) {
228    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
229      << "visibility";
230    return;
231  }
232
233  Token *Toks = new Token[1];
234  Toks[0].startToken();
235  Toks[0].setKind(tok::annot_pragma_vis);
236  Toks[0].setLocation(VisLoc);
237  Toks[0].setAnnotationValue(
238                          const_cast<void*>(static_cast<const void*>(VisType)));
239  PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
240                      /*OwnsTokens=*/true);
241}
242
243// #pragma pack(...) comes in the following delicious flavors:
244//   pack '(' [integer] ')'
245//   pack '(' 'show' ')'
246//   pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
247void PragmaPackHandler::HandlePragma(Preprocessor &PP,
248                                     PragmaIntroducerKind Introducer,
249                                     Token &PackTok) {
250  SourceLocation PackLoc = PackTok.getLocation();
251
252  Token Tok;
253  PP.Lex(Tok);
254  if (Tok.isNot(tok::l_paren)) {
255    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
256    return;
257  }
258
259  Sema::PragmaPackKind Kind = Sema::PPK_Default;
260  IdentifierInfo *Name = 0;
261  Token Alignment;
262  Alignment.startToken();
263  SourceLocation LParenLoc = Tok.getLocation();
264  PP.Lex(Tok);
265  if (Tok.is(tok::numeric_constant)) {
266    Alignment = Tok;
267
268    PP.Lex(Tok);
269
270    // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
271    // the push/pop stack.
272    // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
273    if (PP.getLangOpts().ApplePragmaPack)
274      Kind = Sema::PPK_Push;
275  } else if (Tok.is(tok::identifier)) {
276    const IdentifierInfo *II = Tok.getIdentifierInfo();
277    if (II->isStr("show")) {
278      Kind = Sema::PPK_Show;
279      PP.Lex(Tok);
280    } else {
281      if (II->isStr("push")) {
282        Kind = Sema::PPK_Push;
283      } else if (II->isStr("pop")) {
284        Kind = Sema::PPK_Pop;
285      } else {
286        PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
287        return;
288      }
289      PP.Lex(Tok);
290
291      if (Tok.is(tok::comma)) {
292        PP.Lex(Tok);
293
294        if (Tok.is(tok::numeric_constant)) {
295          Alignment = Tok;
296
297          PP.Lex(Tok);
298        } else if (Tok.is(tok::identifier)) {
299          Name = Tok.getIdentifierInfo();
300          PP.Lex(Tok);
301
302          if (Tok.is(tok::comma)) {
303            PP.Lex(Tok);
304
305            if (Tok.isNot(tok::numeric_constant)) {
306              PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
307              return;
308            }
309
310            Alignment = Tok;
311
312            PP.Lex(Tok);
313          }
314        } else {
315          PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
316          return;
317        }
318      }
319    }
320  } else if (PP.getLangOpts().ApplePragmaPack) {
321    // In MSVC/gcc, #pragma pack() resets the alignment without affecting
322    // the push/pop stack.
323    // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
324    Kind = Sema::PPK_Pop;
325  }
326
327  if (Tok.isNot(tok::r_paren)) {
328    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
329    return;
330  }
331
332  SourceLocation RParenLoc = Tok.getLocation();
333  PP.Lex(Tok);
334  if (Tok.isNot(tok::eod)) {
335    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
336    return;
337  }
338
339  PragmaPackInfo *Info =
340    (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate(
341      sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>());
342  new (Info) PragmaPackInfo();
343  Info->Kind = Kind;
344  Info->Name = Name;
345  Info->Alignment = Alignment;
346  Info->LParenLoc = LParenLoc;
347  Info->RParenLoc = RParenLoc;
348
349  Token *Toks =
350    (Token*) PP.getPreprocessorAllocator().Allocate(
351      sizeof(Token) * 1, llvm::alignOf<Token>());
352  new (Toks) Token();
353  Toks[0].startToken();
354  Toks[0].setKind(tok::annot_pragma_pack);
355  Toks[0].setLocation(PackLoc);
356  Toks[0].setAnnotationValue(static_cast<void*>(Info));
357  PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
358                      /*OwnsTokens=*/false);
359}
360
361// #pragma ms_struct on
362// #pragma ms_struct off
363void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
364                                         PragmaIntroducerKind Introducer,
365                                         Token &MSStructTok) {
366  Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
367
368  Token Tok;
369  PP.Lex(Tok);
370  if (Tok.isNot(tok::identifier)) {
371    PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
372    return;
373  }
374  const IdentifierInfo *II = Tok.getIdentifierInfo();
375  if (II->isStr("on")) {
376    Kind = Sema::PMSST_ON;
377    PP.Lex(Tok);
378  }
379  else if (II->isStr("off") || II->isStr("reset"))
380    PP.Lex(Tok);
381  else {
382    PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
383    return;
384  }
385
386  if (Tok.isNot(tok::eod)) {
387    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
388      << "ms_struct";
389    return;
390  }
391
392  Token *Toks =
393    (Token*) PP.getPreprocessorAllocator().Allocate(
394      sizeof(Token) * 1, llvm::alignOf<Token>());
395  new (Toks) Token();
396  Toks[0].startToken();
397  Toks[0].setKind(tok::annot_pragma_msstruct);
398  Toks[0].setLocation(MSStructTok.getLocation());
399  Toks[0].setAnnotationValue(reinterpret_cast<void*>(
400                             static_cast<uintptr_t>(Kind)));
401  PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
402                      /*OwnsTokens=*/false);
403}
404
405// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
406// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
407static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
408                             bool IsOptions) {
409  Token Tok;
410
411  if (IsOptions) {
412    PP.Lex(Tok);
413    if (Tok.isNot(tok::identifier) ||
414        !Tok.getIdentifierInfo()->isStr("align")) {
415      PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
416      return;
417    }
418  }
419
420  PP.Lex(Tok);
421  if (Tok.isNot(tok::equal)) {
422    PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
423      << IsOptions;
424    return;
425  }
426
427  PP.Lex(Tok);
428  if (Tok.isNot(tok::identifier)) {
429    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
430      << (IsOptions ? "options" : "align");
431    return;
432  }
433
434  Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
435  const IdentifierInfo *II = Tok.getIdentifierInfo();
436  if (II->isStr("native"))
437    Kind = Sema::POAK_Native;
438  else if (II->isStr("natural"))
439    Kind = Sema::POAK_Natural;
440  else if (II->isStr("packed"))
441    Kind = Sema::POAK_Packed;
442  else if (II->isStr("power"))
443    Kind = Sema::POAK_Power;
444  else if (II->isStr("mac68k"))
445    Kind = Sema::POAK_Mac68k;
446  else if (II->isStr("reset"))
447    Kind = Sema::POAK_Reset;
448  else {
449    PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
450      << IsOptions;
451    return;
452  }
453
454  PP.Lex(Tok);
455  if (Tok.isNot(tok::eod)) {
456    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
457      << (IsOptions ? "options" : "align");
458    return;
459  }
460
461  Token *Toks =
462    (Token*) PP.getPreprocessorAllocator().Allocate(
463      sizeof(Token) * 1, llvm::alignOf<Token>());
464  new (Toks) Token();
465  Toks[0].startToken();
466  Toks[0].setKind(tok::annot_pragma_align);
467  Toks[0].setLocation(FirstTok.getLocation());
468  Toks[0].setAnnotationValue(reinterpret_cast<void*>(
469                             static_cast<uintptr_t>(Kind)));
470  PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
471                      /*OwnsTokens=*/false);
472}
473
474void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
475                                      PragmaIntroducerKind Introducer,
476                                      Token &AlignTok) {
477  ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
478}
479
480void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
481                                        PragmaIntroducerKind Introducer,
482                                        Token &OptionsTok) {
483  ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
484}
485
486// #pragma unused(identifier)
487void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
488                                       PragmaIntroducerKind Introducer,
489                                       Token &UnusedTok) {
490  // FIXME: Should we be expanding macros here? My guess is no.
491  SourceLocation UnusedLoc = UnusedTok.getLocation();
492
493  // Lex the left '('.
494  Token Tok;
495  PP.Lex(Tok);
496  if (Tok.isNot(tok::l_paren)) {
497    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
498    return;
499  }
500
501  // Lex the declaration reference(s).
502  SmallVector<Token, 5> Identifiers;
503  SourceLocation RParenLoc;
504  bool LexID = true;
505
506  while (true) {
507    PP.Lex(Tok);
508
509    if (LexID) {
510      if (Tok.is(tok::identifier)) {
511        Identifiers.push_back(Tok);
512        LexID = false;
513        continue;
514      }
515
516      // Illegal token!
517      PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
518      return;
519    }
520
521    // We are execting a ')' or a ','.
522    if (Tok.is(tok::comma)) {
523      LexID = true;
524      continue;
525    }
526
527    if (Tok.is(tok::r_paren)) {
528      RParenLoc = Tok.getLocation();
529      break;
530    }
531
532    // Illegal token!
533    PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
534    return;
535  }
536
537  PP.Lex(Tok);
538  if (Tok.isNot(tok::eod)) {
539    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
540        "unused";
541    return;
542  }
543
544  // Verify that we have a location for the right parenthesis.
545  assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
546  assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
547
548  // For each identifier token, insert into the token stream a
549  // annot_pragma_unused token followed by the identifier token.
550  // This allows us to cache a "#pragma unused" that occurs inside an inline
551  // C++ member function.
552
553  Token *Toks =
554    (Token*) PP.getPreprocessorAllocator().Allocate(
555      sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>());
556  for (unsigned i=0; i != Identifiers.size(); i++) {
557    Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
558    pragmaUnusedTok.startToken();
559    pragmaUnusedTok.setKind(tok::annot_pragma_unused);
560    pragmaUnusedTok.setLocation(UnusedLoc);
561    idTok = Identifiers[i];
562  }
563  PP.EnterTokenStream(Toks, 2*Identifiers.size(),
564                      /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
565}
566
567// #pragma weak identifier
568// #pragma weak identifier '=' identifier
569void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
570                                     PragmaIntroducerKind Introducer,
571                                     Token &WeakTok) {
572  SourceLocation WeakLoc = WeakTok.getLocation();
573
574  Token Tok;
575  PP.Lex(Tok);
576  if (Tok.isNot(tok::identifier)) {
577    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
578    return;
579  }
580
581  Token WeakName = Tok;
582  bool HasAlias = false;
583  Token AliasName;
584
585  PP.Lex(Tok);
586  if (Tok.is(tok::equal)) {
587    HasAlias = true;
588    PP.Lex(Tok);
589    if (Tok.isNot(tok::identifier)) {
590      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
591          << "weak";
592      return;
593    }
594    AliasName = Tok;
595    PP.Lex(Tok);
596  }
597
598  if (Tok.isNot(tok::eod)) {
599    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
600    return;
601  }
602
603  if (HasAlias) {
604    Token *Toks =
605      (Token*) PP.getPreprocessorAllocator().Allocate(
606        sizeof(Token) * 3, llvm::alignOf<Token>());
607    Token &pragmaUnusedTok = Toks[0];
608    pragmaUnusedTok.startToken();
609    pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
610    pragmaUnusedTok.setLocation(WeakLoc);
611    Toks[1] = WeakName;
612    Toks[2] = AliasName;
613    PP.EnterTokenStream(Toks, 3,
614                        /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
615  } else {
616    Token *Toks =
617      (Token*) PP.getPreprocessorAllocator().Allocate(
618        sizeof(Token) * 2, llvm::alignOf<Token>());
619    Token &pragmaUnusedTok = Toks[0];
620    pragmaUnusedTok.startToken();
621    pragmaUnusedTok.setKind(tok::annot_pragma_weak);
622    pragmaUnusedTok.setLocation(WeakLoc);
623    Toks[1] = WeakName;
624    PP.EnterTokenStream(Toks, 2,
625                        /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
626  }
627}
628
629// #pragma redefine_extname identifier identifier
630void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
631                                               PragmaIntroducerKind Introducer,
632                                                Token &RedefToken) {
633  SourceLocation RedefLoc = RedefToken.getLocation();
634
635  Token Tok;
636  PP.Lex(Tok);
637  if (Tok.isNot(tok::identifier)) {
638    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
639      "redefine_extname";
640    return;
641  }
642
643  Token RedefName = Tok;
644  PP.Lex(Tok);
645
646  if (Tok.isNot(tok::identifier)) {
647    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
648        << "redefine_extname";
649    return;
650  }
651
652  Token AliasName = Tok;
653  PP.Lex(Tok);
654
655  if (Tok.isNot(tok::eod)) {
656    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
657      "redefine_extname";
658    return;
659  }
660
661  Token *Toks =
662    (Token*) PP.getPreprocessorAllocator().Allocate(
663      sizeof(Token) * 3, llvm::alignOf<Token>());
664  Token &pragmaRedefTok = Toks[0];
665  pragmaRedefTok.startToken();
666  pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
667  pragmaRedefTok.setLocation(RedefLoc);
668  Toks[1] = RedefName;
669  Toks[2] = AliasName;
670  PP.EnterTokenStream(Toks, 3,
671                      /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
672}
673
674
675void
676PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
677                                      PragmaIntroducerKind Introducer,
678                                      Token &Tok) {
679  tok::OnOffSwitch OOS;
680  if (PP.LexOnOffSwitch(OOS))
681    return;
682
683  Token *Toks =
684    (Token*) PP.getPreprocessorAllocator().Allocate(
685      sizeof(Token) * 1, llvm::alignOf<Token>());
686  new (Toks) Token();
687  Toks[0].startToken();
688  Toks[0].setKind(tok::annot_pragma_fp_contract);
689  Toks[0].setLocation(Tok.getLocation());
690  Toks[0].setAnnotationValue(reinterpret_cast<void*>(
691                             static_cast<uintptr_t>(OOS)));
692  PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
693                      /*OwnsTokens=*/false);
694}
695
696void
697PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
698                                           PragmaIntroducerKind Introducer,
699                                           Token &Tok) {
700  PP.LexUnexpandedToken(Tok);
701  if (Tok.isNot(tok::identifier)) {
702    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
703      "OPENCL";
704    return;
705  }
706  IdentifierInfo *ename = Tok.getIdentifierInfo();
707  SourceLocation NameLoc = Tok.getLocation();
708
709  PP.Lex(Tok);
710  if (Tok.isNot(tok::colon)) {
711    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
712    return;
713  }
714
715  PP.Lex(Tok);
716  if (Tok.isNot(tok::identifier)) {
717    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
718    return;
719  }
720  IdentifierInfo *op = Tok.getIdentifierInfo();
721
722  unsigned state;
723  if (op->isStr("enable")) {
724    state = 1;
725  } else if (op->isStr("disable")) {
726    state = 0;
727  } else {
728    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
729    return;
730  }
731  SourceLocation StateLoc = Tok.getLocation();
732
733  PP.Lex(Tok);
734  if (Tok.isNot(tok::eod)) {
735    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
736      "OPENCL EXTENSION";
737    return;
738  }
739
740  OpenCLExtData data(ename, state);
741  Token *Toks =
742    (Token*) PP.getPreprocessorAllocator().Allocate(
743      sizeof(Token) * 1, llvm::alignOf<Token>());
744  new (Toks) Token();
745  Toks[0].startToken();
746  Toks[0].setKind(tok::annot_pragma_opencl_extension);
747  Toks[0].setLocation(NameLoc);
748  Toks[0].setAnnotationValue(data.getOpaqueValue());
749  PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
750                      /*OwnsTokens=*/false);
751
752  if (PP.getPPCallbacks())
753    PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename,
754                                               StateLoc, state);
755}
756
757/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
758///
759void
760PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
761                                    PragmaIntroducerKind Introducer,
762                                    Token &FirstTok) {
763  if (PP.getDiagnostics().getDiagnosticLevel(diag::warn_pragma_omp_ignored,
764                                             FirstTok.getLocation()) !=
765      DiagnosticsEngine::Ignored) {
766    PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
767    PP.getDiagnostics().setDiagnosticMapping(diag::warn_pragma_omp_ignored,
768                                             diag::MAP_IGNORE,
769                                             SourceLocation());
770  }
771  PP.DiscardUntilEndOfDirective();
772}
773
774/// \brief Handle '#pragma omp ...' when OpenMP is enabled.
775///
776void
777PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
778                                  PragmaIntroducerKind Introducer,
779                                  Token &FirstTok) {
780  SmallVector<Token, 16> Pragma;
781  Token Tok;
782  Tok.startToken();
783  Tok.setKind(tok::annot_pragma_openmp);
784  Tok.setLocation(FirstTok.getLocation());
785
786  while (Tok.isNot(tok::eod)) {
787    Pragma.push_back(Tok);
788    PP.Lex(Tok);
789  }
790  SourceLocation EodLoc = Tok.getLocation();
791  Tok.startToken();
792  Tok.setKind(tok::annot_pragma_openmp_end);
793  Tok.setLocation(EodLoc);
794  Pragma.push_back(Tok);
795
796  Token *Toks = new Token[Pragma.size()];
797  std::copy(Pragma.begin(), Pragma.end(), Toks);
798  PP.EnterTokenStream(Toks, Pragma.size(),
799                      /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
800}
801
802/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
803///
804/// The syntax is:
805/// \code
806///   #pragma detect_mismatch("name", "value")
807/// \endcode
808/// Where 'name' and 'value' are quoted strings.  The values are embedded in
809/// the object file and passed along to the linker.  If the linker detects a
810/// mismatch in the object file's values for the given name, a LNK2038 error
811/// is emitted.  See MSDN for more details.
812void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
813                                               PragmaIntroducerKind Introducer,
814                                               Token &Tok) {
815  SourceLocation CommentLoc = Tok.getLocation();
816  PP.Lex(Tok);
817  if (Tok.isNot(tok::l_paren)) {
818    PP.Diag(CommentLoc, diag::err_expected_lparen);
819    return;
820  }
821
822  // Read the name to embed, which must be a string literal.
823  std::string NameString;
824  if (!PP.LexStringLiteral(Tok, NameString,
825                           "pragma detect_mismatch",
826                           /*MacroExpansion=*/true))
827    return;
828
829  // Read the comma followed by a second string literal.
830  std::string ValueString;
831  if (Tok.isNot(tok::comma)) {
832    PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
833    return;
834  }
835
836  if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
837                           /*MacroExpansion=*/true))
838    return;
839
840  if (Tok.isNot(tok::r_paren)) {
841    PP.Diag(Tok.getLocation(), diag::err_expected_rparen);
842    return;
843  }
844  PP.Lex(Tok);  // Eat the r_paren.
845
846  if (Tok.isNot(tok::eod)) {
847    PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
848    return;
849  }
850
851  // If the pragma is lexically sound, notify any interested PPCallbacks.
852  if (PP.getPPCallbacks())
853    PP.getPPCallbacks()->PragmaDetectMismatch(CommentLoc, NameString,
854                                              ValueString);
855
856  Actions.ActOnPragmaDetectMismatch(NameString, ValueString);
857}
858
859/// \brief Handle the microsoft \#pragma comment extension.
860///
861/// The syntax is:
862/// \code
863///   #pragma comment(linker, "foo")
864/// \endcode
865/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
866/// "foo" is a string, which is fully macro expanded, and permits string
867/// concatenation, embedded escape characters etc.  See MSDN for more details.
868void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
869                                        PragmaIntroducerKind Introducer,
870                                        Token &Tok) {
871  SourceLocation CommentLoc = Tok.getLocation();
872  PP.Lex(Tok);
873  if (Tok.isNot(tok::l_paren)) {
874    PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
875    return;
876  }
877
878  // Read the identifier.
879  PP.Lex(Tok);
880  if (Tok.isNot(tok::identifier)) {
881    PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
882    return;
883  }
884
885  // Verify that this is one of the 5 whitelisted options.
886  IdentifierInfo *II = Tok.getIdentifierInfo();
887  Sema::PragmaMSCommentKind Kind =
888    llvm::StringSwitch<Sema::PragmaMSCommentKind>(II->getName())
889    .Case("linker",   Sema::PCK_Linker)
890    .Case("lib",      Sema::PCK_Lib)
891    .Case("compiler", Sema::PCK_Compiler)
892    .Case("exestr",   Sema::PCK_ExeStr)
893    .Case("user",     Sema::PCK_User)
894    .Default(Sema::PCK_Unknown);
895  if (Kind == Sema::PCK_Unknown) {
896    PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
897    return;
898  }
899
900  // Read the optional string if present.
901  PP.Lex(Tok);
902  std::string ArgumentString;
903  if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
904                                                 "pragma comment",
905                                                 /*MacroExpansion=*/true))
906    return;
907
908  // FIXME: warn that 'exestr' is deprecated.
909  // FIXME: If the kind is "compiler" warn if the string is present (it is
910  // ignored).
911  // The MSDN docs say that "lib" and "linker" require a string and have a short
912  // whitelist of linker options they support, but in practice MSVC doesn't
913  // issue a diagnostic.  Therefore neither does clang.
914
915  if (Tok.isNot(tok::r_paren)) {
916    PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
917    return;
918  }
919  PP.Lex(Tok);  // eat the r_paren.
920
921  if (Tok.isNot(tok::eod)) {
922    PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
923    return;
924  }
925
926  // If the pragma is lexically sound, notify any interested PPCallbacks.
927  if (PP.getPPCallbacks())
928    PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
929
930  Actions.ActOnPragmaMSComment(Kind, ArgumentString);
931}
932