Home | History | Annotate | Download | only in Parse
      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"
     20 using 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'
     27 void 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 
     34 void 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 
     42 struct PragmaPackInfo {
     43   Sema::PragmaPackKind Kind;
     44   IdentifierInfo *Name;
     45   Token Alignment;
     46   SourceLocation LParenLoc;
     47   SourceLocation RParenLoc;
     48 };
     49 
     50 void 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 
     65 void 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 
     74 void 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 
     83 void 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 
     91 void 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 
    105 void 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 
    118 void 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 
    127 StmtResult 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 
    154 namespace {
    155   typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
    156 }
    157 
    158 void 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'
    188 void 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] ')'
    247 void 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
    363 void 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'}
    407 static 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 
    474 void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
    475                                       PragmaIntroducerKind Introducer,
    476                                       Token &AlignTok) {
    477   ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
    478 }
    479 
    480 void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
    481                                         PragmaIntroducerKind Introducer,
    482                                         Token &OptionsTok) {
    483   ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
    484 }
    485 
    486 // #pragma unused(identifier)
    487 void 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
    569 void 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
    630 void 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 
    675 void
    676 PragmaFPContractHandler::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 
    696 void
    697 PragmaOpenCLExtensionHandler::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 
    732   PP.Lex(Tok);
    733   if (Tok.isNot(tok::eod)) {
    734     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
    735       "OPENCL EXTENSION";
    736     return;
    737   }
    738 
    739   OpenCLExtData data(ename, state);
    740   Token *Toks =
    741     (Token*) PP.getPreprocessorAllocator().Allocate(
    742       sizeof(Token) * 1, llvm::alignOf<Token>());
    743   new (Toks) Token();
    744   Toks[0].startToken();
    745   Toks[0].setKind(tok::annot_pragma_opencl_extension);
    746   Toks[0].setLocation(NameLoc);
    747   Toks[0].setAnnotationValue(data.getOpaqueValue());
    748   PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
    749                       /*OwnsTokens=*/false);
    750 }
    751 
    752 /// \brief Handle '#pragma omp ...' when OpenMP is disabled.
    753 ///
    754 void
    755 PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
    756                                     PragmaIntroducerKind Introducer,
    757                                     Token &FirstTok) {
    758   if (PP.getDiagnostics().getDiagnosticLevel(diag::warn_pragma_omp_ignored,
    759                                              FirstTok.getLocation()) !=
    760       DiagnosticsEngine::Ignored) {
    761     PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
    762     PP.getDiagnostics().setDiagnosticMapping(diag::warn_pragma_omp_ignored,
    763                                              diag::MAP_IGNORE,
    764                                              SourceLocation());
    765   }
    766   PP.DiscardUntilEndOfDirective();
    767 }
    768 
    769 /// \brief Handle '#pragma omp ...' when OpenMP is enabled.
    770 ///
    771 void
    772 PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
    773                                   PragmaIntroducerKind Introducer,
    774                                   Token &FirstTok) {
    775   SmallVector<Token, 16> Pragma;
    776   Token Tok;
    777   Tok.startToken();
    778   Tok.setKind(tok::annot_pragma_openmp);
    779   Tok.setLocation(FirstTok.getLocation());
    780 
    781   while (Tok.isNot(tok::eod)) {
    782     Pragma.push_back(Tok);
    783     PP.Lex(Tok);
    784   }
    785   SourceLocation EodLoc = Tok.getLocation();
    786   Tok.startToken();
    787   Tok.setKind(tok::annot_pragma_openmp_end);
    788   Tok.setLocation(EodLoc);
    789   Pragma.push_back(Tok);
    790 
    791   Token *Toks = new Token[Pragma.size()];
    792   std::copy(Pragma.begin(), Pragma.end(), Toks);
    793   PP.EnterTokenStream(Toks, Pragma.size(),
    794                       /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
    795 }
    796 
    797 /// \brief Handle the Microsoft \#pragma detect_mismatch extension.
    798 ///
    799 /// The syntax is:
    800 /// \code
    801 ///   #pragma detect_mismatch("name", "value")
    802 /// \endcode
    803 /// Where 'name' and 'value' are quoted strings.  The values are embedded in
    804 /// the object file and passed along to the linker.  If the linker detects a
    805 /// mismatch in the object file's values for the given name, a LNK2038 error
    806 /// is emitted.  See MSDN for more details.
    807 void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
    808                                                PragmaIntroducerKind Introducer,
    809                                                Token &Tok) {
    810   SourceLocation CommentLoc = Tok.getLocation();
    811   PP.Lex(Tok);
    812   if (Tok.isNot(tok::l_paren)) {
    813     PP.Diag(CommentLoc, diag::err_expected_lparen);
    814     return;
    815   }
    816 
    817   // Read the name to embed, which must be a string literal.
    818   std::string NameString;
    819   if (!PP.LexStringLiteral(Tok, NameString,
    820                            "pragma detect_mismatch",
    821                            /*MacroExpansion=*/true))
    822     return;
    823 
    824   // Read the comma followed by a second string literal.
    825   std::string ValueString;
    826   if (Tok.isNot(tok::comma)) {
    827     PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
    828     return;
    829   }
    830 
    831   if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
    832                            /*MacroExpansion=*/true))
    833     return;
    834 
    835   if (Tok.isNot(tok::r_paren)) {
    836     PP.Diag(Tok.getLocation(), diag::err_expected_rparen);
    837     return;
    838   }
    839   PP.Lex(Tok);  // Eat the r_paren.
    840 
    841   if (Tok.isNot(tok::eod)) {
    842     PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
    843     return;
    844   }
    845 
    846   // If the pragma is lexically sound, notify any interested PPCallbacks.
    847   if (PP.getPPCallbacks())
    848     PP.getPPCallbacks()->PragmaDetectMismatch(CommentLoc, NameString,
    849                                               ValueString);
    850 
    851   Actions.ActOnPragmaDetectMismatch(NameString, ValueString);
    852 }
    853 
    854 /// \brief Handle the microsoft \#pragma comment extension.
    855 ///
    856 /// The syntax is:
    857 /// \code
    858 ///   #pragma comment(linker, "foo")
    859 /// \endcode
    860 /// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
    861 /// "foo" is a string, which is fully macro expanded, and permits string
    862 /// concatenation, embedded escape characters etc.  See MSDN for more details.
    863 void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
    864                                         PragmaIntroducerKind Introducer,
    865                                         Token &Tok) {
    866   SourceLocation CommentLoc = Tok.getLocation();
    867   PP.Lex(Tok);
    868   if (Tok.isNot(tok::l_paren)) {
    869     PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
    870     return;
    871   }
    872 
    873   // Read the identifier.
    874   PP.Lex(Tok);
    875   if (Tok.isNot(tok::identifier)) {
    876     PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
    877     return;
    878   }
    879 
    880   // Verify that this is one of the 5 whitelisted options.
    881   IdentifierInfo *II = Tok.getIdentifierInfo();
    882   Sema::PragmaMSCommentKind Kind =
    883     llvm::StringSwitch<Sema::PragmaMSCommentKind>(II->getName())
    884     .Case("linker",   Sema::PCK_Linker)
    885     .Case("lib",      Sema::PCK_Lib)
    886     .Case("compiler", Sema::PCK_Compiler)
    887     .Case("exestr",   Sema::PCK_ExeStr)
    888     .Case("user",     Sema::PCK_User)
    889     .Default(Sema::PCK_Unknown);
    890   if (Kind == Sema::PCK_Unknown) {
    891     PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
    892     return;
    893   }
    894 
    895   // Read the optional string if present.
    896   PP.Lex(Tok);
    897   std::string ArgumentString;
    898   if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
    899                                                  "pragma comment",
    900                                                  /*MacroExpansion=*/true))
    901     return;
    902 
    903   // FIXME: warn that 'exestr' is deprecated.
    904   // FIXME: If the kind is "compiler" warn if the string is present (it is
    905   // ignored).
    906   // The MSDN docs say that "lib" and "linker" require a string and have a short
    907   // whitelist of linker options they support, but in practice MSVC doesn't
    908   // issue a diagnostic.  Therefore neither does clang.
    909 
    910   if (Tok.isNot(tok::r_paren)) {
    911     PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
    912     return;
    913   }
    914   PP.Lex(Tok);  // eat the r_paren.
    915 
    916   if (Tok.isNot(tok::eod)) {
    917     PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
    918     return;
    919   }
    920 
    921   // If the pragma is lexically sound, notify any interested PPCallbacks.
    922   if (PP.getPPCallbacks())
    923     PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
    924 
    925   Actions.ActOnPragmaMSComment(Kind, ArgumentString);
    926 }
    927