clang API Documentation
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