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