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 "RAIIObjectsForParser.h" 15 #include "clang/AST/ASTContext.h" 16 #include "clang/Basic/TargetInfo.h" 17 #include "clang/Lex/Preprocessor.h" 18 #include "clang/Parse/ParseDiagnostic.h" 19 #include "clang/Parse/Parser.h" 20 #include "clang/Sema/LoopHint.h" 21 #include "clang/Sema/Scope.h" 22 #include "llvm/ADT/StringSwitch.h" 23 using namespace clang; 24 25 namespace { 26 27 struct PragmaAlignHandler : public PragmaHandler { 28 explicit PragmaAlignHandler() : PragmaHandler("align") {} 29 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 30 Token &FirstToken) override; 31 }; 32 33 struct PragmaGCCVisibilityHandler : public PragmaHandler { 34 explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {} 35 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 36 Token &FirstToken) override; 37 }; 38 39 struct PragmaOptionsHandler : public PragmaHandler { 40 explicit PragmaOptionsHandler() : PragmaHandler("options") {} 41 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 42 Token &FirstToken) override; 43 }; 44 45 struct PragmaPackHandler : public PragmaHandler { 46 explicit PragmaPackHandler() : PragmaHandler("pack") {} 47 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 48 Token &FirstToken) override; 49 }; 50 51 struct PragmaMSStructHandler : public PragmaHandler { 52 explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {} 53 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 54 Token &FirstToken) override; 55 }; 56 57 struct PragmaUnusedHandler : public PragmaHandler { 58 PragmaUnusedHandler() : PragmaHandler("unused") {} 59 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 60 Token &FirstToken) override; 61 }; 62 63 struct PragmaWeakHandler : public PragmaHandler { 64 explicit PragmaWeakHandler() : PragmaHandler("weak") {} 65 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 66 Token &FirstToken) override; 67 }; 68 69 struct PragmaRedefineExtnameHandler : public PragmaHandler { 70 explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {} 71 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 72 Token &FirstToken) override; 73 }; 74 75 struct PragmaOpenCLExtensionHandler : public PragmaHandler { 76 PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {} 77 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 78 Token &FirstToken) override; 79 }; 80 81 82 struct PragmaFPContractHandler : public PragmaHandler { 83 PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {} 84 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 85 Token &FirstToken) override; 86 }; 87 88 struct PragmaNoOpenMPHandler : public PragmaHandler { 89 PragmaNoOpenMPHandler() : PragmaHandler("omp") { } 90 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 91 Token &FirstToken) override; 92 }; 93 94 struct PragmaOpenMPHandler : public PragmaHandler { 95 PragmaOpenMPHandler() : PragmaHandler("omp") { } 96 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 97 Token &FirstToken) override; 98 }; 99 100 /// PragmaCommentHandler - "\#pragma comment ...". 101 struct PragmaCommentHandler : public PragmaHandler { 102 PragmaCommentHandler(Sema &Actions) 103 : PragmaHandler("comment"), Actions(Actions) {} 104 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 105 Token &FirstToken) override; 106 private: 107 Sema &Actions; 108 }; 109 110 struct PragmaDetectMismatchHandler : public PragmaHandler { 111 PragmaDetectMismatchHandler(Sema &Actions) 112 : PragmaHandler("detect_mismatch"), Actions(Actions) {} 113 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 114 Token &FirstToken) override; 115 private: 116 Sema &Actions; 117 }; 118 119 struct PragmaMSPointersToMembers : public PragmaHandler { 120 explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {} 121 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 122 Token &FirstToken) override; 123 }; 124 125 struct PragmaMSVtorDisp : public PragmaHandler { 126 explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {} 127 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 128 Token &FirstToken) override; 129 }; 130 131 struct PragmaMSPragma : public PragmaHandler { 132 explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {} 133 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 134 Token &FirstToken) override; 135 }; 136 137 /// PragmaOptimizeHandler - "\#pragma clang optimize on/off". 138 struct PragmaOptimizeHandler : public PragmaHandler { 139 PragmaOptimizeHandler(Sema &S) 140 : PragmaHandler("optimize"), Actions(S) {} 141 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 142 Token &FirstToken) override; 143 private: 144 Sema &Actions; 145 }; 146 147 struct PragmaLoopHintHandler : public PragmaHandler { 148 PragmaLoopHintHandler() : PragmaHandler("loop") {} 149 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 150 Token &FirstToken) override; 151 }; 152 153 struct PragmaUnrollHintHandler : public PragmaHandler { 154 PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {} 155 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 156 Token &FirstToken) override; 157 }; 158 159 struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler { 160 PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {} 161 }; 162 163 } // end namespace 164 165 void Parser::initializePragmaHandlers() { 166 AlignHandler.reset(new PragmaAlignHandler()); 167 PP.AddPragmaHandler(AlignHandler.get()); 168 169 GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler()); 170 PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get()); 171 172 OptionsHandler.reset(new PragmaOptionsHandler()); 173 PP.AddPragmaHandler(OptionsHandler.get()); 174 175 PackHandler.reset(new PragmaPackHandler()); 176 PP.AddPragmaHandler(PackHandler.get()); 177 178 MSStructHandler.reset(new PragmaMSStructHandler()); 179 PP.AddPragmaHandler(MSStructHandler.get()); 180 181 UnusedHandler.reset(new PragmaUnusedHandler()); 182 PP.AddPragmaHandler(UnusedHandler.get()); 183 184 WeakHandler.reset(new PragmaWeakHandler()); 185 PP.AddPragmaHandler(WeakHandler.get()); 186 187 RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler()); 188 PP.AddPragmaHandler(RedefineExtnameHandler.get()); 189 190 FPContractHandler.reset(new PragmaFPContractHandler()); 191 PP.AddPragmaHandler("STDC", FPContractHandler.get()); 192 193 if (getLangOpts().OpenCL) { 194 OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler()); 195 PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get()); 196 197 PP.AddPragmaHandler("OPENCL", FPContractHandler.get()); 198 } 199 if (getLangOpts().OpenMP) 200 OpenMPHandler.reset(new PragmaOpenMPHandler()); 201 else 202 OpenMPHandler.reset(new PragmaNoOpenMPHandler()); 203 PP.AddPragmaHandler(OpenMPHandler.get()); 204 205 if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) { 206 MSCommentHandler.reset(new PragmaCommentHandler(Actions)); 207 PP.AddPragmaHandler(MSCommentHandler.get()); 208 } 209 210 if (getLangOpts().MicrosoftExt) { 211 MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions)); 212 PP.AddPragmaHandler(MSDetectMismatchHandler.get()); 213 MSPointersToMembers.reset(new PragmaMSPointersToMembers()); 214 PP.AddPragmaHandler(MSPointersToMembers.get()); 215 MSVtorDisp.reset(new PragmaMSVtorDisp()); 216 PP.AddPragmaHandler(MSVtorDisp.get()); 217 MSInitSeg.reset(new PragmaMSPragma("init_seg")); 218 PP.AddPragmaHandler(MSInitSeg.get()); 219 MSDataSeg.reset(new PragmaMSPragma("data_seg")); 220 PP.AddPragmaHandler(MSDataSeg.get()); 221 MSBSSSeg.reset(new PragmaMSPragma("bss_seg")); 222 PP.AddPragmaHandler(MSBSSSeg.get()); 223 MSConstSeg.reset(new PragmaMSPragma("const_seg")); 224 PP.AddPragmaHandler(MSConstSeg.get()); 225 MSCodeSeg.reset(new PragmaMSPragma("code_seg")); 226 PP.AddPragmaHandler(MSCodeSeg.get()); 227 MSSection.reset(new PragmaMSPragma("section")); 228 PP.AddPragmaHandler(MSSection.get()); 229 MSRuntimeChecks.reset(new PragmaMSRuntimeChecksHandler()); 230 PP.AddPragmaHandler(MSRuntimeChecks.get()); 231 } 232 233 OptimizeHandler.reset(new PragmaOptimizeHandler(Actions)); 234 PP.AddPragmaHandler("clang", OptimizeHandler.get()); 235 236 LoopHintHandler.reset(new PragmaLoopHintHandler()); 237 PP.AddPragmaHandler("clang", LoopHintHandler.get()); 238 239 UnrollHintHandler.reset(new PragmaUnrollHintHandler("unroll")); 240 PP.AddPragmaHandler(UnrollHintHandler.get()); 241 242 NoUnrollHintHandler.reset(new PragmaUnrollHintHandler("nounroll")); 243 PP.AddPragmaHandler(NoUnrollHintHandler.get()); 244 } 245 246 void Parser::resetPragmaHandlers() { 247 // Remove the pragma handlers we installed. 248 PP.RemovePragmaHandler(AlignHandler.get()); 249 AlignHandler.reset(); 250 PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get()); 251 GCCVisibilityHandler.reset(); 252 PP.RemovePragmaHandler(OptionsHandler.get()); 253 OptionsHandler.reset(); 254 PP.RemovePragmaHandler(PackHandler.get()); 255 PackHandler.reset(); 256 PP.RemovePragmaHandler(MSStructHandler.get()); 257 MSStructHandler.reset(); 258 PP.RemovePragmaHandler(UnusedHandler.get()); 259 UnusedHandler.reset(); 260 PP.RemovePragmaHandler(WeakHandler.get()); 261 WeakHandler.reset(); 262 PP.RemovePragmaHandler(RedefineExtnameHandler.get()); 263 RedefineExtnameHandler.reset(); 264 265 if (getLangOpts().OpenCL) { 266 PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get()); 267 OpenCLExtensionHandler.reset(); 268 PP.RemovePragmaHandler("OPENCL", FPContractHandler.get()); 269 } 270 PP.RemovePragmaHandler(OpenMPHandler.get()); 271 OpenMPHandler.reset(); 272 273 if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) { 274 PP.RemovePragmaHandler(MSCommentHandler.get()); 275 MSCommentHandler.reset(); 276 } 277 278 if (getLangOpts().MicrosoftExt) { 279 PP.RemovePragmaHandler(MSDetectMismatchHandler.get()); 280 MSDetectMismatchHandler.reset(); 281 PP.RemovePragmaHandler(MSPointersToMembers.get()); 282 MSPointersToMembers.reset(); 283 PP.RemovePragmaHandler(MSVtorDisp.get()); 284 MSVtorDisp.reset(); 285 PP.RemovePragmaHandler(MSInitSeg.get()); 286 MSInitSeg.reset(); 287 PP.RemovePragmaHandler(MSDataSeg.get()); 288 MSDataSeg.reset(); 289 PP.RemovePragmaHandler(MSBSSSeg.get()); 290 MSBSSSeg.reset(); 291 PP.RemovePragmaHandler(MSConstSeg.get()); 292 MSConstSeg.reset(); 293 PP.RemovePragmaHandler(MSCodeSeg.get()); 294 MSCodeSeg.reset(); 295 PP.RemovePragmaHandler(MSSection.get()); 296 MSSection.reset(); 297 PP.RemovePragmaHandler(MSRuntimeChecks.get()); 298 MSRuntimeChecks.reset(); 299 } 300 301 PP.RemovePragmaHandler("STDC", FPContractHandler.get()); 302 FPContractHandler.reset(); 303 304 PP.RemovePragmaHandler("clang", OptimizeHandler.get()); 305 OptimizeHandler.reset(); 306 307 PP.RemovePragmaHandler("clang", LoopHintHandler.get()); 308 LoopHintHandler.reset(); 309 310 PP.RemovePragmaHandler(UnrollHintHandler.get()); 311 UnrollHintHandler.reset(); 312 313 PP.RemovePragmaHandler(NoUnrollHintHandler.get()); 314 NoUnrollHintHandler.reset(); 315 } 316 317 /// \brief Handle the annotation token produced for #pragma unused(...) 318 /// 319 /// Each annot_pragma_unused is followed by the argument token so e.g. 320 /// "#pragma unused(x,y)" becomes: 321 /// annot_pragma_unused 'x' annot_pragma_unused 'y' 322 void Parser::HandlePragmaUnused() { 323 assert(Tok.is(tok::annot_pragma_unused)); 324 SourceLocation UnusedLoc = ConsumeToken(); 325 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc); 326 ConsumeToken(); // The argument token. 327 } 328 329 void Parser::HandlePragmaVisibility() { 330 assert(Tok.is(tok::annot_pragma_vis)); 331 const IdentifierInfo *VisType = 332 static_cast<IdentifierInfo *>(Tok.getAnnotationValue()); 333 SourceLocation VisLoc = ConsumeToken(); 334 Actions.ActOnPragmaVisibility(VisType, VisLoc); 335 } 336 337 namespace { 338 struct PragmaPackInfo { 339 Sema::PragmaPackKind Kind; 340 IdentifierInfo *Name; 341 Token Alignment; 342 SourceLocation LParenLoc; 343 SourceLocation RParenLoc; 344 }; 345 } // end anonymous namespace 346 347 void Parser::HandlePragmaPack() { 348 assert(Tok.is(tok::annot_pragma_pack)); 349 PragmaPackInfo *Info = 350 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue()); 351 SourceLocation PragmaLoc = ConsumeToken(); 352 ExprResult Alignment; 353 if (Info->Alignment.is(tok::numeric_constant)) { 354 Alignment = Actions.ActOnNumericConstant(Info->Alignment); 355 if (Alignment.isInvalid()) 356 return; 357 } 358 Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc, 359 Info->LParenLoc, Info->RParenLoc); 360 } 361 362 void Parser::HandlePragmaMSStruct() { 363 assert(Tok.is(tok::annot_pragma_msstruct)); 364 Sema::PragmaMSStructKind Kind = 365 static_cast<Sema::PragmaMSStructKind>( 366 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); 367 Actions.ActOnPragmaMSStruct(Kind); 368 ConsumeToken(); // The annotation token. 369 } 370 371 void Parser::HandlePragmaAlign() { 372 assert(Tok.is(tok::annot_pragma_align)); 373 Sema::PragmaOptionsAlignKind Kind = 374 static_cast<Sema::PragmaOptionsAlignKind>( 375 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); 376 SourceLocation PragmaLoc = ConsumeToken(); 377 Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc); 378 } 379 380 void Parser::HandlePragmaWeak() { 381 assert(Tok.is(tok::annot_pragma_weak)); 382 SourceLocation PragmaLoc = ConsumeToken(); 383 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc, 384 Tok.getLocation()); 385 ConsumeToken(); // The weak name. 386 } 387 388 void Parser::HandlePragmaWeakAlias() { 389 assert(Tok.is(tok::annot_pragma_weakalias)); 390 SourceLocation PragmaLoc = ConsumeToken(); 391 IdentifierInfo *WeakName = Tok.getIdentifierInfo(); 392 SourceLocation WeakNameLoc = Tok.getLocation(); 393 ConsumeToken(); 394 IdentifierInfo *AliasName = Tok.getIdentifierInfo(); 395 SourceLocation AliasNameLoc = Tok.getLocation(); 396 ConsumeToken(); 397 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc, 398 WeakNameLoc, AliasNameLoc); 399 400 } 401 402 void Parser::HandlePragmaRedefineExtname() { 403 assert(Tok.is(tok::annot_pragma_redefine_extname)); 404 SourceLocation RedefLoc = ConsumeToken(); 405 IdentifierInfo *RedefName = Tok.getIdentifierInfo(); 406 SourceLocation RedefNameLoc = Tok.getLocation(); 407 ConsumeToken(); 408 IdentifierInfo *AliasName = Tok.getIdentifierInfo(); 409 SourceLocation AliasNameLoc = Tok.getLocation(); 410 ConsumeToken(); 411 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc, 412 RedefNameLoc, AliasNameLoc); 413 } 414 415 void Parser::HandlePragmaFPContract() { 416 assert(Tok.is(tok::annot_pragma_fp_contract)); 417 tok::OnOffSwitch OOS = 418 static_cast<tok::OnOffSwitch>( 419 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); 420 Actions.ActOnPragmaFPContract(OOS); 421 ConsumeToken(); // The annotation token. 422 } 423 424 StmtResult Parser::HandlePragmaCaptured() 425 { 426 assert(Tok.is(tok::annot_pragma_captured)); 427 ConsumeToken(); 428 429 if (Tok.isNot(tok::l_brace)) { 430 PP.Diag(Tok, diag::err_expected) << tok::l_brace; 431 return StmtError(); 432 } 433 434 SourceLocation Loc = Tok.getLocation(); 435 436 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope); 437 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default, 438 /*NumParams=*/1); 439 440 StmtResult R = ParseCompoundStatement(); 441 CapturedRegionScope.Exit(); 442 443 if (R.isInvalid()) { 444 Actions.ActOnCapturedRegionError(); 445 return StmtError(); 446 } 447 448 return Actions.ActOnCapturedRegionEnd(R.get()); 449 } 450 451 namespace { 452 typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData; 453 } 454 455 void Parser::HandlePragmaOpenCLExtension() { 456 assert(Tok.is(tok::annot_pragma_opencl_extension)); 457 OpenCLExtData data = 458 OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue()); 459 unsigned state = data.getInt(); 460 IdentifierInfo *ename = data.getPointer(); 461 SourceLocation NameLoc = Tok.getLocation(); 462 ConsumeToken(); // The annotation token. 463 464 OpenCLOptions &f = Actions.getOpenCLOptions(); 465 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions, 466 // overriding all previously issued extension directives, but only if the 467 // behavior is set to disable." 468 if (state == 0 && ename->isStr("all")) { 469 #define OPENCLEXT(nm) f.nm = 0; 470 #include "clang/Basic/OpenCLExtensions.def" 471 } 472 #define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; } 473 #include "clang/Basic/OpenCLExtensions.def" 474 else { 475 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename; 476 return; 477 } 478 } 479 480 void Parser::HandlePragmaMSPointersToMembers() { 481 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members)); 482 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod = 483 static_cast<LangOptions::PragmaMSPointersToMembersKind>( 484 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); 485 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token. 486 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc); 487 } 488 489 void Parser::HandlePragmaMSVtorDisp() { 490 assert(Tok.is(tok::annot_pragma_ms_vtordisp)); 491 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()); 492 Sema::PragmaVtorDispKind Kind = 493 static_cast<Sema::PragmaVtorDispKind>((Value >> 16) & 0xFFFF); 494 MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF); 495 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token. 496 Actions.ActOnPragmaMSVtorDisp(Kind, PragmaLoc, Mode); 497 } 498 499 void Parser::HandlePragmaMSPragma() { 500 assert(Tok.is(tok::annot_pragma_ms_pragma)); 501 // Grab the tokens out of the annotation and enter them into the stream. 502 auto TheTokens = (std::pair<Token*, size_t> *)Tok.getAnnotationValue(); 503 PP.EnterTokenStream(TheTokens->first, TheTokens->second, true, true); 504 SourceLocation PragmaLocation = ConsumeToken(); // The annotation token. 505 assert(Tok.isAnyIdentifier()); 506 StringRef PragmaName = Tok.getIdentifierInfo()->getName(); 507 PP.Lex(Tok); // pragma kind 508 509 // Figure out which #pragma we're dealing with. The switch has no default 510 // because lex shouldn't emit the annotation token for unrecognized pragmas. 511 typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation); 512 PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName) 513 .Case("data_seg", &Parser::HandlePragmaMSSegment) 514 .Case("bss_seg", &Parser::HandlePragmaMSSegment) 515 .Case("const_seg", &Parser::HandlePragmaMSSegment) 516 .Case("code_seg", &Parser::HandlePragmaMSSegment) 517 .Case("section", &Parser::HandlePragmaMSSection) 518 .Case("init_seg", &Parser::HandlePragmaMSInitSeg); 519 520 if (!(this->*Handler)(PragmaName, PragmaLocation)) { 521 // Pragma handling failed, and has been diagnosed. Slurp up the tokens 522 // until eof (really end of line) to prevent follow-on errors. 523 while (Tok.isNot(tok::eof)) 524 PP.Lex(Tok); 525 PP.Lex(Tok); 526 } 527 } 528 529 bool Parser::HandlePragmaMSSection(StringRef PragmaName, 530 SourceLocation PragmaLocation) { 531 if (Tok.isNot(tok::l_paren)) { 532 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName; 533 return false; 534 } 535 PP.Lex(Tok); // ( 536 // Parsing code for pragma section 537 if (Tok.isNot(tok::string_literal)) { 538 PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name) 539 << PragmaName; 540 return false; 541 } 542 ExprResult StringResult = ParseStringLiteralExpression(); 543 if (StringResult.isInvalid()) 544 return false; // Already diagnosed. 545 StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get()); 546 if (SegmentName->getCharByteWidth() != 1) { 547 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string) 548 << PragmaName; 549 return false; 550 } 551 int SectionFlags = ASTContext::PSF_Read; 552 bool SectionFlagsAreDefault = true; 553 while (Tok.is(tok::comma)) { 554 PP.Lex(Tok); // , 555 // Ignore "long" and "short". 556 // They are undocumented, but widely used, section attributes which appear 557 // to do nothing. 558 if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) { 559 PP.Lex(Tok); // long/short 560 continue; 561 } 562 563 if (!Tok.isAnyIdentifier()) { 564 PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren) 565 << PragmaName; 566 return false; 567 } 568 ASTContext::PragmaSectionFlag Flag = 569 llvm::StringSwitch<ASTContext::PragmaSectionFlag>( 570 Tok.getIdentifierInfo()->getName()) 571 .Case("read", ASTContext::PSF_Read) 572 .Case("write", ASTContext::PSF_Write) 573 .Case("execute", ASTContext::PSF_Execute) 574 .Case("shared", ASTContext::PSF_Invalid) 575 .Case("nopage", ASTContext::PSF_Invalid) 576 .Case("nocache", ASTContext::PSF_Invalid) 577 .Case("discard", ASTContext::PSF_Invalid) 578 .Case("remove", ASTContext::PSF_Invalid) 579 .Default(ASTContext::PSF_None); 580 if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) { 581 PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None 582 ? diag::warn_pragma_invalid_specific_action 583 : diag::warn_pragma_unsupported_action) 584 << PragmaName << Tok.getIdentifierInfo()->getName(); 585 return false; 586 } 587 SectionFlags |= Flag; 588 SectionFlagsAreDefault = false; 589 PP.Lex(Tok); // Identifier 590 } 591 // If no section attributes are specified, the section will be marked as 592 // read/write. 593 if (SectionFlagsAreDefault) 594 SectionFlags |= ASTContext::PSF_Write; 595 if (Tok.isNot(tok::r_paren)) { 596 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName; 597 return false; 598 } 599 PP.Lex(Tok); // ) 600 if (Tok.isNot(tok::eof)) { 601 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol) 602 << PragmaName; 603 return false; 604 } 605 PP.Lex(Tok); // eof 606 Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName); 607 return true; 608 } 609 610 bool Parser::HandlePragmaMSSegment(StringRef PragmaName, 611 SourceLocation PragmaLocation) { 612 if (Tok.isNot(tok::l_paren)) { 613 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName; 614 return false; 615 } 616 PP.Lex(Tok); // ( 617 Sema::PragmaMsStackAction Action = Sema::PSK_Reset; 618 StringRef SlotLabel; 619 if (Tok.isAnyIdentifier()) { 620 StringRef PushPop = Tok.getIdentifierInfo()->getName(); 621 if (PushPop == "push") 622 Action = Sema::PSK_Push; 623 else if (PushPop == "pop") 624 Action = Sema::PSK_Pop; 625 else { 626 PP.Diag(PragmaLocation, 627 diag::warn_pragma_expected_section_push_pop_or_name) 628 << PragmaName; 629 return false; 630 } 631 if (Action != Sema::PSK_Reset) { 632 PP.Lex(Tok); // push | pop 633 if (Tok.is(tok::comma)) { 634 PP.Lex(Tok); // , 635 // If we've got a comma, we either need a label or a string. 636 if (Tok.isAnyIdentifier()) { 637 SlotLabel = Tok.getIdentifierInfo()->getName(); 638 PP.Lex(Tok); // identifier 639 if (Tok.is(tok::comma)) 640 PP.Lex(Tok); 641 else if (Tok.isNot(tok::r_paren)) { 642 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) 643 << PragmaName; 644 return false; 645 } 646 } 647 } else if (Tok.isNot(tok::r_paren)) { 648 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName; 649 return false; 650 } 651 } 652 } 653 // Grab the string literal for our section name. 654 StringLiteral *SegmentName = nullptr; 655 if (Tok.isNot(tok::r_paren)) { 656 if (Tok.isNot(tok::string_literal)) { 657 unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ? 658 diag::warn_pragma_expected_section_name : 659 diag::warn_pragma_expected_section_label_or_name : 660 diag::warn_pragma_expected_section_push_pop_or_name; 661 PP.Diag(PragmaLocation, DiagID) << PragmaName; 662 return false; 663 } 664 ExprResult StringResult = ParseStringLiteralExpression(); 665 if (StringResult.isInvalid()) 666 return false; // Already diagnosed. 667 SegmentName = cast<StringLiteral>(StringResult.get()); 668 if (SegmentName->getCharByteWidth() != 1) { 669 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string) 670 << PragmaName; 671 return false; 672 } 673 // Setting section "" has no effect 674 if (SegmentName->getLength()) 675 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set); 676 } 677 if (Tok.isNot(tok::r_paren)) { 678 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName; 679 return false; 680 } 681 PP.Lex(Tok); // ) 682 if (Tok.isNot(tok::eof)) { 683 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol) 684 << PragmaName; 685 return false; 686 } 687 PP.Lex(Tok); // eof 688 Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel, 689 SegmentName, PragmaName); 690 return true; 691 } 692 693 // #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} ) 694 bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName, 695 SourceLocation PragmaLocation) { 696 if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) { 697 PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target); 698 return false; 699 } 700 701 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen, 702 PragmaName)) 703 return false; 704 705 // Parse either the known section names or the string section name. 706 StringLiteral *SegmentName = nullptr; 707 if (Tok.isAnyIdentifier()) { 708 auto *II = Tok.getIdentifierInfo(); 709 StringRef Section = llvm::StringSwitch<StringRef>(II->getName()) 710 .Case("compiler", "\".CRT$XCC\"") 711 .Case("lib", "\".CRT$XCL\"") 712 .Case("user", "\".CRT$XCU\"") 713 .Default(""); 714 715 if (!Section.empty()) { 716 // Pretend the user wrote the appropriate string literal here. 717 Token Toks[1]; 718 Toks[0].startToken(); 719 Toks[0].setKind(tok::string_literal); 720 Toks[0].setLocation(Tok.getLocation()); 721 Toks[0].setLiteralData(Section.data()); 722 Toks[0].setLength(Section.size()); 723 SegmentName = 724 cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get()); 725 PP.Lex(Tok); 726 } 727 } else if (Tok.is(tok::string_literal)) { 728 ExprResult StringResult = ParseStringLiteralExpression(); 729 if (StringResult.isInvalid()) 730 return false; 731 SegmentName = cast<StringLiteral>(StringResult.get()); 732 if (SegmentName->getCharByteWidth() != 1) { 733 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string) 734 << PragmaName; 735 return false; 736 } 737 // FIXME: Add support for the '[, func-name]' part of the pragma. 738 } 739 740 if (!SegmentName) { 741 PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName; 742 return false; 743 } 744 745 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen, 746 PragmaName) || 747 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol, 748 PragmaName)) 749 return false; 750 751 Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName); 752 return true; 753 } 754 755 namespace { 756 struct PragmaLoopHintInfo { 757 Token PragmaName; 758 Token Option; 759 ArrayRef<Token> Toks; 760 }; 761 } // end anonymous namespace 762 763 static std::string PragmaLoopHintString(Token PragmaName, Token Option) { 764 std::string PragmaString; 765 if (PragmaName.getIdentifierInfo()->getName() == "loop") { 766 PragmaString = "clang loop "; 767 PragmaString += Option.getIdentifierInfo()->getName(); 768 } else { 769 assert(PragmaName.getIdentifierInfo()->getName() == "unroll" && 770 "Unexpected pragma name"); 771 PragmaString = "unroll"; 772 } 773 return PragmaString; 774 } 775 776 bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { 777 assert(Tok.is(tok::annot_pragma_loop_hint)); 778 PragmaLoopHintInfo *Info = 779 static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue()); 780 781 IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo(); 782 Hint.PragmaNameLoc = IdentifierLoc::create( 783 Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo); 784 785 // It is possible that the loop hint has no option identifier, such as 786 // #pragma unroll(4). 787 IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier) 788 ? Info->Option.getIdentifierInfo() 789 : nullptr; 790 Hint.OptionLoc = IdentifierLoc::create( 791 Actions.Context, Info->Option.getLocation(), OptionInfo); 792 793 const Token *Toks = Info->Toks.data(); 794 size_t TokSize = Info->Toks.size(); 795 796 // Return a valid hint if pragma unroll or nounroll were specified 797 // without an argument. 798 bool PragmaUnroll = PragmaNameInfo->getName() == "unroll"; 799 bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll"; 800 if (TokSize == 0 && (PragmaUnroll || PragmaNoUnroll)) { 801 ConsumeToken(); // The annotation token. 802 Hint.Range = Info->PragmaName.getLocation(); 803 return true; 804 } 805 806 // The constant expression is always followed by an eof token, which increases 807 // the TokSize by 1. 808 assert(TokSize > 0 && 809 "PragmaLoopHintInfo::Toks must contain at least one token."); 810 811 // If no option is specified the argument is assumed to be a constant expr. 812 bool OptionUnroll = false; 813 bool StateOption = false; 814 if (OptionInfo) { // Pragma Unroll does not specify an option. 815 OptionUnroll = OptionInfo->isStr("unroll"); 816 StateOption = llvm::StringSwitch<bool>(OptionInfo->getName()) 817 .Case("vectorize", true) 818 .Case("interleave", true) 819 .Case("unroll", true) 820 .Default(false); 821 } 822 823 // Verify loop hint has an argument. 824 if (Toks[0].is(tok::eof)) { 825 ConsumeToken(); // The annotation token. 826 Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument) 827 << /*StateArgument=*/StateOption << /*FullKeyword=*/OptionUnroll; 828 return false; 829 } 830 831 // Validate the argument. 832 if (StateOption) { 833 ConsumeToken(); // The annotation token. 834 SourceLocation StateLoc = Toks[0].getLocation(); 835 IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo(); 836 if (!StateInfo || 837 (!StateInfo->isStr("enable") && !StateInfo->isStr("disable") && 838 ((OptionUnroll && !StateInfo->isStr("full")) || 839 (!OptionUnroll && !StateInfo->isStr("assume_safety"))))) { 840 Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword) 841 << /*FullKeyword=*/OptionUnroll; 842 return false; 843 } 844 if (TokSize > 2) 845 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 846 << PragmaLoopHintString(Info->PragmaName, Info->Option); 847 Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo); 848 } else { 849 // Enter constant expression including eof terminator into token stream. 850 PP.EnterTokenStream(Toks, TokSize, /*DisableMacroExpansion=*/false, 851 /*OwnsTokens=*/false); 852 ConsumeToken(); // The annotation token. 853 854 ExprResult R = ParseConstantExpression(); 855 856 // Tokens following an error in an ill-formed constant expression will 857 // remain in the token stream and must be removed. 858 if (Tok.isNot(tok::eof)) { 859 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 860 << PragmaLoopHintString(Info->PragmaName, Info->Option); 861 while (Tok.isNot(tok::eof)) 862 ConsumeAnyToken(); 863 } 864 865 ConsumeToken(); // Consume the constant expression eof terminator. 866 867 if (R.isInvalid() || 868 Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation())) 869 return false; 870 871 // Argument is a constant expression with an integer type. 872 Hint.ValueExpr = R.get(); 873 } 874 875 Hint.Range = SourceRange(Info->PragmaName.getLocation(), 876 Info->Toks[TokSize - 1].getLocation()); 877 return true; 878 } 879 880 // #pragma GCC visibility comes in two variants: 881 // 'push' '(' [visibility] ')' 882 // 'pop' 883 void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP, 884 PragmaIntroducerKind Introducer, 885 Token &VisTok) { 886 SourceLocation VisLoc = VisTok.getLocation(); 887 888 Token Tok; 889 PP.LexUnexpandedToken(Tok); 890 891 const IdentifierInfo *PushPop = Tok.getIdentifierInfo(); 892 893 const IdentifierInfo *VisType; 894 if (PushPop && PushPop->isStr("pop")) { 895 VisType = nullptr; 896 } else if (PushPop && PushPop->isStr("push")) { 897 PP.LexUnexpandedToken(Tok); 898 if (Tok.isNot(tok::l_paren)) { 899 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) 900 << "visibility"; 901 return; 902 } 903 PP.LexUnexpandedToken(Tok); 904 VisType = Tok.getIdentifierInfo(); 905 if (!VisType) { 906 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 907 << "visibility"; 908 return; 909 } 910 PP.LexUnexpandedToken(Tok); 911 if (Tok.isNot(tok::r_paren)) { 912 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) 913 << "visibility"; 914 return; 915 } 916 } else { 917 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 918 << "visibility"; 919 return; 920 } 921 SourceLocation EndLoc = Tok.getLocation(); 922 PP.LexUnexpandedToken(Tok); 923 if (Tok.isNot(tok::eod)) { 924 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 925 << "visibility"; 926 return; 927 } 928 929 Token *Toks = new Token[1]; 930 Toks[0].startToken(); 931 Toks[0].setKind(tok::annot_pragma_vis); 932 Toks[0].setLocation(VisLoc); 933 Toks[0].setAnnotationEndLoc(EndLoc); 934 Toks[0].setAnnotationValue( 935 const_cast<void*>(static_cast<const void*>(VisType))); 936 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, 937 /*OwnsTokens=*/true); 938 } 939 940 // #pragma pack(...) comes in the following delicious flavors: 941 // pack '(' [integer] ')' 942 // pack '(' 'show' ')' 943 // pack '(' ('push' | 'pop') [',' identifier] [, integer] ')' 944 void PragmaPackHandler::HandlePragma(Preprocessor &PP, 945 PragmaIntroducerKind Introducer, 946 Token &PackTok) { 947 SourceLocation PackLoc = PackTok.getLocation(); 948 949 Token Tok; 950 PP.Lex(Tok); 951 if (Tok.isNot(tok::l_paren)) { 952 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack"; 953 return; 954 } 955 956 Sema::PragmaPackKind Kind = Sema::PPK_Default; 957 IdentifierInfo *Name = nullptr; 958 Token Alignment; 959 Alignment.startToken(); 960 SourceLocation LParenLoc = Tok.getLocation(); 961 PP.Lex(Tok); 962 if (Tok.is(tok::numeric_constant)) { 963 Alignment = Tok; 964 965 PP.Lex(Tok); 966 967 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting 968 // the push/pop stack. 969 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4) 970 if (PP.getLangOpts().ApplePragmaPack) 971 Kind = Sema::PPK_Push; 972 } else if (Tok.is(tok::identifier)) { 973 const IdentifierInfo *II = Tok.getIdentifierInfo(); 974 if (II->isStr("show")) { 975 Kind = Sema::PPK_Show; 976 PP.Lex(Tok); 977 } else { 978 if (II->isStr("push")) { 979 Kind = Sema::PPK_Push; 980 } else if (II->isStr("pop")) { 981 Kind = Sema::PPK_Pop; 982 } else { 983 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack"; 984 return; 985 } 986 PP.Lex(Tok); 987 988 if (Tok.is(tok::comma)) { 989 PP.Lex(Tok); 990 991 if (Tok.is(tok::numeric_constant)) { 992 Alignment = Tok; 993 994 PP.Lex(Tok); 995 } else if (Tok.is(tok::identifier)) { 996 Name = Tok.getIdentifierInfo(); 997 PP.Lex(Tok); 998 999 if (Tok.is(tok::comma)) { 1000 PP.Lex(Tok); 1001 1002 if (Tok.isNot(tok::numeric_constant)) { 1003 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed); 1004 return; 1005 } 1006 1007 Alignment = Tok; 1008 1009 PP.Lex(Tok); 1010 } 1011 } else { 1012 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed); 1013 return; 1014 } 1015 } 1016 } 1017 } else if (PP.getLangOpts().ApplePragmaPack) { 1018 // In MSVC/gcc, #pragma pack() resets the alignment without affecting 1019 // the push/pop stack. 1020 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop). 1021 Kind = Sema::PPK_Pop; 1022 } 1023 1024 if (Tok.isNot(tok::r_paren)) { 1025 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack"; 1026 return; 1027 } 1028 1029 SourceLocation RParenLoc = Tok.getLocation(); 1030 PP.Lex(Tok); 1031 if (Tok.isNot(tok::eod)) { 1032 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack"; 1033 return; 1034 } 1035 1036 PragmaPackInfo *Info = 1037 (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate( 1038 sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>()); 1039 new (Info) PragmaPackInfo(); 1040 Info->Kind = Kind; 1041 Info->Name = Name; 1042 Info->Alignment = Alignment; 1043 Info->LParenLoc = LParenLoc; 1044 Info->RParenLoc = RParenLoc; 1045 1046 Token *Toks = 1047 (Token*) PP.getPreprocessorAllocator().Allocate( 1048 sizeof(Token) * 1, llvm::alignOf<Token>()); 1049 new (Toks) Token(); 1050 Toks[0].startToken(); 1051 Toks[0].setKind(tok::annot_pragma_pack); 1052 Toks[0].setLocation(PackLoc); 1053 Toks[0].setAnnotationEndLoc(RParenLoc); 1054 Toks[0].setAnnotationValue(static_cast<void*>(Info)); 1055 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, 1056 /*OwnsTokens=*/false); 1057 } 1058 1059 // #pragma ms_struct on 1060 // #pragma ms_struct off 1061 void PragmaMSStructHandler::HandlePragma(Preprocessor &PP, 1062 PragmaIntroducerKind Introducer, 1063 Token &MSStructTok) { 1064 Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF; 1065 1066 Token Tok; 1067 PP.Lex(Tok); 1068 if (Tok.isNot(tok::identifier)) { 1069 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct); 1070 return; 1071 } 1072 SourceLocation EndLoc = Tok.getLocation(); 1073 const IdentifierInfo *II = Tok.getIdentifierInfo(); 1074 if (II->isStr("on")) { 1075 Kind = Sema::PMSST_ON; 1076 PP.Lex(Tok); 1077 } 1078 else if (II->isStr("off") || II->isStr("reset")) 1079 PP.Lex(Tok); 1080 else { 1081 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct); 1082 return; 1083 } 1084 1085 if (Tok.isNot(tok::eod)) { 1086 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 1087 << "ms_struct"; 1088 return; 1089 } 1090 1091 Token *Toks = 1092 (Token*) PP.getPreprocessorAllocator().Allocate( 1093 sizeof(Token) * 1, llvm::alignOf<Token>()); 1094 new (Toks) Token(); 1095 Toks[0].startToken(); 1096 Toks[0].setKind(tok::annot_pragma_msstruct); 1097 Toks[0].setLocation(MSStructTok.getLocation()); 1098 Toks[0].setAnnotationEndLoc(EndLoc); 1099 Toks[0].setAnnotationValue(reinterpret_cast<void*>( 1100 static_cast<uintptr_t>(Kind))); 1101 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, 1102 /*OwnsTokens=*/false); 1103 } 1104 1105 // #pragma 'align' '=' {'native','natural','mac68k','power','reset'} 1106 // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'} 1107 static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok, 1108 bool IsOptions) { 1109 Token Tok; 1110 1111 if (IsOptions) { 1112 PP.Lex(Tok); 1113 if (Tok.isNot(tok::identifier) || 1114 !Tok.getIdentifierInfo()->isStr("align")) { 1115 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align); 1116 return; 1117 } 1118 } 1119 1120 PP.Lex(Tok); 1121 if (Tok.isNot(tok::equal)) { 1122 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal) 1123 << IsOptions; 1124 return; 1125 } 1126 1127 PP.Lex(Tok); 1128 if (Tok.isNot(tok::identifier)) { 1129 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 1130 << (IsOptions ? "options" : "align"); 1131 return; 1132 } 1133 1134 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural; 1135 const IdentifierInfo *II = Tok.getIdentifierInfo(); 1136 if (II->isStr("native")) 1137 Kind = Sema::POAK_Native; 1138 else if (II->isStr("natural")) 1139 Kind = Sema::POAK_Natural; 1140 else if (II->isStr("packed")) 1141 Kind = Sema::POAK_Packed; 1142 else if (II->isStr("power")) 1143 Kind = Sema::POAK_Power; 1144 else if (II->isStr("mac68k")) 1145 Kind = Sema::POAK_Mac68k; 1146 else if (II->isStr("reset")) 1147 Kind = Sema::POAK_Reset; 1148 else { 1149 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option) 1150 << IsOptions; 1151 return; 1152 } 1153 1154 SourceLocation EndLoc = Tok.getLocation(); 1155 PP.Lex(Tok); 1156 if (Tok.isNot(tok::eod)) { 1157 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 1158 << (IsOptions ? "options" : "align"); 1159 return; 1160 } 1161 1162 Token *Toks = 1163 (Token*) PP.getPreprocessorAllocator().Allocate( 1164 sizeof(Token) * 1, llvm::alignOf<Token>()); 1165 new (Toks) Token(); 1166 Toks[0].startToken(); 1167 Toks[0].setKind(tok::annot_pragma_align); 1168 Toks[0].setLocation(FirstTok.getLocation()); 1169 Toks[0].setAnnotationEndLoc(EndLoc); 1170 Toks[0].setAnnotationValue(reinterpret_cast<void*>( 1171 static_cast<uintptr_t>(Kind))); 1172 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, 1173 /*OwnsTokens=*/false); 1174 } 1175 1176 void PragmaAlignHandler::HandlePragma(Preprocessor &PP, 1177 PragmaIntroducerKind Introducer, 1178 Token &AlignTok) { 1179 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false); 1180 } 1181 1182 void PragmaOptionsHandler::HandlePragma(Preprocessor &PP, 1183 PragmaIntroducerKind Introducer, 1184 Token &OptionsTok) { 1185 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true); 1186 } 1187 1188 // #pragma unused(identifier) 1189 void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, 1190 PragmaIntroducerKind Introducer, 1191 Token &UnusedTok) { 1192 // FIXME: Should we be expanding macros here? My guess is no. 1193 SourceLocation UnusedLoc = UnusedTok.getLocation(); 1194 1195 // Lex the left '('. 1196 Token Tok; 1197 PP.Lex(Tok); 1198 if (Tok.isNot(tok::l_paren)) { 1199 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused"; 1200 return; 1201 } 1202 1203 // Lex the declaration reference(s). 1204 SmallVector<Token, 5> Identifiers; 1205 SourceLocation RParenLoc; 1206 bool LexID = true; 1207 1208 while (true) { 1209 PP.Lex(Tok); 1210 1211 if (LexID) { 1212 if (Tok.is(tok::identifier)) { 1213 Identifiers.push_back(Tok); 1214 LexID = false; 1215 continue; 1216 } 1217 1218 // Illegal token! 1219 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var); 1220 return; 1221 } 1222 1223 // We are execting a ')' or a ','. 1224 if (Tok.is(tok::comma)) { 1225 LexID = true; 1226 continue; 1227 } 1228 1229 if (Tok.is(tok::r_paren)) { 1230 RParenLoc = Tok.getLocation(); 1231 break; 1232 } 1233 1234 // Illegal token! 1235 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused"; 1236 return; 1237 } 1238 1239 PP.Lex(Tok); 1240 if (Tok.isNot(tok::eod)) { 1241 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << 1242 "unused"; 1243 return; 1244 } 1245 1246 // Verify that we have a location for the right parenthesis. 1247 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'"); 1248 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments"); 1249 1250 // For each identifier token, insert into the token stream a 1251 // annot_pragma_unused token followed by the identifier token. 1252 // This allows us to cache a "#pragma unused" that occurs inside an inline 1253 // C++ member function. 1254 1255 Token *Toks = 1256 (Token*) PP.getPreprocessorAllocator().Allocate( 1257 sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>()); 1258 for (unsigned i=0; i != Identifiers.size(); i++) { 1259 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1]; 1260 pragmaUnusedTok.startToken(); 1261 pragmaUnusedTok.setKind(tok::annot_pragma_unused); 1262 pragmaUnusedTok.setLocation(UnusedLoc); 1263 idTok = Identifiers[i]; 1264 } 1265 PP.EnterTokenStream(Toks, 2*Identifiers.size(), 1266 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false); 1267 } 1268 1269 // #pragma weak identifier 1270 // #pragma weak identifier '=' identifier 1271 void PragmaWeakHandler::HandlePragma(Preprocessor &PP, 1272 PragmaIntroducerKind Introducer, 1273 Token &WeakTok) { 1274 SourceLocation WeakLoc = WeakTok.getLocation(); 1275 1276 Token Tok; 1277 PP.Lex(Tok); 1278 if (Tok.isNot(tok::identifier)) { 1279 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak"; 1280 return; 1281 } 1282 1283 Token WeakName = Tok; 1284 bool HasAlias = false; 1285 Token AliasName; 1286 1287 PP.Lex(Tok); 1288 if (Tok.is(tok::equal)) { 1289 HasAlias = true; 1290 PP.Lex(Tok); 1291 if (Tok.isNot(tok::identifier)) { 1292 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 1293 << "weak"; 1294 return; 1295 } 1296 AliasName = Tok; 1297 PP.Lex(Tok); 1298 } 1299 1300 if (Tok.isNot(tok::eod)) { 1301 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak"; 1302 return; 1303 } 1304 1305 if (HasAlias) { 1306 Token *Toks = 1307 (Token*) PP.getPreprocessorAllocator().Allocate( 1308 sizeof(Token) * 3, llvm::alignOf<Token>()); 1309 Token &pragmaUnusedTok = Toks[0]; 1310 pragmaUnusedTok.startToken(); 1311 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias); 1312 pragmaUnusedTok.setLocation(WeakLoc); 1313 pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation()); 1314 Toks[1] = WeakName; 1315 Toks[2] = AliasName; 1316 PP.EnterTokenStream(Toks, 3, 1317 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false); 1318 } else { 1319 Token *Toks = 1320 (Token*) PP.getPreprocessorAllocator().Allocate( 1321 sizeof(Token) * 2, llvm::alignOf<Token>()); 1322 Token &pragmaUnusedTok = Toks[0]; 1323 pragmaUnusedTok.startToken(); 1324 pragmaUnusedTok.setKind(tok::annot_pragma_weak); 1325 pragmaUnusedTok.setLocation(WeakLoc); 1326 pragmaUnusedTok.setAnnotationEndLoc(WeakLoc); 1327 Toks[1] = WeakName; 1328 PP.EnterTokenStream(Toks, 2, 1329 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false); 1330 } 1331 } 1332 1333 // #pragma redefine_extname identifier identifier 1334 void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP, 1335 PragmaIntroducerKind Introducer, 1336 Token &RedefToken) { 1337 SourceLocation RedefLoc = RedefToken.getLocation(); 1338 1339 Token Tok; 1340 PP.Lex(Tok); 1341 if (Tok.isNot(tok::identifier)) { 1342 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << 1343 "redefine_extname"; 1344 return; 1345 } 1346 1347 Token RedefName = Tok; 1348 PP.Lex(Tok); 1349 1350 if (Tok.isNot(tok::identifier)) { 1351 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 1352 << "redefine_extname"; 1353 return; 1354 } 1355 1356 Token AliasName = Tok; 1357 PP.Lex(Tok); 1358 1359 if (Tok.isNot(tok::eod)) { 1360 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << 1361 "redefine_extname"; 1362 return; 1363 } 1364 1365 Token *Toks = 1366 (Token*) PP.getPreprocessorAllocator().Allocate( 1367 sizeof(Token) * 3, llvm::alignOf<Token>()); 1368 Token &pragmaRedefTok = Toks[0]; 1369 pragmaRedefTok.startToken(); 1370 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname); 1371 pragmaRedefTok.setLocation(RedefLoc); 1372 pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation()); 1373 Toks[1] = RedefName; 1374 Toks[2] = AliasName; 1375 PP.EnterTokenStream(Toks, 3, 1376 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false); 1377 } 1378 1379 1380 void 1381 PragmaFPContractHandler::HandlePragma(Preprocessor &PP, 1382 PragmaIntroducerKind Introducer, 1383 Token &Tok) { 1384 tok::OnOffSwitch OOS; 1385 if (PP.LexOnOffSwitch(OOS)) 1386 return; 1387 1388 Token *Toks = 1389 (Token*) PP.getPreprocessorAllocator().Allocate( 1390 sizeof(Token) * 1, llvm::alignOf<Token>()); 1391 new (Toks) Token(); 1392 Toks[0].startToken(); 1393 Toks[0].setKind(tok::annot_pragma_fp_contract); 1394 Toks[0].setLocation(Tok.getLocation()); 1395 Toks[0].setAnnotationEndLoc(Tok.getLocation()); 1396 Toks[0].setAnnotationValue(reinterpret_cast<void*>( 1397 static_cast<uintptr_t>(OOS))); 1398 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, 1399 /*OwnsTokens=*/false); 1400 } 1401 1402 void 1403 PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP, 1404 PragmaIntroducerKind Introducer, 1405 Token &Tok) { 1406 PP.LexUnexpandedToken(Tok); 1407 if (Tok.isNot(tok::identifier)) { 1408 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << 1409 "OPENCL"; 1410 return; 1411 } 1412 IdentifierInfo *ename = Tok.getIdentifierInfo(); 1413 SourceLocation NameLoc = Tok.getLocation(); 1414 1415 PP.Lex(Tok); 1416 if (Tok.isNot(tok::colon)) { 1417 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename; 1418 return; 1419 } 1420 1421 PP.Lex(Tok); 1422 if (Tok.isNot(tok::identifier)) { 1423 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable); 1424 return; 1425 } 1426 IdentifierInfo *op = Tok.getIdentifierInfo(); 1427 1428 unsigned state; 1429 if (op->isStr("enable")) { 1430 state = 1; 1431 } else if (op->isStr("disable")) { 1432 state = 0; 1433 } else { 1434 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable); 1435 return; 1436 } 1437 SourceLocation StateLoc = Tok.getLocation(); 1438 1439 PP.Lex(Tok); 1440 if (Tok.isNot(tok::eod)) { 1441 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << 1442 "OPENCL EXTENSION"; 1443 return; 1444 } 1445 1446 OpenCLExtData data(ename, state); 1447 Token *Toks = 1448 (Token*) PP.getPreprocessorAllocator().Allocate( 1449 sizeof(Token) * 1, llvm::alignOf<Token>()); 1450 new (Toks) Token(); 1451 Toks[0].startToken(); 1452 Toks[0].setKind(tok::annot_pragma_opencl_extension); 1453 Toks[0].setLocation(NameLoc); 1454 Toks[0].setAnnotationValue(data.getOpaqueValue()); 1455 Toks[0].setAnnotationEndLoc(StateLoc); 1456 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, 1457 /*OwnsTokens=*/false); 1458 1459 if (PP.getPPCallbacks()) 1460 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename, 1461 StateLoc, state); 1462 } 1463 1464 /// \brief Handle '#pragma omp ...' when OpenMP is disabled. 1465 /// 1466 void 1467 PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP, 1468 PragmaIntroducerKind Introducer, 1469 Token &FirstTok) { 1470 if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored, 1471 FirstTok.getLocation())) { 1472 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored); 1473 PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored, 1474 diag::Severity::Ignored, SourceLocation()); 1475 } 1476 PP.DiscardUntilEndOfDirective(); 1477 } 1478 1479 /// \brief Handle '#pragma omp ...' when OpenMP is enabled. 1480 /// 1481 void 1482 PragmaOpenMPHandler::HandlePragma(Preprocessor &PP, 1483 PragmaIntroducerKind Introducer, 1484 Token &FirstTok) { 1485 SmallVector<Token, 16> Pragma; 1486 Token Tok; 1487 Tok.startToken(); 1488 Tok.setKind(tok::annot_pragma_openmp); 1489 Tok.setLocation(FirstTok.getLocation()); 1490 1491 while (Tok.isNot(tok::eod)) { 1492 Pragma.push_back(Tok); 1493 PP.Lex(Tok); 1494 } 1495 SourceLocation EodLoc = Tok.getLocation(); 1496 Tok.startToken(); 1497 Tok.setKind(tok::annot_pragma_openmp_end); 1498 Tok.setLocation(EodLoc); 1499 Pragma.push_back(Tok); 1500 1501 Token *Toks = new Token[Pragma.size()]; 1502 std::copy(Pragma.begin(), Pragma.end(), Toks); 1503 PP.EnterTokenStream(Toks, Pragma.size(), 1504 /*DisableMacroExpansion=*/false, /*OwnsTokens=*/true); 1505 } 1506 1507 /// \brief Handle '#pragma pointers_to_members' 1508 // The grammar for this pragma is as follows: 1509 // 1510 // <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance' 1511 // 1512 // #pragma pointers_to_members '(' 'best_case' ')' 1513 // #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')' 1514 // #pragma pointers_to_members '(' inheritance-model ')' 1515 void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP, 1516 PragmaIntroducerKind Introducer, 1517 Token &Tok) { 1518 SourceLocation PointersToMembersLoc = Tok.getLocation(); 1519 PP.Lex(Tok); 1520 if (Tok.isNot(tok::l_paren)) { 1521 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen) 1522 << "pointers_to_members"; 1523 return; 1524 } 1525 PP.Lex(Tok); 1526 const IdentifierInfo *Arg = Tok.getIdentifierInfo(); 1527 if (!Arg) { 1528 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 1529 << "pointers_to_members"; 1530 return; 1531 } 1532 PP.Lex(Tok); 1533 1534 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod; 1535 if (Arg->isStr("best_case")) { 1536 RepresentationMethod = LangOptions::PPTMK_BestCase; 1537 } else { 1538 if (Arg->isStr("full_generality")) { 1539 if (Tok.is(tok::comma)) { 1540 PP.Lex(Tok); 1541 1542 Arg = Tok.getIdentifierInfo(); 1543 if (!Arg) { 1544 PP.Diag(Tok.getLocation(), 1545 diag::err_pragma_pointers_to_members_unknown_kind) 1546 << Tok.getKind() << /*OnlyInheritanceModels*/ 0; 1547 return; 1548 } 1549 PP.Lex(Tok); 1550 } else if (Tok.is(tok::r_paren)) { 1551 // #pragma pointers_to_members(full_generality) implicitly specifies 1552 // virtual_inheritance. 1553 Arg = nullptr; 1554 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance; 1555 } else { 1556 PP.Diag(Tok.getLocation(), diag::err_expected_punc) 1557 << "full_generality"; 1558 return; 1559 } 1560 } 1561 1562 if (Arg) { 1563 if (Arg->isStr("single_inheritance")) { 1564 RepresentationMethod = 1565 LangOptions::PPTMK_FullGeneralitySingleInheritance; 1566 } else if (Arg->isStr("multiple_inheritance")) { 1567 RepresentationMethod = 1568 LangOptions::PPTMK_FullGeneralityMultipleInheritance; 1569 } else if (Arg->isStr("virtual_inheritance")) { 1570 RepresentationMethod = 1571 LangOptions::PPTMK_FullGeneralityVirtualInheritance; 1572 } else { 1573 PP.Diag(Tok.getLocation(), 1574 diag::err_pragma_pointers_to_members_unknown_kind) 1575 << Arg << /*HasPointerDeclaration*/ 1; 1576 return; 1577 } 1578 } 1579 } 1580 1581 if (Tok.isNot(tok::r_paren)) { 1582 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after) 1583 << (Arg ? Arg->getName() : "full_generality"); 1584 return; 1585 } 1586 1587 SourceLocation EndLoc = Tok.getLocation(); 1588 PP.Lex(Tok); 1589 if (Tok.isNot(tok::eod)) { 1590 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 1591 << "pointers_to_members"; 1592 return; 1593 } 1594 1595 Token AnnotTok; 1596 AnnotTok.startToken(); 1597 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members); 1598 AnnotTok.setLocation(PointersToMembersLoc); 1599 AnnotTok.setAnnotationEndLoc(EndLoc); 1600 AnnotTok.setAnnotationValue( 1601 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod))); 1602 PP.EnterToken(AnnotTok); 1603 } 1604 1605 /// \brief Handle '#pragma vtordisp' 1606 // The grammar for this pragma is as follows: 1607 // 1608 // <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' ) 1609 // 1610 // #pragma vtordisp '(' ['push' ','] vtordisp-mode ')' 1611 // #pragma vtordisp '(' 'pop' ')' 1612 // #pragma vtordisp '(' ')' 1613 void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP, 1614 PragmaIntroducerKind Introducer, 1615 Token &Tok) { 1616 SourceLocation VtorDispLoc = Tok.getLocation(); 1617 PP.Lex(Tok); 1618 if (Tok.isNot(tok::l_paren)) { 1619 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp"; 1620 return; 1621 } 1622 PP.Lex(Tok); 1623 1624 Sema::PragmaVtorDispKind Kind = Sema::PVDK_Set; 1625 const IdentifierInfo *II = Tok.getIdentifierInfo(); 1626 if (II) { 1627 if (II->isStr("push")) { 1628 // #pragma vtordisp(push, mode) 1629 PP.Lex(Tok); 1630 if (Tok.isNot(tok::comma)) { 1631 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp"; 1632 return; 1633 } 1634 PP.Lex(Tok); 1635 Kind = Sema::PVDK_Push; 1636 // not push, could be on/off 1637 } else if (II->isStr("pop")) { 1638 // #pragma vtordisp(pop) 1639 PP.Lex(Tok); 1640 Kind = Sema::PVDK_Pop; 1641 } 1642 // not push or pop, could be on/off 1643 } else { 1644 if (Tok.is(tok::r_paren)) { 1645 // #pragma vtordisp() 1646 Kind = Sema::PVDK_Reset; 1647 } 1648 } 1649 1650 1651 uint64_t Value = 0; 1652 if (Kind == Sema::PVDK_Push || Kind == Sema::PVDK_Set) { 1653 const IdentifierInfo *II = Tok.getIdentifierInfo(); 1654 if (II && II->isStr("off")) { 1655 PP.Lex(Tok); 1656 Value = 0; 1657 } else if (II && II->isStr("on")) { 1658 PP.Lex(Tok); 1659 Value = 1; 1660 } else if (Tok.is(tok::numeric_constant) && 1661 PP.parseSimpleIntegerLiteral(Tok, Value)) { 1662 if (Value > 2) { 1663 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer) 1664 << 0 << 2 << "vtordisp"; 1665 return; 1666 } 1667 } else { 1668 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) 1669 << "vtordisp"; 1670 return; 1671 } 1672 } 1673 1674 // Finish the pragma: ')' $ 1675 if (Tok.isNot(tok::r_paren)) { 1676 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp"; 1677 return; 1678 } 1679 SourceLocation EndLoc = Tok.getLocation(); 1680 PP.Lex(Tok); 1681 if (Tok.isNot(tok::eod)) { 1682 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 1683 << "vtordisp"; 1684 return; 1685 } 1686 1687 // Enter the annotation. 1688 Token AnnotTok; 1689 AnnotTok.startToken(); 1690 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp); 1691 AnnotTok.setLocation(VtorDispLoc); 1692 AnnotTok.setAnnotationEndLoc(EndLoc); 1693 AnnotTok.setAnnotationValue(reinterpret_cast<void *>( 1694 static_cast<uintptr_t>((Kind << 16) | (Value & 0xFFFF)))); 1695 PP.EnterToken(AnnotTok); 1696 } 1697 1698 /// \brief Handle all MS pragmas. Simply forwards the tokens after inserting 1699 /// an annotation token. 1700 void PragmaMSPragma::HandlePragma(Preprocessor &PP, 1701 PragmaIntroducerKind Introducer, 1702 Token &Tok) { 1703 Token EoF, AnnotTok; 1704 EoF.startToken(); 1705 EoF.setKind(tok::eof); 1706 AnnotTok.startToken(); 1707 AnnotTok.setKind(tok::annot_pragma_ms_pragma); 1708 AnnotTok.setLocation(Tok.getLocation()); 1709 AnnotTok.setAnnotationEndLoc(Tok.getLocation()); 1710 SmallVector<Token, 8> TokenVector; 1711 // Suck up all of the tokens before the eod. 1712 for (; Tok.isNot(tok::eod); PP.Lex(Tok)) { 1713 TokenVector.push_back(Tok); 1714 AnnotTok.setAnnotationEndLoc(Tok.getLocation()); 1715 } 1716 // Add a sentinal EoF token to the end of the list. 1717 TokenVector.push_back(EoF); 1718 // We must allocate this array with new because EnterTokenStream is going to 1719 // delete it later. 1720 Token *TokenArray = new Token[TokenVector.size()]; 1721 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray); 1722 auto Value = new (PP.getPreprocessorAllocator()) 1723 std::pair<Token*, size_t>(std::make_pair(TokenArray, TokenVector.size())); 1724 AnnotTok.setAnnotationValue(Value); 1725 PP.EnterToken(AnnotTok); 1726 } 1727 1728 /// \brief Handle the Microsoft \#pragma detect_mismatch extension. 1729 /// 1730 /// The syntax is: 1731 /// \code 1732 /// #pragma detect_mismatch("name", "value") 1733 /// \endcode 1734 /// Where 'name' and 'value' are quoted strings. The values are embedded in 1735 /// the object file and passed along to the linker. If the linker detects a 1736 /// mismatch in the object file's values for the given name, a LNK2038 error 1737 /// is emitted. See MSDN for more details. 1738 void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP, 1739 PragmaIntroducerKind Introducer, 1740 Token &Tok) { 1741 SourceLocation CommentLoc = Tok.getLocation(); 1742 PP.Lex(Tok); 1743 if (Tok.isNot(tok::l_paren)) { 1744 PP.Diag(CommentLoc, diag::err_expected) << tok::l_paren; 1745 return; 1746 } 1747 1748 // Read the name to embed, which must be a string literal. 1749 std::string NameString; 1750 if (!PP.LexStringLiteral(Tok, NameString, 1751 "pragma detect_mismatch", 1752 /*MacroExpansion=*/true)) 1753 return; 1754 1755 // Read the comma followed by a second string literal. 1756 std::string ValueString; 1757 if (Tok.isNot(tok::comma)) { 1758 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed); 1759 return; 1760 } 1761 1762 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch", 1763 /*MacroExpansion=*/true)) 1764 return; 1765 1766 if (Tok.isNot(tok::r_paren)) { 1767 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren; 1768 return; 1769 } 1770 PP.Lex(Tok); // Eat the r_paren. 1771 1772 if (Tok.isNot(tok::eod)) { 1773 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed); 1774 return; 1775 } 1776 1777 // If the pragma is lexically sound, notify any interested PPCallbacks. 1778 if (PP.getPPCallbacks()) 1779 PP.getPPCallbacks()->PragmaDetectMismatch(CommentLoc, NameString, 1780 ValueString); 1781 1782 Actions.ActOnPragmaDetectMismatch(NameString, ValueString); 1783 } 1784 1785 /// \brief Handle the microsoft \#pragma comment extension. 1786 /// 1787 /// The syntax is: 1788 /// \code 1789 /// #pragma comment(linker, "foo") 1790 /// \endcode 1791 /// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user. 1792 /// "foo" is a string, which is fully macro expanded, and permits string 1793 /// concatenation, embedded escape characters etc. See MSDN for more details. 1794 void PragmaCommentHandler::HandlePragma(Preprocessor &PP, 1795 PragmaIntroducerKind Introducer, 1796 Token &Tok) { 1797 SourceLocation CommentLoc = Tok.getLocation(); 1798 PP.Lex(Tok); 1799 if (Tok.isNot(tok::l_paren)) { 1800 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed); 1801 return; 1802 } 1803 1804 // Read the identifier. 1805 PP.Lex(Tok); 1806 if (Tok.isNot(tok::identifier)) { 1807 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed); 1808 return; 1809 } 1810 1811 // Verify that this is one of the 5 whitelisted options. 1812 IdentifierInfo *II = Tok.getIdentifierInfo(); 1813 Sema::PragmaMSCommentKind Kind = 1814 llvm::StringSwitch<Sema::PragmaMSCommentKind>(II->getName()) 1815 .Case("linker", Sema::PCK_Linker) 1816 .Case("lib", Sema::PCK_Lib) 1817 .Case("compiler", Sema::PCK_Compiler) 1818 .Case("exestr", Sema::PCK_ExeStr) 1819 .Case("user", Sema::PCK_User) 1820 .Default(Sema::PCK_Unknown); 1821 if (Kind == Sema::PCK_Unknown) { 1822 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind); 1823 return; 1824 } 1825 1826 // On PS4, issue a warning about any pragma comments other than 1827 // #pragma comment lib. 1828 if (PP.getTargetInfo().getTriple().isPS4() && Kind != Sema::PCK_Lib) { 1829 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored) 1830 << II->getName(); 1831 return; 1832 } 1833 1834 // Read the optional string if present. 1835 PP.Lex(Tok); 1836 std::string ArgumentString; 1837 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString, 1838 "pragma comment", 1839 /*MacroExpansion=*/true)) 1840 return; 1841 1842 // FIXME: warn that 'exestr' is deprecated. 1843 // FIXME: If the kind is "compiler" warn if the string is present (it is 1844 // ignored). 1845 // The MSDN docs say that "lib" and "linker" require a string and have a short 1846 // whitelist of linker options they support, but in practice MSVC doesn't 1847 // issue a diagnostic. Therefore neither does clang. 1848 1849 if (Tok.isNot(tok::r_paren)) { 1850 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed); 1851 return; 1852 } 1853 PP.Lex(Tok); // eat the r_paren. 1854 1855 if (Tok.isNot(tok::eod)) { 1856 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed); 1857 return; 1858 } 1859 1860 // If the pragma is lexically sound, notify any interested PPCallbacks. 1861 if (PP.getPPCallbacks()) 1862 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString); 1863 1864 Actions.ActOnPragmaMSComment(Kind, ArgumentString); 1865 } 1866 1867 // #pragma clang optimize off 1868 // #pragma clang optimize on 1869 void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP, 1870 PragmaIntroducerKind Introducer, 1871 Token &FirstToken) { 1872 Token Tok; 1873 PP.Lex(Tok); 1874 if (Tok.is(tok::eod)) { 1875 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument) 1876 << "clang optimize" << /*Expected=*/true << "'on' or 'off'"; 1877 return; 1878 } 1879 if (Tok.isNot(tok::identifier)) { 1880 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument) 1881 << PP.getSpelling(Tok); 1882 return; 1883 } 1884 const IdentifierInfo *II = Tok.getIdentifierInfo(); 1885 // The only accepted values are 'on' or 'off'. 1886 bool IsOn = false; 1887 if (II->isStr("on")) { 1888 IsOn = true; 1889 } else if (!II->isStr("off")) { 1890 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument) 1891 << PP.getSpelling(Tok); 1892 return; 1893 } 1894 PP.Lex(Tok); 1895 1896 if (Tok.isNot(tok::eod)) { 1897 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument) 1898 << PP.getSpelling(Tok); 1899 return; 1900 } 1901 1902 Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation()); 1903 } 1904 1905 /// \brief Parses loop or unroll pragma hint value and fills in Info. 1906 static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName, 1907 Token Option, bool ValueInParens, 1908 PragmaLoopHintInfo &Info) { 1909 SmallVector<Token, 1> ValueList; 1910 int OpenParens = ValueInParens ? 1 : 0; 1911 // Read constant expression. 1912 while (Tok.isNot(tok::eod)) { 1913 if (Tok.is(tok::l_paren)) 1914 OpenParens++; 1915 else if (Tok.is(tok::r_paren)) { 1916 OpenParens--; 1917 if (OpenParens == 0 && ValueInParens) 1918 break; 1919 } 1920 1921 ValueList.push_back(Tok); 1922 PP.Lex(Tok); 1923 } 1924 1925 if (ValueInParens) { 1926 // Read ')' 1927 if (Tok.isNot(tok::r_paren)) { 1928 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren; 1929 return true; 1930 } 1931 PP.Lex(Tok); 1932 } 1933 1934 Token EOFTok; 1935 EOFTok.startToken(); 1936 EOFTok.setKind(tok::eof); 1937 EOFTok.setLocation(Tok.getLocation()); 1938 ValueList.push_back(EOFTok); // Terminates expression for parsing. 1939 1940 Info.Toks = llvm::makeArrayRef(ValueList).copy(PP.getPreprocessorAllocator()); 1941 1942 Info.PragmaName = PragmaName; 1943 Info.Option = Option; 1944 return false; 1945 } 1946 1947 /// \brief Handle the \#pragma clang loop directive. 1948 /// #pragma clang 'loop' loop-hints 1949 /// 1950 /// loop-hints: 1951 /// loop-hint loop-hints[opt] 1952 /// 1953 /// loop-hint: 1954 /// 'vectorize' '(' loop-hint-keyword ')' 1955 /// 'interleave' '(' loop-hint-keyword ')' 1956 /// 'unroll' '(' unroll-hint-keyword ')' 1957 /// 'vectorize_width' '(' loop-hint-value ')' 1958 /// 'interleave_count' '(' loop-hint-value ')' 1959 /// 'unroll_count' '(' loop-hint-value ')' 1960 /// 1961 /// loop-hint-keyword: 1962 /// 'enable' 1963 /// 'disable' 1964 /// 'assume_safety' 1965 /// 1966 /// unroll-hint-keyword: 1967 /// 'enable' 1968 /// 'disable' 1969 /// 'full' 1970 /// 1971 /// loop-hint-value: 1972 /// constant-expression 1973 /// 1974 /// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to 1975 /// try vectorizing the instructions of the loop it precedes. Specifying 1976 /// interleave(enable) or interleave_count(_value_) instructs llvm to try 1977 /// interleaving multiple iterations of the loop it precedes. The width of the 1978 /// vector instructions is specified by vectorize_width() and the number of 1979 /// interleaved loop iterations is specified by interleave_count(). Specifying a 1980 /// value of 1 effectively disables vectorization/interleaving, even if it is 1981 /// possible and profitable, and 0 is invalid. The loop vectorizer currently 1982 /// only works on inner loops. 1983 /// 1984 /// The unroll and unroll_count directives control the concatenation 1985 /// unroller. Specifying unroll(enable) instructs llvm to unroll the loop 1986 /// completely if the trip count is known at compile time and unroll partially 1987 /// if the trip count is not known. Specifying unroll(full) is similar to 1988 /// unroll(enable) but will unroll the loop only if the trip count is known at 1989 /// compile time. Specifying unroll(disable) disables unrolling for the 1990 /// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the 1991 /// loop the number of times indicated by the value. 1992 void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP, 1993 PragmaIntroducerKind Introducer, 1994 Token &Tok) { 1995 // Incoming token is "loop" from "#pragma clang loop". 1996 Token PragmaName = Tok; 1997 SmallVector<Token, 1> TokenList; 1998 1999 // Lex the optimization option and verify it is an identifier. 2000 PP.Lex(Tok); 2001 if (Tok.isNot(tok::identifier)) { 2002 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option) 2003 << /*MissingOption=*/true << ""; 2004 return; 2005 } 2006 2007 while (Tok.is(tok::identifier)) { 2008 Token Option = Tok; 2009 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo(); 2010 2011 bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName()) 2012 .Case("vectorize", true) 2013 .Case("interleave", true) 2014 .Case("unroll", true) 2015 .Case("vectorize_width", true) 2016 .Case("interleave_count", true) 2017 .Case("unroll_count", true) 2018 .Default(false); 2019 if (!OptionValid) { 2020 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option) 2021 << /*MissingOption=*/false << OptionInfo; 2022 return; 2023 } 2024 PP.Lex(Tok); 2025 2026 // Read '(' 2027 if (Tok.isNot(tok::l_paren)) { 2028 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren; 2029 return; 2030 } 2031 PP.Lex(Tok); 2032 2033 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo; 2034 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true, 2035 *Info)) 2036 return; 2037 2038 // Generate the loop hint token. 2039 Token LoopHintTok; 2040 LoopHintTok.startToken(); 2041 LoopHintTok.setKind(tok::annot_pragma_loop_hint); 2042 LoopHintTok.setLocation(PragmaName.getLocation()); 2043 LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation()); 2044 LoopHintTok.setAnnotationValue(static_cast<void *>(Info)); 2045 TokenList.push_back(LoopHintTok); 2046 } 2047 2048 if (Tok.isNot(tok::eod)) { 2049 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 2050 << "clang loop"; 2051 return; 2052 } 2053 2054 Token *TokenArray = new Token[TokenList.size()]; 2055 std::copy(TokenList.begin(), TokenList.end(), TokenArray); 2056 2057 PP.EnterTokenStream(TokenArray, TokenList.size(), 2058 /*DisableMacroExpansion=*/false, 2059 /*OwnsTokens=*/true); 2060 } 2061 2062 /// \brief Handle the loop unroll optimization pragmas. 2063 /// #pragma unroll 2064 /// #pragma unroll unroll-hint-value 2065 /// #pragma unroll '(' unroll-hint-value ')' 2066 /// #pragma nounroll 2067 /// 2068 /// unroll-hint-value: 2069 /// constant-expression 2070 /// 2071 /// Loop unrolling hints can be specified with '#pragma unroll' or 2072 /// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally 2073 /// contained in parentheses. With no argument the directive instructs llvm to 2074 /// try to unroll the loop completely. A positive integer argument can be 2075 /// specified to indicate the number of times the loop should be unrolled. To 2076 /// maximize compatibility with other compilers the unroll count argument can be 2077 /// specified with or without parentheses. Specifying, '#pragma nounroll' 2078 /// disables unrolling of the loop. 2079 void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP, 2080 PragmaIntroducerKind Introducer, 2081 Token &Tok) { 2082 // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for 2083 // "#pragma nounroll". 2084 Token PragmaName = Tok; 2085 PP.Lex(Tok); 2086 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo; 2087 if (Tok.is(tok::eod)) { 2088 // nounroll or unroll pragma without an argument. 2089 Info->PragmaName = PragmaName; 2090 Info->Option.startToken(); 2091 } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll") { 2092 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 2093 << "nounroll"; 2094 return; 2095 } else { 2096 // Unroll pragma with an argument: "#pragma unroll N" or 2097 // "#pragma unroll(N)". 2098 // Read '(' if it exists. 2099 bool ValueInParens = Tok.is(tok::l_paren); 2100 if (ValueInParens) 2101 PP.Lex(Tok); 2102 2103 Token Option; 2104 Option.startToken(); 2105 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info)) 2106 return; 2107 2108 // In CUDA, the argument to '#pragma unroll' should not be contained in 2109 // parentheses. 2110 if (PP.getLangOpts().CUDA && ValueInParens) 2111 PP.Diag(Info->Toks[0].getLocation(), 2112 diag::warn_pragma_unroll_cuda_value_in_parens); 2113 2114 if (Tok.isNot(tok::eod)) { 2115 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 2116 << "unroll"; 2117 return; 2118 } 2119 } 2120 2121 // Generate the hint token. 2122 Token *TokenArray = new Token[1]; 2123 TokenArray[0].startToken(); 2124 TokenArray[0].setKind(tok::annot_pragma_loop_hint); 2125 TokenArray[0].setLocation(PragmaName.getLocation()); 2126 TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation()); 2127 TokenArray[0].setAnnotationValue(static_cast<void *>(Info)); 2128 PP.EnterTokenStream(TokenArray, 1, /*DisableMacroExpansion=*/false, 2129 /*OwnsTokens=*/true); 2130 } 2131