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