clang API Documentation

ParsePragma.cpp
Go to the documentation of this file.
00001 //===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements the language specific #pragma handlers.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "ParsePragma.h"
00015 #include "clang/Parse/ParseDiagnostic.h"
00016 #include "clang/Parse/Parser.h"
00017 #include "clang/Lex/Preprocessor.h"
00018 using namespace clang;
00019 
00020 /// \brief Handle the annotation token produced for #pragma unused(...)
00021 ///
00022 /// Each annot_pragma_unused is followed by the argument token so e.g.
00023 /// "#pragma unused(x,y)" becomes:
00024 /// annot_pragma_unused 'x' annot_pragma_unused 'y'
00025 void Parser::HandlePragmaUnused() {
00026   assert(Tok.is(tok::annot_pragma_unused));
00027   SourceLocation UnusedLoc = ConsumeToken();
00028   Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
00029   ConsumeToken(); // The argument token.
00030 }
00031 
00032 void Parser::HandlePragmaVisibility() {
00033   assert(Tok.is(tok::annot_pragma_vis));
00034   const IdentifierInfo *VisType =
00035     static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
00036   SourceLocation VisLoc = ConsumeToken();
00037   Actions.ActOnPragmaVisibility(VisType, VisLoc);
00038 }
00039 
00040 struct PragmaPackInfo {
00041   Sema::PragmaPackKind Kind;
00042   IdentifierInfo *Name;
00043   Expr *Alignment;
00044   SourceLocation LParenLoc;
00045   SourceLocation RParenLoc;
00046 };
00047 
00048 void Parser::HandlePragmaPack() {
00049   assert(Tok.is(tok::annot_pragma_pack));
00050   PragmaPackInfo *Info =
00051     static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
00052   SourceLocation PragmaLoc = ConsumeToken();
00053   Actions.ActOnPragmaPack(Info->Kind, Info->Name, Info->Alignment, PragmaLoc,
00054                           Info->LParenLoc, Info->RParenLoc);
00055 }
00056 
00057 // #pragma GCC visibility comes in two variants:
00058 //   'push' '(' [visibility] ')'
00059 //   'pop'
00060 void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP, 
00061                                               PragmaIntroducerKind Introducer,
00062                                               Token &VisTok) {
00063   SourceLocation VisLoc = VisTok.getLocation();
00064 
00065   Token Tok;
00066   PP.LexUnexpandedToken(Tok);
00067 
00068   const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
00069 
00070   const IdentifierInfo *VisType;
00071   if (PushPop && PushPop->isStr("pop")) {
00072     VisType = 0;
00073   } else if (PushPop && PushPop->isStr("push")) {
00074     PP.LexUnexpandedToken(Tok);
00075     if (Tok.isNot(tok::l_paren)) {
00076       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
00077         << "visibility";
00078       return;
00079     }
00080     PP.LexUnexpandedToken(Tok);
00081     VisType = Tok.getIdentifierInfo();
00082     if (!VisType) {
00083       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
00084         << "visibility";
00085       return;
00086     }
00087     PP.LexUnexpandedToken(Tok);
00088     if (Tok.isNot(tok::r_paren)) {
00089       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
00090         << "visibility";
00091       return;
00092     }
00093   } else {
00094     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
00095       << "visibility";
00096     return;
00097   }
00098   PP.LexUnexpandedToken(Tok);
00099   if (Tok.isNot(tok::eod)) {
00100     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
00101       << "visibility";
00102     return;
00103   }
00104 
00105   Token *Toks = new Token[1];
00106   Toks[0].startToken();
00107   Toks[0].setKind(tok::annot_pragma_vis);
00108   Toks[0].setLocation(VisLoc);
00109   Toks[0].setAnnotationValue(
00110                           const_cast<void*>(static_cast<const void*>(VisType)));
00111   PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
00112                       /*OwnsTokens=*/true);
00113 }
00114 
00115 // #pragma pack(...) comes in the following delicious flavors:
00116 //   pack '(' [integer] ')'
00117 //   pack '(' 'show' ')'
00118 //   pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
00119 void PragmaPackHandler::HandlePragma(Preprocessor &PP, 
00120                                      PragmaIntroducerKind Introducer,
00121                                      Token &PackTok) {
00122   SourceLocation PackLoc = PackTok.getLocation();
00123 
00124   Token Tok;
00125   PP.Lex(Tok);
00126   if (Tok.isNot(tok::l_paren)) {
00127     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
00128     return;
00129   }
00130 
00131   Sema::PragmaPackKind Kind = Sema::PPK_Default;
00132   IdentifierInfo *Name = 0;
00133   ExprResult Alignment;
00134   SourceLocation LParenLoc = Tok.getLocation();
00135   PP.Lex(Tok);
00136   if (Tok.is(tok::numeric_constant)) {
00137     Alignment = Actions.ActOnNumericConstant(Tok);
00138     if (Alignment.isInvalid())
00139       return;
00140 
00141     PP.Lex(Tok);
00142 
00143     // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
00144     // the push/pop stack.
00145     // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
00146     if (PP.getLangOpts().ApplePragmaPack)
00147       Kind = Sema::PPK_Push;
00148   } else if (Tok.is(tok::identifier)) {
00149     const IdentifierInfo *II = Tok.getIdentifierInfo();
00150     if (II->isStr("show")) {
00151       Kind = Sema::PPK_Show;
00152       PP.Lex(Tok);
00153     } else {
00154       if (II->isStr("push")) {
00155         Kind = Sema::PPK_Push;
00156       } else if (II->isStr("pop")) {
00157         Kind = Sema::PPK_Pop;
00158       } else {
00159         PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
00160         return;
00161       }
00162       PP.Lex(Tok);
00163 
00164       if (Tok.is(tok::comma)) {
00165         PP.Lex(Tok);
00166 
00167         if (Tok.is(tok::numeric_constant)) {
00168           Alignment = Actions.ActOnNumericConstant(Tok);
00169           if (Alignment.isInvalid())
00170             return;
00171 
00172           PP.Lex(Tok);
00173         } else if (Tok.is(tok::identifier)) {
00174           Name = Tok.getIdentifierInfo();
00175           PP.Lex(Tok);
00176 
00177           if (Tok.is(tok::comma)) {
00178             PP.Lex(Tok);
00179 
00180             if (Tok.isNot(tok::numeric_constant)) {
00181               PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
00182               return;
00183             }
00184 
00185             Alignment = Actions.ActOnNumericConstant(Tok);
00186             if (Alignment.isInvalid())
00187               return;
00188 
00189             PP.Lex(Tok);
00190           }
00191         } else {
00192           PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
00193           return;
00194         }
00195       }
00196     }
00197   } else if (PP.getLangOpts().ApplePragmaPack) {
00198     // In MSVC/gcc, #pragma pack() resets the alignment without affecting
00199     // the push/pop stack.
00200     // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
00201     Kind = Sema::PPK_Pop;
00202   }
00203 
00204   if (Tok.isNot(tok::r_paren)) {
00205     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
00206     return;
00207   }
00208 
00209   SourceLocation RParenLoc = Tok.getLocation();
00210   PP.Lex(Tok);
00211   if (Tok.isNot(tok::eod)) {
00212     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
00213     return;
00214   }
00215 
00216   PragmaPackInfo *Info = 
00217     (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate(
00218       sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>());
00219   new (Info) PragmaPackInfo();
00220   Info->Kind = Kind;
00221   Info->Name = Name;
00222   Info->Alignment = Alignment.release();
00223   Info->LParenLoc = LParenLoc;
00224   Info->RParenLoc = RParenLoc;
00225 
00226   Token *Toks = 
00227     (Token*) PP.getPreprocessorAllocator().Allocate(
00228       sizeof(Token) * 1, llvm::alignOf<Token>());
00229   new (Toks) Token();
00230   Toks[0].startToken();
00231   Toks[0].setKind(tok::annot_pragma_pack);
00232   Toks[0].setLocation(PackLoc);
00233   Toks[0].setAnnotationValue(static_cast<void*>(Info));
00234   PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
00235                       /*OwnsTokens=*/false);
00236 }
00237 
00238 // #pragma ms_struct on
00239 // #pragma ms_struct off
00240 void PragmaMSStructHandler::HandlePragma(Preprocessor &PP, 
00241                                          PragmaIntroducerKind Introducer,
00242                                          Token &MSStructTok) {
00243   Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
00244   
00245   Token Tok;
00246   PP.Lex(Tok);
00247   if (Tok.isNot(tok::identifier)) {
00248     PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
00249     return;
00250   }
00251   const IdentifierInfo *II = Tok.getIdentifierInfo();
00252   if (II->isStr("on")) {
00253     Kind = Sema::PMSST_ON;
00254     PP.Lex(Tok);
00255   }
00256   else if (II->isStr("off") || II->isStr("reset"))
00257     PP.Lex(Tok);
00258   else {
00259     PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
00260     return;
00261   }
00262   
00263   if (Tok.isNot(tok::eod)) {
00264     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
00265       << "ms_struct";
00266     return;
00267   }
00268   Actions.ActOnPragmaMSStruct(Kind);
00269 }
00270 
00271 // #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
00272 // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
00273 static void ParseAlignPragma(Sema &Actions, Preprocessor &PP, Token &FirstTok,
00274                              bool IsOptions) {
00275   Token Tok;
00276 
00277   if (IsOptions) {
00278     PP.Lex(Tok);
00279     if (Tok.isNot(tok::identifier) ||
00280         !Tok.getIdentifierInfo()->isStr("align")) {
00281       PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
00282       return;
00283     }
00284   }
00285 
00286   PP.Lex(Tok);
00287   if (Tok.isNot(tok::equal)) {
00288     PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
00289       << IsOptions;
00290     return;
00291   }
00292 
00293   PP.Lex(Tok);
00294   if (Tok.isNot(tok::identifier)) {
00295     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
00296       << (IsOptions ? "options" : "align");
00297     return;
00298   }
00299 
00300   Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
00301   const IdentifierInfo *II = Tok.getIdentifierInfo();
00302   if (II->isStr("native"))
00303     Kind = Sema::POAK_Native;
00304   else if (II->isStr("natural"))
00305     Kind = Sema::POAK_Natural;
00306   else if (II->isStr("packed"))
00307     Kind = Sema::POAK_Packed;
00308   else if (II->isStr("power"))
00309     Kind = Sema::POAK_Power;
00310   else if (II->isStr("mac68k"))
00311     Kind = Sema::POAK_Mac68k;
00312   else if (II->isStr("reset"))
00313     Kind = Sema::POAK_Reset;
00314   else {
00315     PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
00316       << IsOptions;
00317     return;
00318   }
00319 
00320   SourceLocation KindLoc = Tok.getLocation();
00321   PP.Lex(Tok);
00322   if (Tok.isNot(tok::eod)) {
00323     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
00324       << (IsOptions ? "options" : "align");
00325     return;
00326   }
00327 
00328   Actions.ActOnPragmaOptionsAlign(Kind, FirstTok.getLocation(), KindLoc);
00329 }
00330 
00331 void PragmaAlignHandler::HandlePragma(Preprocessor &PP, 
00332                                       PragmaIntroducerKind Introducer,
00333                                       Token &AlignTok) {
00334   ParseAlignPragma(Actions, PP, AlignTok, /*IsOptions=*/false);
00335 }
00336 
00337 void PragmaOptionsHandler::HandlePragma(Preprocessor &PP, 
00338                                         PragmaIntroducerKind Introducer,
00339                                         Token &OptionsTok) {
00340   ParseAlignPragma(Actions, PP, OptionsTok, /*IsOptions=*/true);
00341 }
00342 
00343 // #pragma unused(identifier)
00344 void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, 
00345                                        PragmaIntroducerKind Introducer,
00346                                        Token &UnusedTok) {
00347   // FIXME: Should we be expanding macros here? My guess is no.
00348   SourceLocation UnusedLoc = UnusedTok.getLocation();
00349 
00350   // Lex the left '('.
00351   Token Tok;
00352   PP.Lex(Tok);
00353   if (Tok.isNot(tok::l_paren)) {
00354     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
00355     return;
00356   }
00357 
00358   // Lex the declaration reference(s).
00359   SmallVector<Token, 5> Identifiers;
00360   SourceLocation RParenLoc;
00361   bool LexID = true;
00362 
00363   while (true) {
00364     PP.Lex(Tok);
00365 
00366     if (LexID) {
00367       if (Tok.is(tok::identifier)) {
00368         Identifiers.push_back(Tok);
00369         LexID = false;
00370         continue;
00371       }
00372 
00373       // Illegal token!
00374       PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
00375       return;
00376     }
00377 
00378     // We are execting a ')' or a ','.
00379     if (Tok.is(tok::comma)) {
00380       LexID = true;
00381       continue;
00382     }
00383 
00384     if (Tok.is(tok::r_paren)) {
00385       RParenLoc = Tok.getLocation();
00386       break;
00387     }
00388 
00389     // Illegal token!
00390     PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
00391     return;
00392   }
00393 
00394   PP.Lex(Tok);
00395   if (Tok.isNot(tok::eod)) {
00396     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
00397         "unused";
00398     return;
00399   }
00400 
00401   // Verify that we have a location for the right parenthesis.
00402   assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
00403   assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
00404 
00405   // For each identifier token, insert into the token stream a
00406   // annot_pragma_unused token followed by the identifier token.
00407   // This allows us to cache a "#pragma unused" that occurs inside an inline
00408   // C++ member function.
00409 
00410   Token *Toks = 
00411     (Token*) PP.getPreprocessorAllocator().Allocate(
00412       sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>());
00413   for (unsigned i=0; i != Identifiers.size(); i++) {
00414     Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
00415     pragmaUnusedTok.startToken();
00416     pragmaUnusedTok.setKind(tok::annot_pragma_unused);
00417     pragmaUnusedTok.setLocation(UnusedLoc);
00418     idTok = Identifiers[i];
00419   }
00420   PP.EnterTokenStream(Toks, 2*Identifiers.size(),
00421                       /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
00422 }
00423 
00424 // #pragma weak identifier
00425 // #pragma weak identifier '=' identifier
00426 void PragmaWeakHandler::HandlePragma(Preprocessor &PP, 
00427                                      PragmaIntroducerKind Introducer,
00428                                      Token &WeakTok) {
00429   // FIXME: Should we be expanding macros here? My guess is no.
00430   SourceLocation WeakLoc = WeakTok.getLocation();
00431 
00432   Token Tok;
00433   PP.Lex(Tok);
00434   if (Tok.isNot(tok::identifier)) {
00435     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
00436     return;
00437   }
00438 
00439   IdentifierInfo *WeakName = Tok.getIdentifierInfo(), *AliasName = 0;
00440   SourceLocation WeakNameLoc = Tok.getLocation(), AliasNameLoc;
00441 
00442   PP.Lex(Tok);
00443   if (Tok.is(tok::equal)) {
00444     PP.Lex(Tok);
00445     if (Tok.isNot(tok::identifier)) {
00446       PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
00447           << "weak";
00448       return;
00449     }
00450     AliasName = Tok.getIdentifierInfo();
00451     AliasNameLoc = Tok.getLocation();
00452     PP.Lex(Tok);
00453   }
00454 
00455   if (Tok.isNot(tok::eod)) {
00456     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
00457     return;
00458   }
00459 
00460   if (AliasName) {
00461     Actions.ActOnPragmaWeakAlias(WeakName, AliasName, WeakLoc, WeakNameLoc,
00462                                  AliasNameLoc);
00463   } else {
00464     Actions.ActOnPragmaWeakID(WeakName, WeakLoc, WeakNameLoc);
00465   }
00466 }
00467 
00468 // #pragma redefine_extname identifier identifier
00469 void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP, 
00470                                                PragmaIntroducerKind Introducer,
00471                                                 Token &RedefToken) {
00472   SourceLocation RedefLoc = RedefToken.getLocation();
00473 
00474   Token Tok;
00475   PP.Lex(Tok);
00476   if (Tok.isNot(tok::identifier)) {
00477     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
00478       "redefine_extname";
00479     return;
00480   }
00481 
00482   IdentifierInfo *RedefName = Tok.getIdentifierInfo(), *AliasName = 0;
00483   SourceLocation RedefNameLoc = Tok.getLocation(), AliasNameLoc;
00484 
00485   PP.Lex(Tok);
00486   if (Tok.isNot(tok::identifier)) {
00487     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
00488         << "redefine_extname";
00489     return;
00490   }
00491   AliasName = Tok.getIdentifierInfo();
00492   AliasNameLoc = Tok.getLocation();
00493   PP.Lex(Tok);
00494 
00495   if (Tok.isNot(tok::eod)) {
00496     PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
00497       "redefine_extname";
00498     return;
00499   }
00500 
00501   Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
00502       RedefNameLoc, AliasNameLoc);
00503 }
00504 
00505 
00506 void
00507 PragmaFPContractHandler::HandlePragma(Preprocessor &PP, 
00508                                       PragmaIntroducerKind Introducer,
00509                                       Token &Tok) {
00510   tok::OnOffSwitch OOS;
00511   if (PP.LexOnOffSwitch(OOS))
00512     return;
00513 
00514   Actions.ActOnPragmaFPContract(OOS);
00515 }
00516 
00517 void 
00518 PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP, 
00519                                            PragmaIntroducerKind Introducer,
00520                                            Token &Tok) {
00521   PP.LexUnexpandedToken(Tok);
00522   if (Tok.isNot(tok::identifier)) {
00523     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
00524       "OPENCL";
00525     return;
00526   }
00527   IdentifierInfo *ename = Tok.getIdentifierInfo();
00528   SourceLocation NameLoc = Tok.getLocation();
00529 
00530   PP.Lex(Tok);
00531   if (Tok.isNot(tok::colon)) {
00532     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
00533     return;
00534   }
00535 
00536   PP.Lex(Tok);
00537   if (Tok.isNot(tok::identifier)) {
00538     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
00539     return;
00540   }
00541   IdentifierInfo *op = Tok.getIdentifierInfo();
00542 
00543   unsigned state;
00544   if (op->isStr("enable")) {
00545     state = 1;
00546   } else if (op->isStr("disable")) {
00547     state = 0;
00548   } else {
00549     PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
00550     return;
00551   }
00552 
00553   OpenCLOptions &f = Actions.getOpenCLOptions();
00554   // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
00555   // overriding all previously issued extension directives, but only if the
00556   // behavior is set to disable."
00557   if (state == 0 && ename->isStr("all")) {
00558 #define OPENCLEXT(nm)   f.nm = 0;
00559 #include "clang/Basic/OpenCLExtensions.def"
00560   }
00561 #define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
00562 #include "clang/Basic/OpenCLExtensions.def"
00563   else {
00564     PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
00565     return;
00566   }
00567 }
00568