1 //===--- ParsePragma.cpp - Language specific pragma parsing ---------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the language specific #pragma handlers. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "clang/AST/ASTContext.h" 14 #include "clang/Basic/PragmaKinds.h" 15 #include "clang/Basic/TargetInfo.h" 16 #include "clang/Lex/Preprocessor.h" 17 #include "clang/Parse/LoopHint.h" 18 #include "clang/Parse/ParseDiagnostic.h" 19 #include "clang/Parse/Parser.h" 20 #include "clang/Parse/RAIIObjectsForParser.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, PragmaIntroducer Introducer, 30 Token &FirstToken) override; 31 }; 32 33 struct PragmaGCCVisibilityHandler : public PragmaHandler { 34 explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {} 35 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 36 Token &FirstToken) override; 37 }; 38 39 struct PragmaOptionsHandler : public PragmaHandler { 40 explicit PragmaOptionsHandler() : PragmaHandler("options") {} 41 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 42 Token &FirstToken) override; 43 }; 44 45 struct PragmaPackHandler : public PragmaHandler { 46 explicit PragmaPackHandler() : PragmaHandler("pack") {} 47 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 48 Token &FirstToken) override; 49 }; 50 51 struct PragmaClangSectionHandler : public PragmaHandler { 52 explicit PragmaClangSectionHandler(Sema &S) 53 : PragmaHandler("section"), Actions(S) {} 54 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 55 Token &FirstToken) override; 56 57 private: 58 Sema &Actions; 59 }; 60 61 struct PragmaMSStructHandler : public PragmaHandler { 62 explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {} 63 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 64 Token &FirstToken) override; 65 }; 66 67 struct PragmaUnusedHandler : public PragmaHandler { 68 PragmaUnusedHandler() : PragmaHandler("unused") {} 69 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 70 Token &FirstToken) override; 71 }; 72 73 struct PragmaWeakHandler : public PragmaHandler { 74 explicit PragmaWeakHandler() : PragmaHandler("weak") {} 75 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 76 Token &FirstToken) override; 77 }; 78 79 struct PragmaRedefineExtnameHandler : public PragmaHandler { 80 explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {} 81 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 82 Token &FirstToken) override; 83 }; 84 85 struct PragmaOpenCLExtensionHandler : public PragmaHandler { 86 PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {} 87 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 88 Token &FirstToken) override; 89 }; 90 91 92 struct PragmaFPContractHandler : public PragmaHandler { 93 PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {} 94 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 95 Token &FirstToken) override; 96 }; 97 98 // Pragma STDC implementations. 99 100 /// PragmaSTDC_FENV_ACCESSHandler - "\#pragma STDC FENV_ACCESS ...". 101 struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler { 102 PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {} 103 104 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 105 Token &Tok) override { 106 tok::OnOffSwitch OOS; 107 if (PP.LexOnOffSwitch(OOS)) 108 return; 109 if (OOS == tok::OOS_ON) { 110 PP.Diag(Tok, diag::warn_stdc_fenv_access_not_supported); 111 } 112 113 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1), 114 1); 115 Toks[0].startToken(); 116 Toks[0].setKind(tok::annot_pragma_fenv_access); 117 Toks[0].setLocation(Tok.getLocation()); 118 Toks[0].setAnnotationEndLoc(Tok.getLocation()); 119 Toks[0].setAnnotationValue(reinterpret_cast<void*>( 120 static_cast<uintptr_t>(OOS))); 121 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 122 /*IsReinject=*/false); 123 } 124 }; 125 126 /// PragmaSTDC_CX_LIMITED_RANGEHandler - "\#pragma STDC CX_LIMITED_RANGE ...". 127 struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler { 128 PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {} 129 130 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 131 Token &Tok) override { 132 tok::OnOffSwitch OOS; 133 PP.LexOnOffSwitch(OOS); 134 } 135 }; 136 137 /// PragmaSTDC_UnknownHandler - "\#pragma STDC ...". 138 struct PragmaSTDC_UnknownHandler : public PragmaHandler { 139 PragmaSTDC_UnknownHandler() = default; 140 141 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 142 Token &UnknownTok) override { 143 // C99 6.10.6p2, unknown forms are not allowed. 144 PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored); 145 } 146 }; 147 148 struct PragmaFPHandler : public PragmaHandler { 149 PragmaFPHandler() : PragmaHandler("fp") {} 150 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 151 Token &FirstToken) override; 152 }; 153 154 struct PragmaNoOpenMPHandler : public PragmaHandler { 155 PragmaNoOpenMPHandler() : PragmaHandler("omp") { } 156 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 157 Token &FirstToken) override; 158 }; 159 160 struct PragmaOpenMPHandler : public PragmaHandler { 161 PragmaOpenMPHandler() : PragmaHandler("omp") { } 162 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 163 Token &FirstToken) override; 164 }; 165 166 /// PragmaCommentHandler - "\#pragma comment ...". 167 struct PragmaCommentHandler : public PragmaHandler { 168 PragmaCommentHandler(Sema &Actions) 169 : PragmaHandler("comment"), Actions(Actions) {} 170 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 171 Token &FirstToken) override; 172 173 private: 174 Sema &Actions; 175 }; 176 177 struct PragmaDetectMismatchHandler : public PragmaHandler { 178 PragmaDetectMismatchHandler(Sema &Actions) 179 : PragmaHandler("detect_mismatch"), Actions(Actions) {} 180 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 181 Token &FirstToken) override; 182 183 private: 184 Sema &Actions; 185 }; 186 187 struct PragmaMSPointersToMembers : public PragmaHandler { 188 explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {} 189 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 190 Token &FirstToken) override; 191 }; 192 193 struct PragmaMSVtorDisp : public PragmaHandler { 194 explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {} 195 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 196 Token &FirstToken) override; 197 }; 198 199 struct PragmaMSPragma : public PragmaHandler { 200 explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {} 201 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 202 Token &FirstToken) override; 203 }; 204 205 /// PragmaOptimizeHandler - "\#pragma clang optimize on/off". 206 struct PragmaOptimizeHandler : public PragmaHandler { 207 PragmaOptimizeHandler(Sema &S) 208 : PragmaHandler("optimize"), Actions(S) {} 209 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 210 Token &FirstToken) override; 211 212 private: 213 Sema &Actions; 214 }; 215 216 struct PragmaLoopHintHandler : public PragmaHandler { 217 PragmaLoopHintHandler() : PragmaHandler("loop") {} 218 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 219 Token &FirstToken) override; 220 }; 221 222 struct PragmaUnrollHintHandler : public PragmaHandler { 223 PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {} 224 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 225 Token &FirstToken) override; 226 }; 227 228 struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler { 229 PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {} 230 }; 231 232 struct PragmaMSIntrinsicHandler : public PragmaHandler { 233 PragmaMSIntrinsicHandler() : PragmaHandler("intrinsic") {} 234 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 235 Token &FirstToken) override; 236 }; 237 238 struct PragmaMSOptimizeHandler : public PragmaHandler { 239 PragmaMSOptimizeHandler() : PragmaHandler("optimize") {} 240 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 241 Token &FirstToken) override; 242 }; 243 244 struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler { 245 PragmaForceCUDAHostDeviceHandler(Sema &Actions) 246 : PragmaHandler("force_cuda_host_device"), Actions(Actions) {} 247 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 248 Token &FirstToken) override; 249 250 private: 251 Sema &Actions; 252 }; 253 254 /// PragmaAttributeHandler - "\#pragma clang attribute ...". 255 struct PragmaAttributeHandler : public PragmaHandler { 256 PragmaAttributeHandler(AttributeFactory &AttrFactory) 257 : PragmaHandler("attribute"), AttributesForPragmaAttribute(AttrFactory) {} 258 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 259 Token &FirstToken) override; 260 261 /// A pool of attributes that were parsed in \#pragma clang attribute. 262 ParsedAttributes AttributesForPragmaAttribute; 263 }; 264 265 } // end namespace 266 267 void Parser::initializePragmaHandlers() { 268 AlignHandler = std::make_unique<PragmaAlignHandler>(); 269 PP.AddPragmaHandler(AlignHandler.get()); 270 271 GCCVisibilityHandler = std::make_unique<PragmaGCCVisibilityHandler>(); 272 PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get()); 273 274 OptionsHandler = std::make_unique<PragmaOptionsHandler>(); 275 PP.AddPragmaHandler(OptionsHandler.get()); 276 277 PackHandler = std::make_unique<PragmaPackHandler>(); 278 PP.AddPragmaHandler(PackHandler.get()); 279 280 MSStructHandler = std::make_unique<PragmaMSStructHandler>(); 281 PP.AddPragmaHandler(MSStructHandler.get()); 282 283 UnusedHandler = std::make_unique<PragmaUnusedHandler>(); 284 PP.AddPragmaHandler(UnusedHandler.get()); 285 286 WeakHandler = std::make_unique<PragmaWeakHandler>(); 287 PP.AddPragmaHandler(WeakHandler.get()); 288 289 RedefineExtnameHandler = std::make_unique<PragmaRedefineExtnameHandler>(); 290 PP.AddPragmaHandler(RedefineExtnameHandler.get()); 291 292 FPContractHandler = std::make_unique<PragmaFPContractHandler>(); 293 PP.AddPragmaHandler("STDC", FPContractHandler.get()); 294 295 STDCFENVHandler = std::make_unique<PragmaSTDC_FENV_ACCESSHandler>(); 296 PP.AddPragmaHandler("STDC", STDCFENVHandler.get()); 297 298 STDCCXLIMITHandler = std::make_unique<PragmaSTDC_CX_LIMITED_RANGEHandler>(); 299 PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get()); 300 301 STDCUnknownHandler = std::make_unique<PragmaSTDC_UnknownHandler>(); 302 PP.AddPragmaHandler("STDC", STDCUnknownHandler.get()); 303 304 PCSectionHandler = std::make_unique<PragmaClangSectionHandler>(Actions); 305 PP.AddPragmaHandler("clang", PCSectionHandler.get()); 306 307 if (getLangOpts().OpenCL) { 308 OpenCLExtensionHandler = std::make_unique<PragmaOpenCLExtensionHandler>(); 309 PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get()); 310 311 PP.AddPragmaHandler("OPENCL", FPContractHandler.get()); 312 } 313 if (getLangOpts().OpenMP) 314 OpenMPHandler = std::make_unique<PragmaOpenMPHandler>(); 315 else 316 OpenMPHandler = std::make_unique<PragmaNoOpenMPHandler>(); 317 PP.AddPragmaHandler(OpenMPHandler.get()); 318 319 if (getLangOpts().MicrosoftExt || 320 getTargetInfo().getTriple().isOSBinFormatELF()) { 321 MSCommentHandler = std::make_unique<PragmaCommentHandler>(Actions); 322 PP.AddPragmaHandler(MSCommentHandler.get()); 323 } 324 325 if (getLangOpts().MicrosoftExt) { 326 MSDetectMismatchHandler = 327 std::make_unique<PragmaDetectMismatchHandler>(Actions); 328 PP.AddPragmaHandler(MSDetectMismatchHandler.get()); 329 MSPointersToMembers = std::make_unique<PragmaMSPointersToMembers>(); 330 PP.AddPragmaHandler(MSPointersToMembers.get()); 331 MSVtorDisp = std::make_unique<PragmaMSVtorDisp>(); 332 PP.AddPragmaHandler(MSVtorDisp.get()); 333 MSInitSeg = std::make_unique<PragmaMSPragma>("init_seg"); 334 PP.AddPragmaHandler(MSInitSeg.get()); 335 MSDataSeg = std::make_unique<PragmaMSPragma>("data_seg"); 336 PP.AddPragmaHandler(MSDataSeg.get()); 337 MSBSSSeg = std::make_unique<PragmaMSPragma>("bss_seg"); 338 PP.AddPragmaHandler(MSBSSSeg.get()); 339 MSConstSeg = std::make_unique<PragmaMSPragma>("const_seg"); 340 PP.AddPragmaHandler(MSConstSeg.get()); 341 MSCodeSeg = std::make_unique<PragmaMSPragma>("code_seg"); 342 PP.AddPragmaHandler(MSCodeSeg.get()); 343 MSSection = std::make_unique<PragmaMSPragma>("section"); 344 PP.AddPragmaHandler(MSSection.get()); 345 MSRuntimeChecks = std::make_unique<PragmaMSRuntimeChecksHandler>(); 346 PP.AddPragmaHandler(MSRuntimeChecks.get()); 347 MSIntrinsic = std::make_unique<PragmaMSIntrinsicHandler>(); 348 PP.AddPragmaHandler(MSIntrinsic.get()); 349 MSOptimize = std::make_unique<PragmaMSOptimizeHandler>(); 350 PP.AddPragmaHandler(MSOptimize.get()); 351 } 352 353 if (getLangOpts().CUDA) { 354 CUDAForceHostDeviceHandler = 355 std::make_unique<PragmaForceCUDAHostDeviceHandler>(Actions); 356 PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get()); 357 } 358 359 OptimizeHandler = std::make_unique<PragmaOptimizeHandler>(Actions); 360 PP.AddPragmaHandler("clang", OptimizeHandler.get()); 361 362 LoopHintHandler = std::make_unique<PragmaLoopHintHandler>(); 363 PP.AddPragmaHandler("clang", LoopHintHandler.get()); 364 365 UnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("unroll"); 366 PP.AddPragmaHandler(UnrollHintHandler.get()); 367 368 NoUnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("nounroll"); 369 PP.AddPragmaHandler(NoUnrollHintHandler.get()); 370 371 UnrollAndJamHintHandler = 372 std::make_unique<PragmaUnrollHintHandler>("unroll_and_jam"); 373 PP.AddPragmaHandler(UnrollAndJamHintHandler.get()); 374 375 NoUnrollAndJamHintHandler = 376 std::make_unique<PragmaUnrollHintHandler>("nounroll_and_jam"); 377 PP.AddPragmaHandler(NoUnrollAndJamHintHandler.get()); 378 379 FPHandler = std::make_unique<PragmaFPHandler>(); 380 PP.AddPragmaHandler("clang", FPHandler.get()); 381 382 AttributePragmaHandler = 383 std::make_unique<PragmaAttributeHandler>(AttrFactory); 384 PP.AddPragmaHandler("clang", AttributePragmaHandler.get()); 385 } 386 387 void Parser::resetPragmaHandlers() { 388 // Remove the pragma handlers we installed. 389 PP.RemovePragmaHandler(AlignHandler.get()); 390 AlignHandler.reset(); 391 PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get()); 392 GCCVisibilityHandler.reset(); 393 PP.RemovePragmaHandler(OptionsHandler.get()); 394 OptionsHandler.reset(); 395 PP.RemovePragmaHandler(PackHandler.get()); 396 PackHandler.reset(); 397 PP.RemovePragmaHandler(MSStructHandler.get()); 398 MSStructHandler.reset(); 399 PP.RemovePragmaHandler(UnusedHandler.get()); 400 UnusedHandler.reset(); 401 PP.RemovePragmaHandler(WeakHandler.get()); 402 WeakHandler.reset(); 403 PP.RemovePragmaHandler(RedefineExtnameHandler.get()); 404 RedefineExtnameHandler.reset(); 405 406 if (getLangOpts().OpenCL) { 407 PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get()); 408 OpenCLExtensionHandler.reset(); 409 PP.RemovePragmaHandler("OPENCL", FPContractHandler.get()); 410 } 411 PP.RemovePragmaHandler(OpenMPHandler.get()); 412 OpenMPHandler.reset(); 413 414 if (getLangOpts().MicrosoftExt || 415 getTargetInfo().getTriple().isOSBinFormatELF()) { 416 PP.RemovePragmaHandler(MSCommentHandler.get()); 417 MSCommentHandler.reset(); 418 } 419 420 PP.RemovePragmaHandler("clang", PCSectionHandler.get()); 421 PCSectionHandler.reset(); 422 423 if (getLangOpts().MicrosoftExt) { 424 PP.RemovePragmaHandler(MSDetectMismatchHandler.get()); 425 MSDetectMismatchHandler.reset(); 426 PP.RemovePragmaHandler(MSPointersToMembers.get()); 427 MSPointersToMembers.reset(); 428 PP.RemovePragmaHandler(MSVtorDisp.get()); 429 MSVtorDisp.reset(); 430 PP.RemovePragmaHandler(MSInitSeg.get()); 431 MSInitSeg.reset(); 432 PP.RemovePragmaHandler(MSDataSeg.get()); 433 MSDataSeg.reset(); 434 PP.RemovePragmaHandler(MSBSSSeg.get()); 435 MSBSSSeg.reset(); 436 PP.RemovePragmaHandler(MSConstSeg.get()); 437 MSConstSeg.reset(); 438 PP.RemovePragmaHandler(MSCodeSeg.get()); 439 MSCodeSeg.reset(); 440 PP.RemovePragmaHandler(MSSection.get()); 441 MSSection.reset(); 442 PP.RemovePragmaHandler(MSRuntimeChecks.get()); 443 MSRuntimeChecks.reset(); 444 PP.RemovePragmaHandler(MSIntrinsic.get()); 445 MSIntrinsic.reset(); 446 PP.RemovePragmaHandler(MSOptimize.get()); 447 MSOptimize.reset(); 448 } 449 450 if (getLangOpts().CUDA) { 451 PP.RemovePragmaHandler("clang", CUDAForceHostDeviceHandler.get()); 452 CUDAForceHostDeviceHandler.reset(); 453 } 454 455 PP.RemovePragmaHandler("STDC", FPContractHandler.get()); 456 FPContractHandler.reset(); 457 458 PP.RemovePragmaHandler("STDC", STDCFENVHandler.get()); 459 STDCFENVHandler.reset(); 460 461 PP.RemovePragmaHandler("STDC", STDCCXLIMITHandler.get()); 462 STDCCXLIMITHandler.reset(); 463 464 PP.RemovePragmaHandler("STDC", STDCUnknownHandler.get()); 465 STDCUnknownHandler.reset(); 466 467 PP.RemovePragmaHandler("clang", OptimizeHandler.get()); 468 OptimizeHandler.reset(); 469 470 PP.RemovePragmaHandler("clang", LoopHintHandler.get()); 471 LoopHintHandler.reset(); 472 473 PP.RemovePragmaHandler(UnrollHintHandler.get()); 474 UnrollHintHandler.reset(); 475 476 PP.RemovePragmaHandler(NoUnrollHintHandler.get()); 477 NoUnrollHintHandler.reset(); 478 479 PP.RemovePragmaHandler(UnrollAndJamHintHandler.get()); 480 UnrollAndJamHintHandler.reset(); 481 482 PP.RemovePragmaHandler(NoUnrollAndJamHintHandler.get()); 483 NoUnrollAndJamHintHandler.reset(); 484 485 PP.RemovePragmaHandler("clang", FPHandler.get()); 486 FPHandler.reset(); 487 488 PP.RemovePragmaHandler("clang", AttributePragmaHandler.get()); 489 AttributePragmaHandler.reset(); 490 } 491 492 /// Handle the annotation token produced for #pragma unused(...) 493 /// 494 /// Each annot_pragma_unused is followed by the argument token so e.g. 495 /// "#pragma unused(x,y)" becomes: 496 /// annot_pragma_unused 'x' annot_pragma_unused 'y' 497 void Parser::HandlePragmaUnused() { 498 assert(Tok.is(tok::annot_pragma_unused)); 499 SourceLocation UnusedLoc = ConsumeAnnotationToken(); 500 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc); 501 ConsumeToken(); // The argument token. 502 } 503 504 void Parser::HandlePragmaVisibility() { 505 assert(Tok.is(tok::annot_pragma_vis)); 506 const IdentifierInfo *VisType = 507 static_cast<IdentifierInfo *>(Tok.getAnnotationValue()); 508 SourceLocation VisLoc = ConsumeAnnotationToken(); 509 Actions.ActOnPragmaVisibility(VisType, VisLoc); 510 } 511 512 namespace { 513 struct PragmaPackInfo { 514 Sema::PragmaMsStackAction Action; 515 StringRef SlotLabel; 516 Token Alignment; 517 }; 518 } // end anonymous namespace 519 520 void Parser::HandlePragmaPack() { 521 assert(Tok.is(tok::annot_pragma_pack)); 522 PragmaPackInfo *Info = 523 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue()); 524 SourceLocation PragmaLoc = Tok.getLocation(); 525 ExprResult Alignment; 526 if (Info->Alignment.is(tok::numeric_constant)) { 527 Alignment = Actions.ActOnNumericConstant(Info->Alignment); 528 if (Alignment.isInvalid()) { 529 ConsumeAnnotationToken(); 530 return; 531 } 532 } 533 Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel, 534 Alignment.get()); 535 // Consume the token after processing the pragma to enable pragma-specific 536 // #include warnings. 537 ConsumeAnnotationToken(); 538 } 539 540 void Parser::HandlePragmaMSStruct() { 541 assert(Tok.is(tok::annot_pragma_msstruct)); 542 PragmaMSStructKind Kind = static_cast<PragmaMSStructKind>( 543 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); 544 Actions.ActOnPragmaMSStruct(Kind); 545 ConsumeAnnotationToken(); 546 } 547 548 void Parser::HandlePragmaAlign() { 549 assert(Tok.is(tok::annot_pragma_align)); 550 Sema::PragmaOptionsAlignKind Kind = 551 static_cast<Sema::PragmaOptionsAlignKind>( 552 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); 553 Actions.ActOnPragmaOptionsAlign(Kind, Tok.getLocation()); 554 // Consume the token after processing the pragma to enable pragma-specific 555 // #include warnings. 556 ConsumeAnnotationToken(); 557 } 558 559 void Parser::HandlePragmaDump() { 560 assert(Tok.is(tok::annot_pragma_dump)); 561 IdentifierInfo *II = 562 reinterpret_cast<IdentifierInfo *>(Tok.getAnnotationValue()); 563 Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II); 564 ConsumeAnnotationToken(); 565 } 566 567 void Parser::HandlePragmaWeak() { 568 assert(Tok.is(tok::annot_pragma_weak)); 569 SourceLocation PragmaLoc = ConsumeAnnotationToken(); 570 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc, 571 Tok.getLocation()); 572 ConsumeToken(); // The weak name. 573 } 574 575 void Parser::HandlePragmaWeakAlias() { 576 assert(Tok.is(tok::annot_pragma_weakalias)); 577 SourceLocation PragmaLoc = ConsumeAnnotationToken(); 578 IdentifierInfo *WeakName = Tok.getIdentifierInfo(); 579 SourceLocation WeakNameLoc = Tok.getLocation(); 580 ConsumeToken(); 581 IdentifierInfo *AliasName = Tok.getIdentifierInfo(); 582 SourceLocation AliasNameLoc = Tok.getLocation(); 583 ConsumeToken(); 584 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc, 585 WeakNameLoc, AliasNameLoc); 586 587 } 588 589 void Parser::HandlePragmaRedefineExtname() { 590 assert(Tok.is(tok::annot_pragma_redefine_extname)); 591 SourceLocation RedefLoc = ConsumeAnnotationToken(); 592 IdentifierInfo *RedefName = Tok.getIdentifierInfo(); 593 SourceLocation RedefNameLoc = Tok.getLocation(); 594 ConsumeToken(); 595 IdentifierInfo *AliasName = Tok.getIdentifierInfo(); 596 SourceLocation AliasNameLoc = Tok.getLocation(); 597 ConsumeToken(); 598 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc, 599 RedefNameLoc, AliasNameLoc); 600 } 601 602 void Parser::HandlePragmaFPContract() { 603 assert(Tok.is(tok::annot_pragma_fp_contract)); 604 tok::OnOffSwitch OOS = 605 static_cast<tok::OnOffSwitch>( 606 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); 607 608 LangOptions::FPContractModeKind FPC; 609 switch (OOS) { 610 case tok::OOS_ON: 611 FPC = LangOptions::FPC_On; 612 break; 613 case tok::OOS_OFF: 614 FPC = LangOptions::FPC_Off; 615 break; 616 case tok::OOS_DEFAULT: 617 FPC = getLangOpts().getDefaultFPContractMode(); 618 break; 619 } 620 621 Actions.ActOnPragmaFPContract(FPC); 622 ConsumeAnnotationToken(); 623 } 624 625 void Parser::HandlePragmaFEnvAccess() { 626 assert(Tok.is(tok::annot_pragma_fenv_access)); 627 tok::OnOffSwitch OOS = 628 static_cast<tok::OnOffSwitch>( 629 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); 630 631 LangOptions::FEnvAccessModeKind FPC; 632 switch (OOS) { 633 case tok::OOS_ON: 634 FPC = LangOptions::FEA_On; 635 break; 636 case tok::OOS_OFF: 637 FPC = LangOptions::FEA_Off; 638 break; 639 case tok::OOS_DEFAULT: // FIXME: Add this cli option when it makes sense. 640 FPC = LangOptions::FEA_Off; 641 break; 642 } 643 644 Actions.ActOnPragmaFEnvAccess(FPC); 645 ConsumeAnnotationToken(); 646 } 647 648 649 StmtResult Parser::HandlePragmaCaptured() 650 { 651 assert(Tok.is(tok::annot_pragma_captured)); 652 ConsumeAnnotationToken(); 653 654 if (Tok.isNot(tok::l_brace)) { 655 PP.Diag(Tok, diag::err_expected) << tok::l_brace; 656 return StmtError(); 657 } 658 659 SourceLocation Loc = Tok.getLocation(); 660 661 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope | 662 Scope::CompoundStmtScope); 663 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default, 664 /*NumParams=*/1); 665 666 StmtResult R = ParseCompoundStatement(); 667 CapturedRegionScope.Exit(); 668 669 if (R.isInvalid()) { 670 Actions.ActOnCapturedRegionError(); 671 return StmtError(); 672 } 673 674 return Actions.ActOnCapturedRegionEnd(R.get()); 675 } 676 677 namespace { 678 enum OpenCLExtState : char { 679 Disable, Enable, Begin, End 680 }; 681 typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData; 682 } 683 684 void Parser::HandlePragmaOpenCLExtension() { 685 assert(Tok.is(tok::annot_pragma_opencl_extension)); 686 OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue()); 687 auto State = Data->second; 688 auto Ident = Data->first; 689 SourceLocation NameLoc = Tok.getLocation(); 690 ConsumeAnnotationToken(); 691 692 auto &Opt = Actions.getOpenCLOptions(); 693 auto Name = Ident->getName(); 694 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions, 695 // overriding all previously issued extension directives, but only if the 696 // behavior is set to disable." 697 if (Name == "all") { 698 if (State == Disable) { 699 Opt.disableAll(); 700 Opt.enableSupportedCore(getLangOpts()); 701 } else { 702 PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1; 703 } 704 } else if (State == Begin) { 705 if (!Opt.isKnown(Name) || !Opt.isSupported(Name, getLangOpts())) { 706 Opt.support(Name); 707 } 708 Actions.setCurrentOpenCLExtension(Name); 709 } else if (State == End) { 710 if (Name != Actions.getCurrentOpenCLExtension()) 711 PP.Diag(NameLoc, diag::warn_pragma_begin_end_mismatch); 712 Actions.setCurrentOpenCLExtension(""); 713 } else if (!Opt.isKnown(Name)) 714 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident; 715 else if (Opt.isSupportedExtension(Name, getLangOpts())) 716 Opt.enable(Name, State == Enable); 717 else if (Opt.isSupportedCore(Name, getLangOpts())) 718 PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident; 719 else 720 PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident; 721 } 722 723 void Parser::HandlePragmaMSPointersToMembers() { 724 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members)); 725 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod = 726 static_cast<LangOptions::PragmaMSPointersToMembersKind>( 727 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); 728 SourceLocation PragmaLoc = ConsumeAnnotationToken(); 729 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc); 730 } 731 732 void Parser::HandlePragmaMSVtorDisp() { 733 assert(Tok.is(tok::annot_pragma_ms_vtordisp)); 734 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()); 735 Sema::PragmaMsStackAction Action = 736 static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF); 737 MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF); 738 SourceLocation PragmaLoc = ConsumeAnnotationToken(); 739 Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode); 740 } 741 742 void Parser::HandlePragmaMSPragma() { 743 assert(Tok.is(tok::annot_pragma_ms_pragma)); 744 // Grab the tokens out of the annotation and enter them into the stream. 745 auto TheTokens = 746 (std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue(); 747 PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true, 748 /*IsReinject=*/true); 749 SourceLocation PragmaLocation = ConsumeAnnotationToken(); 750 assert(Tok.isAnyIdentifier()); 751 StringRef PragmaName = Tok.getIdentifierInfo()->getName(); 752 PP.Lex(Tok); // pragma kind 753 754 // Figure out which #pragma we're dealing with. The switch has no default 755 // because lex shouldn't emit the annotation token for unrecognized pragmas. 756 typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation); 757 PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName) 758 .Case("data_seg", &Parser::HandlePragmaMSSegment) 759 .Case("bss_seg", &Parser::HandlePragmaMSSegment) 760 .Case("const_seg", &Parser::HandlePragmaMSSegment) 761 .Case("code_seg", &Parser::HandlePragmaMSSegment) 762 .Case("section", &Parser::HandlePragmaMSSection) 763 .Case("init_seg", &Parser::HandlePragmaMSInitSeg); 764 765 if (!(this->*Handler)(PragmaName, PragmaLocation)) { 766 // Pragma handling failed, and has been diagnosed. Slurp up the tokens 767 // until eof (really end of line) to prevent follow-on errors. 768 while (Tok.isNot(tok::eof)) 769 PP.Lex(Tok); 770 PP.Lex(Tok); 771 } 772 } 773 774 bool Parser::HandlePragmaMSSection(StringRef PragmaName, 775 SourceLocation PragmaLocation) { 776 if (Tok.isNot(tok::l_paren)) { 777 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName; 778 return false; 779 } 780 PP.Lex(Tok); // ( 781 // Parsing code for pragma section 782 if (Tok.isNot(tok::string_literal)) { 783 PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name) 784 << PragmaName; 785 return false; 786 } 787 ExprResult StringResult = ParseStringLiteralExpression(); 788 if (StringResult.isInvalid()) 789 return false; // Already diagnosed. 790 StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get()); 791 if (SegmentName->getCharByteWidth() != 1) { 792 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string) 793 << PragmaName; 794 return false; 795 } 796 int SectionFlags = ASTContext::PSF_Read; 797 bool SectionFlagsAreDefault = true; 798 while (Tok.is(tok::comma)) { 799 PP.Lex(Tok); // , 800 // Ignore "long" and "short". 801 // They are undocumented, but widely used, section attributes which appear 802 // to do nothing. 803 if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) { 804 PP.Lex(Tok); // long/short 805 continue; 806 } 807 808 if (!Tok.isAnyIdentifier()) { 809 PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren) 810 << PragmaName; 811 return false; 812 } 813 ASTContext::PragmaSectionFlag Flag = 814 llvm::StringSwitch<ASTContext::PragmaSectionFlag>( 815 Tok.getIdentifierInfo()->getName()) 816 .Case("read", ASTContext::PSF_Read) 817 .Case("write", ASTContext::PSF_Write) 818 .Case("execute", ASTContext::PSF_Execute) 819 .Case("shared", ASTContext::PSF_Invalid) 820 .Case("nopage", ASTContext::PSF_Invalid) 821 .Case("nocache", ASTContext::PSF_Invalid) 822 .Case("discard", ASTContext::PSF_Invalid) 823 .Case("remove", ASTContext::PSF_Invalid) 824 .Default(ASTContext::PSF_None); 825 if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) { 826 PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None 827 ? diag::warn_pragma_invalid_specific_action 828 : diag::warn_pragma_unsupported_action) 829 << PragmaName << Tok.getIdentifierInfo()->getName(); 830 return false; 831 } 832 SectionFlags |= Flag; 833 SectionFlagsAreDefault = false; 834 PP.Lex(Tok); // Identifier 835 } 836 // If no section attributes are specified, the section will be marked as 837 // read/write. 838 if (SectionFlagsAreDefault) 839 SectionFlags |= ASTContext::PSF_Write; 840 if (Tok.isNot(tok::r_paren)) { 841 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName; 842 return false; 843 } 844 PP.Lex(Tok); // ) 845 if (Tok.isNot(tok::eof)) { 846 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol) 847 << PragmaName; 848 return false; 849 } 850 PP.Lex(Tok); // eof 851 Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName); 852 return true; 853 } 854 855 bool Parser::HandlePragmaMSSegment(StringRef PragmaName, 856 SourceLocation PragmaLocation) { 857 if (Tok.isNot(tok::l_paren)) { 858 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName; 859 return false; 860 } 861 PP.Lex(Tok); // ( 862 Sema::PragmaMsStackAction Action = Sema::PSK_Reset; 863 StringRef SlotLabel; 864 if (Tok.isAnyIdentifier()) { 865 StringRef PushPop = Tok.getIdentifierInfo()->getName(); 866 if (PushPop == "push") 867 Action = Sema::PSK_Push; 868 else if (PushPop == "pop") 869 Action = Sema::PSK_Pop; 870 else { 871 PP.Diag(PragmaLocation, 872 diag::warn_pragma_expected_section_push_pop_or_name) 873 << PragmaName; 874 return false; 875 } 876 if (Action != Sema::PSK_Reset) { 877 PP.Lex(Tok); // push | pop 878 if (Tok.is(tok::comma)) { 879 PP.Lex(Tok); // , 880 // If we've got a comma, we either need a label or a string. 881 if (Tok.isAnyIdentifier()) { 882 SlotLabel = Tok.getIdentifierInfo()->getName(); 883 PP.Lex(Tok); // identifier 884 if (Tok.is(tok::comma)) 885 PP.Lex(Tok); 886 else if (Tok.isNot(tok::r_paren)) { 887 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) 888 << PragmaName; 889 return false; 890 } 891 } 892 } else if (Tok.isNot(tok::r_paren)) { 893 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName; 894 return false; 895 } 896 } 897 } 898 // Grab the string literal for our section name. 899 StringLiteral *SegmentName = nullptr; 900 if (Tok.isNot(tok::r_paren)) { 901 if (Tok.isNot(tok::string_literal)) { 902 unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ? 903 diag::warn_pragma_expected_section_name : 904 diag::warn_pragma_expected_section_label_or_name : 905 diag::warn_pragma_expected_section_push_pop_or_name; 906 PP.Diag(PragmaLocation, DiagID) << PragmaName; 907 return false; 908 } 909 ExprResult StringResult = ParseStringLiteralExpression(); 910 if (StringResult.isInvalid()) 911 return false; // Already diagnosed. 912 SegmentName = cast<StringLiteral>(StringResult.get()); 913 if (SegmentName->getCharByteWidth() != 1) { 914 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string) 915 << PragmaName; 916 return false; 917 } 918 // Setting section "" has no effect 919 if (SegmentName->getLength()) 920 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set); 921 } 922 if (Tok.isNot(tok::r_paren)) { 923 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName; 924 return false; 925 } 926 PP.Lex(Tok); // ) 927 if (Tok.isNot(tok::eof)) { 928 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol) 929 << PragmaName; 930 return false; 931 } 932 PP.Lex(Tok); // eof 933 Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel, 934 SegmentName, PragmaName); 935 return true; 936 } 937 938 // #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} ) 939 bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName, 940 SourceLocation PragmaLocation) { 941 if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) { 942 PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target); 943 return false; 944 } 945 946 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen, 947 PragmaName)) 948 return false; 949 950 // Parse either the known section names or the string section name. 951 StringLiteral *SegmentName = nullptr; 952 if (Tok.isAnyIdentifier()) { 953 auto *II = Tok.getIdentifierInfo(); 954 StringRef Section = llvm::StringSwitch<StringRef>(II->getName()) 955 .Case("compiler", "\".CRT$XCC\"") 956 .Case("lib", "\".CRT$XCL\"") 957 .Case("user", "\".CRT$XCU\"") 958 .Default(""); 959 960 if (!Section.empty()) { 961 // Pretend the user wrote the appropriate string literal here. 962 Token Toks[1]; 963 Toks[0].startToken(); 964 Toks[0].setKind(tok::string_literal); 965 Toks[0].setLocation(Tok.getLocation()); 966 Toks[0].setLiteralData(Section.data()); 967 Toks[0].setLength(Section.size()); 968 SegmentName = 969 cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get()); 970 PP.Lex(Tok); 971 } 972 } else if (Tok.is(tok::string_literal)) { 973 ExprResult StringResult = ParseStringLiteralExpression(); 974 if (StringResult.isInvalid()) 975 return false; 976 SegmentName = cast<StringLiteral>(StringResult.get()); 977 if (SegmentName->getCharByteWidth() != 1) { 978 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string) 979 << PragmaName; 980 return false; 981 } 982 // FIXME: Add support for the '[, func-name]' part of the pragma. 983 } 984 985 if (!SegmentName) { 986 PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName; 987 return false; 988 } 989 990 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen, 991 PragmaName) || 992 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol, 993 PragmaName)) 994 return false; 995 996 Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName); 997 return true; 998 } 999 1000 namespace { 1001 struct PragmaLoopHintInfo { 1002 Token PragmaName; 1003 Token Option; 1004 ArrayRef<Token> Toks; 1005 }; 1006 } // end anonymous namespace 1007 1008 static std::string PragmaLoopHintString(Token PragmaName, Token Option) { 1009 StringRef Str = PragmaName.getIdentifierInfo()->getName(); 1010 std::string ClangLoopStr = (llvm::Twine("clang loop ") + Str).str(); 1011 return llvm::StringSwitch<StringRef>(Str) 1012 .Case("loop", ClangLoopStr) 1013 .Case("unroll_and_jam", Str) 1014 .Case("unroll", Str) 1015 .Default(""); 1016 } 1017 1018 bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { 1019 assert(Tok.is(tok::annot_pragma_loop_hint)); 1020 PragmaLoopHintInfo *Info = 1021 static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue()); 1022 1023 IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo(); 1024 Hint.PragmaNameLoc = IdentifierLoc::create( 1025 Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo); 1026 1027 // It is possible that the loop hint has no option identifier, such as 1028 // #pragma unroll(4). 1029 IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier) 1030 ? Info->Option.getIdentifierInfo() 1031 : nullptr; 1032 Hint.OptionLoc = IdentifierLoc::create( 1033 Actions.Context, Info->Option.getLocation(), OptionInfo); 1034 1035 llvm::ArrayRef<Token> Toks = Info->Toks; 1036 1037 // Return a valid hint if pragma unroll or nounroll were specified 1038 // without an argument. 1039 auto IsLoopHint = llvm::StringSwitch<bool>(PragmaNameInfo->getName()) 1040 .Cases("unroll", "nounroll", "unroll_and_jam", 1041 "nounroll_and_jam", true) 1042 .Default(false); 1043 1044 if (Toks.empty() && IsLoopHint) { 1045 ConsumeAnnotationToken(); 1046 Hint.Range = Info->PragmaName.getLocation(); 1047 return true; 1048 } 1049 1050 // The constant expression is always followed by an eof token, which increases 1051 // the TokSize by 1. 1052 assert(!Toks.empty() && 1053 "PragmaLoopHintInfo::Toks must contain at least one token."); 1054 1055 // If no option is specified the argument is assumed to be a constant expr. 1056 bool OptionUnroll = false; 1057 bool OptionUnrollAndJam = false; 1058 bool OptionDistribute = false; 1059 bool OptionPipelineDisabled = false; 1060 bool StateOption = false; 1061 if (OptionInfo) { // Pragma Unroll does not specify an option. 1062 OptionUnroll = OptionInfo->isStr("unroll"); 1063 OptionUnrollAndJam = OptionInfo->isStr("unroll_and_jam"); 1064 OptionDistribute = OptionInfo->isStr("distribute"); 1065 OptionPipelineDisabled = OptionInfo->isStr("pipeline"); 1066 StateOption = llvm::StringSwitch<bool>(OptionInfo->getName()) 1067 .Case("vectorize", true) 1068 .Case("interleave", true) 1069 .Case("vectorize_predicate", true) 1070 .Default(false) || 1071 OptionUnroll || OptionUnrollAndJam || OptionDistribute || 1072 OptionPipelineDisabled; 1073 } 1074 1075 bool AssumeSafetyArg = !OptionUnroll && !OptionUnrollAndJam && 1076 !OptionDistribute && !OptionPipelineDisabled; 1077 // Verify loop hint has an argument. 1078 if (Toks[0].is(tok::eof)) { 1079 ConsumeAnnotationToken(); 1080 Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument) 1081 << /*StateArgument=*/StateOption 1082 << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam) 1083 << /*AssumeSafetyKeyword=*/AssumeSafetyArg; 1084 return false; 1085 } 1086 1087 // Validate the argument. 1088 if (StateOption) { 1089 ConsumeAnnotationToken(); 1090 SourceLocation StateLoc = Toks[0].getLocation(); 1091 IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo(); 1092 1093 bool Valid = StateInfo && 1094 llvm::StringSwitch<bool>(StateInfo->getName()) 1095 .Case("disable", true) 1096 .Case("enable", !OptionPipelineDisabled) 1097 .Case("full", OptionUnroll || OptionUnrollAndJam) 1098 .Case("assume_safety", AssumeSafetyArg) 1099 .Default(false); 1100 if (!Valid) { 1101 if (OptionPipelineDisabled) { 1102 Diag(Toks[0].getLocation(), diag::err_pragma_pipeline_invalid_keyword); 1103 } else { 1104 Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword) 1105 << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam) 1106 << /*AssumeSafetyKeyword=*/AssumeSafetyArg; 1107 } 1108 return false; 1109 } 1110 if (Toks.size() > 2) 1111 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 1112 << PragmaLoopHintString(Info->PragmaName, Info->Option); 1113 Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo); 1114 } else { 1115 // Enter constant expression including eof terminator into token stream. 1116 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false, 1117 /*IsReinject=*/false); 1118 ConsumeAnnotationToken(); 1119 1120 ExprResult R = ParseConstantExpression(); 1121 1122 // Tokens following an error in an ill-formed constant expression will 1123 // remain in the token stream and must be removed. 1124 if (Tok.isNot(tok::eof)) { 1125 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 1126 << PragmaLoopHintString(Info->PragmaName, Info->Option); 1127 while (Tok.isNot(tok::eof)) 1128 ConsumeAnyToken(); 1129 } 1130 1131 ConsumeToken(); // Consume the constant expression eof terminator. 1132 1133 if (R.isInvalid() || 1134 Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation())) 1135 return false; 1136 1137 // Argument is a constant expression with an integer type. 1138 Hint.ValueExpr = R.get(); 1139 } 1140 1141 Hint.Range = SourceRange(Info->PragmaName.getLocation(), 1142 Info->Toks.back().getLocation()); 1143 return true; 1144 } 1145 1146 namespace { 1147 struct PragmaAttributeInfo { 1148 enum ActionType { Push, Pop, Attribute }; 1149 ParsedAttributes &Attributes; 1150 ActionType Action; 1151 const IdentifierInfo *Namespace = nullptr; 1152 ArrayRef<Token> Tokens; 1153 1154 PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {} 1155 }; 1156 1157 #include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc" 1158 1159 } // end anonymous namespace 1160 1161 static StringRef getIdentifier(const Token &Tok) { 1162 if (Tok.is(tok::identifier)) 1163 return Tok.getIdentifierInfo()->getName(); 1164 const char *S = tok::getKeywordSpelling(Tok.getKind()); 1165 if (!S) 1166 return ""; 1167 return S; 1168 } 1169 1170 static bool isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule) { 1171 using namespace attr; 1172 switch (Rule) { 1173 #define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) \ 1174 case Value: \ 1175 return IsAbstract; 1176 #include "clang/Basic/AttrSubMatchRulesList.inc" 1177 } 1178 llvm_unreachable("Invalid attribute subject match rule"); 1179 return false; 1180 } 1181 1182 static void diagnoseExpectedAttributeSubjectSubRule( 1183 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName, 1184 SourceLocation SubRuleLoc) { 1185 auto Diagnostic = 1186 PRef.Diag(SubRuleLoc, 1187 diag::err_pragma_attribute_expected_subject_sub_identifier) 1188 << PrimaryRuleName; 1189 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule)) 1190 Diagnostic << /*SubRulesSupported=*/1 << SubRules; 1191 else 1192 Diagnostic << /*SubRulesSupported=*/0; 1193 } 1194 1195 static void diagnoseUnknownAttributeSubjectSubRule( 1196 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName, 1197 StringRef SubRuleName, SourceLocation SubRuleLoc) { 1198 1199 auto Diagnostic = 1200 PRef.Diag(SubRuleLoc, diag::err_pragma_attribute_unknown_subject_sub_rule) 1201 << SubRuleName << PrimaryRuleName; 1202 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule)) 1203 Diagnostic << /*SubRulesSupported=*/1 << SubRules; 1204 else 1205 Diagnostic << /*SubRulesSupported=*/0; 1206 } 1207 1208 bool Parser::ParsePragmaAttributeSubjectMatchRuleSet( 1209 attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, SourceLocation &AnyLoc, 1210 SourceLocation &LastMatchRuleEndLoc) { 1211 bool IsAny = false; 1212 BalancedDelimiterTracker AnyParens(*this, tok::l_paren); 1213 if (getIdentifier(Tok) == "any") { 1214 AnyLoc = ConsumeToken(); 1215 IsAny = true; 1216 if (AnyParens.expectAndConsume()) 1217 return true; 1218 } 1219 1220 do { 1221 // Parse the subject matcher rule. 1222 StringRef Name = getIdentifier(Tok); 1223 if (Name.empty()) { 1224 Diag(Tok, diag::err_pragma_attribute_expected_subject_identifier); 1225 return true; 1226 } 1227 std::pair<Optional<attr::SubjectMatchRule>, 1228 Optional<attr::SubjectMatchRule> (*)(StringRef, bool)> 1229 Rule = isAttributeSubjectMatchRule(Name); 1230 if (!Rule.first) { 1231 Diag(Tok, diag::err_pragma_attribute_unknown_subject_rule) << Name; 1232 return true; 1233 } 1234 attr::SubjectMatchRule PrimaryRule = *Rule.first; 1235 SourceLocation RuleLoc = ConsumeToken(); 1236 1237 BalancedDelimiterTracker Parens(*this, tok::l_paren); 1238 if (isAbstractAttrMatcherRule(PrimaryRule)) { 1239 if (Parens.expectAndConsume()) 1240 return true; 1241 } else if (Parens.consumeOpen()) { 1242 if (!SubjectMatchRules 1243 .insert( 1244 std::make_pair(PrimaryRule, SourceRange(RuleLoc, RuleLoc))) 1245 .second) 1246 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject) 1247 << Name 1248 << FixItHint::CreateRemoval(SourceRange( 1249 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleLoc)); 1250 LastMatchRuleEndLoc = RuleLoc; 1251 continue; 1252 } 1253 1254 // Parse the sub-rules. 1255 StringRef SubRuleName = getIdentifier(Tok); 1256 if (SubRuleName.empty()) { 1257 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name, 1258 Tok.getLocation()); 1259 return true; 1260 } 1261 attr::SubjectMatchRule SubRule; 1262 if (SubRuleName == "unless") { 1263 SourceLocation SubRuleLoc = ConsumeToken(); 1264 BalancedDelimiterTracker Parens(*this, tok::l_paren); 1265 if (Parens.expectAndConsume()) 1266 return true; 1267 SubRuleName = getIdentifier(Tok); 1268 if (SubRuleName.empty()) { 1269 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name, 1270 SubRuleLoc); 1271 return true; 1272 } 1273 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/true); 1274 if (!SubRuleOrNone) { 1275 std::string SubRuleUnlessName = "unless(" + SubRuleName.str() + ")"; 1276 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name, 1277 SubRuleUnlessName, SubRuleLoc); 1278 return true; 1279 } 1280 SubRule = *SubRuleOrNone; 1281 ConsumeToken(); 1282 if (Parens.consumeClose()) 1283 return true; 1284 } else { 1285 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/false); 1286 if (!SubRuleOrNone) { 1287 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name, 1288 SubRuleName, Tok.getLocation()); 1289 return true; 1290 } 1291 SubRule = *SubRuleOrNone; 1292 ConsumeToken(); 1293 } 1294 SourceLocation RuleEndLoc = Tok.getLocation(); 1295 LastMatchRuleEndLoc = RuleEndLoc; 1296 if (Parens.consumeClose()) 1297 return true; 1298 if (!SubjectMatchRules 1299 .insert(std::make_pair(SubRule, SourceRange(RuleLoc, RuleEndLoc))) 1300 .second) { 1301 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject) 1302 << attr::getSubjectMatchRuleSpelling(SubRule) 1303 << FixItHint::CreateRemoval(SourceRange( 1304 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleEndLoc)); 1305 continue; 1306 } 1307 } while (IsAny && TryConsumeToken(tok::comma)); 1308 1309 if (IsAny) 1310 if (AnyParens.consumeClose()) 1311 return true; 1312 1313 return false; 1314 } 1315 1316 namespace { 1317 1318 /// Describes the stage at which attribute subject rule parsing was interrupted. 1319 enum class MissingAttributeSubjectRulesRecoveryPoint { 1320 Comma, 1321 ApplyTo, 1322 Equals, 1323 Any, 1324 None, 1325 }; 1326 1327 MissingAttributeSubjectRulesRecoveryPoint 1328 getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) { 1329 if (const auto *II = Tok.getIdentifierInfo()) { 1330 if (II->isStr("apply_to")) 1331 return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo; 1332 if (II->isStr("any")) 1333 return MissingAttributeSubjectRulesRecoveryPoint::Any; 1334 } 1335 if (Tok.is(tok::equal)) 1336 return MissingAttributeSubjectRulesRecoveryPoint::Equals; 1337 return MissingAttributeSubjectRulesRecoveryPoint::None; 1338 } 1339 1340 /// Creates a diagnostic for the attribute subject rule parsing diagnostic that 1341 /// suggests the possible attribute subject rules in a fix-it together with 1342 /// any other missing tokens. 1343 DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic( 1344 unsigned DiagID, ParsedAttr &Attribute, 1345 MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) { 1346 SourceLocation Loc = PRef.getEndOfPreviousToken(); 1347 if (Loc.isInvalid()) 1348 Loc = PRef.getCurToken().getLocation(); 1349 auto Diagnostic = PRef.Diag(Loc, DiagID); 1350 std::string FixIt; 1351 MissingAttributeSubjectRulesRecoveryPoint EndPoint = 1352 getAttributeSubjectRulesRecoveryPointForToken(PRef.getCurToken()); 1353 if (Point == MissingAttributeSubjectRulesRecoveryPoint::Comma) 1354 FixIt = ", "; 1355 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo && 1356 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::ApplyTo) 1357 FixIt += "apply_to"; 1358 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::Equals && 1359 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::Equals) 1360 FixIt += " = "; 1361 SourceRange FixItRange(Loc); 1362 if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) { 1363 // Gather the subject match rules that are supported by the attribute. 1364 SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> SubjectMatchRuleSet; 1365 Attribute.getMatchRules(PRef.getLangOpts(), SubjectMatchRuleSet); 1366 if (SubjectMatchRuleSet.empty()) { 1367 // FIXME: We can emit a "fix-it" with a subject list placeholder when 1368 // placeholders will be supported by the fix-its. 1369 return Diagnostic; 1370 } 1371 FixIt += "any("; 1372 bool NeedsComma = false; 1373 for (const auto &I : SubjectMatchRuleSet) { 1374 // Ensure that the missing rule is reported in the fix-it only when it's 1375 // supported in the current language mode. 1376 if (!I.second) 1377 continue; 1378 if (NeedsComma) 1379 FixIt += ", "; 1380 else 1381 NeedsComma = true; 1382 FixIt += attr::getSubjectMatchRuleSpelling(I.first); 1383 } 1384 FixIt += ")"; 1385 // Check if we need to remove the range 1386 PRef.SkipUntil(tok::eof, Parser::StopBeforeMatch); 1387 FixItRange.setEnd(PRef.getCurToken().getLocation()); 1388 } 1389 if (FixItRange.getBegin() == FixItRange.getEnd()) 1390 Diagnostic << FixItHint::CreateInsertion(FixItRange.getBegin(), FixIt); 1391 else 1392 Diagnostic << FixItHint::CreateReplacement( 1393 CharSourceRange::getCharRange(FixItRange), FixIt); 1394 return Diagnostic; 1395 } 1396 1397 } // end anonymous namespace 1398 1399 void Parser::HandlePragmaAttribute() { 1400 assert(Tok.is(tok::annot_pragma_attribute) && 1401 "Expected #pragma attribute annotation token"); 1402 SourceLocation PragmaLoc = Tok.getLocation(); 1403 auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue()); 1404 if (Info->Action == PragmaAttributeInfo::Pop) { 1405 ConsumeAnnotationToken(); 1406 Actions.ActOnPragmaAttributePop(PragmaLoc, Info->Namespace); 1407 return; 1408 } 1409 // Parse the actual attribute with its arguments. 1410 assert((Info->Action == PragmaAttributeInfo::Push || 1411 Info->Action == PragmaAttributeInfo::Attribute) && 1412 "Unexpected #pragma attribute command"); 1413 1414 if (Info->Action == PragmaAttributeInfo::Push && Info->Tokens.empty()) { 1415 ConsumeAnnotationToken(); 1416 Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace); 1417 return; 1418 } 1419 1420 PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false, 1421 /*IsReinject=*/false); 1422 ConsumeAnnotationToken(); 1423 1424 ParsedAttributes &Attrs = Info->Attributes; 1425 Attrs.clearListOnly(); 1426 1427 auto SkipToEnd = [this]() { 1428 SkipUntil(tok::eof, StopBeforeMatch); 1429 ConsumeToken(); 1430 }; 1431 1432 if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) { 1433 // Parse the CXX11 style attribute. 1434 ParseCXX11AttributeSpecifier(Attrs); 1435 } else if (Tok.is(tok::kw___attribute)) { 1436 ConsumeToken(); 1437 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, 1438 "attribute")) 1439 return SkipToEnd(); 1440 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "(")) 1441 return SkipToEnd(); 1442 1443 if (Tok.isNot(tok::identifier)) { 1444 Diag(Tok, diag::err_pragma_attribute_expected_attribute_name); 1445 SkipToEnd(); 1446 return; 1447 } 1448 IdentifierInfo *AttrName = Tok.getIdentifierInfo(); 1449 SourceLocation AttrNameLoc = ConsumeToken(); 1450 1451 if (Tok.isNot(tok::l_paren)) 1452 Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, 1453 ParsedAttr::AS_GNU); 1454 else 1455 ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr, 1456 /*ScopeName=*/nullptr, 1457 /*ScopeLoc=*/SourceLocation(), ParsedAttr::AS_GNU, 1458 /*Declarator=*/nullptr); 1459 1460 if (ExpectAndConsume(tok::r_paren)) 1461 return SkipToEnd(); 1462 if (ExpectAndConsume(tok::r_paren)) 1463 return SkipToEnd(); 1464 } else if (Tok.is(tok::kw___declspec)) { 1465 ParseMicrosoftDeclSpecs(Attrs); 1466 } else { 1467 Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax); 1468 if (Tok.getIdentifierInfo()) { 1469 // If we suspect that this is an attribute suggest the use of 1470 // '__attribute__'. 1471 if (ParsedAttr::getParsedKind( 1472 Tok.getIdentifierInfo(), /*ScopeName=*/nullptr, 1473 ParsedAttr::AS_GNU) != ParsedAttr::UnknownAttribute) { 1474 SourceLocation InsertStartLoc = Tok.getLocation(); 1475 ConsumeToken(); 1476 if (Tok.is(tok::l_paren)) { 1477 ConsumeAnyToken(); 1478 SkipUntil(tok::r_paren, StopBeforeMatch); 1479 if (Tok.isNot(tok::r_paren)) 1480 return SkipToEnd(); 1481 } 1482 Diag(Tok, diag::note_pragma_attribute_use_attribute_kw) 1483 << FixItHint::CreateInsertion(InsertStartLoc, "__attribute__((") 1484 << FixItHint::CreateInsertion(Tok.getEndLoc(), "))"); 1485 } 1486 } 1487 SkipToEnd(); 1488 return; 1489 } 1490 1491 if (Attrs.empty() || Attrs.begin()->isInvalid()) { 1492 SkipToEnd(); 1493 return; 1494 } 1495 1496 // Ensure that we don't have more than one attribute. 1497 if (Attrs.size() > 1) { 1498 SourceLocation Loc = Attrs[1].getLoc(); 1499 Diag(Loc, diag::err_pragma_attribute_multiple_attributes); 1500 SkipToEnd(); 1501 return; 1502 } 1503 1504 ParsedAttr &Attribute = *Attrs.begin(); 1505 if (!Attribute.isSupportedByPragmaAttribute()) { 1506 Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute) 1507 << Attribute; 1508 SkipToEnd(); 1509 return; 1510 } 1511 1512 // Parse the subject-list. 1513 if (!TryConsumeToken(tok::comma)) { 1514 createExpectedAttributeSubjectRulesTokenDiagnostic( 1515 diag::err_expected, Attribute, 1516 MissingAttributeSubjectRulesRecoveryPoint::Comma, *this) 1517 << tok::comma; 1518 SkipToEnd(); 1519 return; 1520 } 1521 1522 if (Tok.isNot(tok::identifier)) { 1523 createExpectedAttributeSubjectRulesTokenDiagnostic( 1524 diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute, 1525 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this); 1526 SkipToEnd(); 1527 return; 1528 } 1529 const IdentifierInfo *II = Tok.getIdentifierInfo(); 1530 if (!II->isStr("apply_to")) { 1531 createExpectedAttributeSubjectRulesTokenDiagnostic( 1532 diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute, 1533 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this); 1534 SkipToEnd(); 1535 return; 1536 } 1537 ConsumeToken(); 1538 1539 if (!TryConsumeToken(tok::equal)) { 1540 createExpectedAttributeSubjectRulesTokenDiagnostic( 1541 diag::err_expected, Attribute, 1542 MissingAttributeSubjectRulesRecoveryPoint::Equals, *this) 1543 << tok::equal; 1544 SkipToEnd(); 1545 return; 1546 } 1547 1548 attr::ParsedSubjectMatchRuleSet SubjectMatchRules; 1549 SourceLocation AnyLoc, LastMatchRuleEndLoc; 1550 if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules, AnyLoc, 1551 LastMatchRuleEndLoc)) { 1552 SkipToEnd(); 1553 return; 1554 } 1555 1556 // Tokens following an ill-formed attribute will remain in the token stream 1557 // and must be removed. 1558 if (Tok.isNot(tok::eof)) { 1559 Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute); 1560 SkipToEnd(); 1561 return; 1562 } 1563 1564 // Consume the eof terminator token. 1565 ConsumeToken(); 1566 1567 // Handle a mixed push/attribute by desurging to a push, then an attribute. 1568 if (Info->Action == PragmaAttributeInfo::Push) 1569 Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace); 1570 1571 Actions.ActOnPragmaAttributeAttribute(Attribute, PragmaLoc, 1572 std::move(SubjectMatchRules)); 1573 } 1574 1575 // #pragma GCC visibility comes in two variants: 1576 // 'push' '(' [visibility] ')' 1577 // 'pop' 1578 void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP, 1579 PragmaIntroducer Introducer, 1580 Token &VisTok) { 1581 SourceLocation VisLoc = VisTok.getLocation(); 1582 1583 Token Tok; 1584 PP.LexUnexpandedToken(Tok); 1585 1586 const IdentifierInfo *PushPop = Tok.getIdentifierInfo(); 1587 1588 const IdentifierInfo *VisType; 1589 if (PushPop && PushPop->isStr("pop")) { 1590 VisType = nullptr; 1591 } else if (PushPop && PushPop->isStr("push")) { 1592 PP.LexUnexpandedToken(Tok); 1593 if (Tok.isNot(tok::l_paren)) { 1594 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) 1595 << "visibility"; 1596 return; 1597 } 1598 PP.LexUnexpandedToken(Tok); 1599 VisType = Tok.getIdentifierInfo(); 1600 if (!VisType) { 1601 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 1602 << "visibility"; 1603 return; 1604 } 1605 PP.LexUnexpandedToken(Tok); 1606 if (Tok.isNot(tok::r_paren)) { 1607 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) 1608 << "visibility"; 1609 return; 1610 } 1611 } else { 1612 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 1613 << "visibility"; 1614 return; 1615 } 1616 SourceLocation EndLoc = Tok.getLocation(); 1617 PP.LexUnexpandedToken(Tok); 1618 if (Tok.isNot(tok::eod)) { 1619 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 1620 << "visibility"; 1621 return; 1622 } 1623 1624 auto Toks = std::make_unique<Token[]>(1); 1625 Toks[0].startToken(); 1626 Toks[0].setKind(tok::annot_pragma_vis); 1627 Toks[0].setLocation(VisLoc); 1628 Toks[0].setAnnotationEndLoc(EndLoc); 1629 Toks[0].setAnnotationValue( 1630 const_cast<void *>(static_cast<const void *>(VisType))); 1631 PP.EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion=*/true, 1632 /*IsReinject=*/false); 1633 } 1634 1635 // #pragma pack(...) comes in the following delicious flavors: 1636 // pack '(' [integer] ')' 1637 // pack '(' 'show' ')' 1638 // pack '(' ('push' | 'pop') [',' identifier] [, integer] ')' 1639 void PragmaPackHandler::HandlePragma(Preprocessor &PP, 1640 PragmaIntroducer Introducer, 1641 Token &PackTok) { 1642 SourceLocation PackLoc = PackTok.getLocation(); 1643 1644 Token Tok; 1645 PP.Lex(Tok); 1646 if (Tok.isNot(tok::l_paren)) { 1647 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack"; 1648 return; 1649 } 1650 1651 Sema::PragmaMsStackAction Action = Sema::PSK_Reset; 1652 StringRef SlotLabel; 1653 Token Alignment; 1654 Alignment.startToken(); 1655 PP.Lex(Tok); 1656 if (Tok.is(tok::numeric_constant)) { 1657 Alignment = Tok; 1658 1659 PP.Lex(Tok); 1660 1661 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting 1662 // the push/pop stack. 1663 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4) 1664 Action = 1665 PP.getLangOpts().ApplePragmaPack ? Sema::PSK_Push_Set : Sema::PSK_Set; 1666 } else if (Tok.is(tok::identifier)) { 1667 const IdentifierInfo *II = Tok.getIdentifierInfo(); 1668 if (II->isStr("show")) { 1669 Action = Sema::PSK_Show; 1670 PP.Lex(Tok); 1671 } else { 1672 if (II->isStr("push")) { 1673 Action = Sema::PSK_Push; 1674 } else if (II->isStr("pop")) { 1675 Action = Sema::PSK_Pop; 1676 } else { 1677 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack"; 1678 return; 1679 } 1680 PP.Lex(Tok); 1681 1682 if (Tok.is(tok::comma)) { 1683 PP.Lex(Tok); 1684 1685 if (Tok.is(tok::numeric_constant)) { 1686 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set); 1687 Alignment = Tok; 1688 1689 PP.Lex(Tok); 1690 } else if (Tok.is(tok::identifier)) { 1691 SlotLabel = Tok.getIdentifierInfo()->getName(); 1692 PP.Lex(Tok); 1693 1694 if (Tok.is(tok::comma)) { 1695 PP.Lex(Tok); 1696 1697 if (Tok.isNot(tok::numeric_constant)) { 1698 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed); 1699 return; 1700 } 1701 1702 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set); 1703 Alignment = Tok; 1704 1705 PP.Lex(Tok); 1706 } 1707 } else { 1708 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed); 1709 return; 1710 } 1711 } 1712 } 1713 } else if (PP.getLangOpts().ApplePragmaPack) { 1714 // In MSVC/gcc, #pragma pack() resets the alignment without affecting 1715 // the push/pop stack. 1716 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop). 1717 Action = Sema::PSK_Pop; 1718 } 1719 1720 if (Tok.isNot(tok::r_paren)) { 1721 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack"; 1722 return; 1723 } 1724 1725 SourceLocation RParenLoc = Tok.getLocation(); 1726 PP.Lex(Tok); 1727 if (Tok.isNot(tok::eod)) { 1728 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack"; 1729 return; 1730 } 1731 1732 PragmaPackInfo *Info = 1733 PP.getPreprocessorAllocator().Allocate<PragmaPackInfo>(1); 1734 Info->Action = Action; 1735 Info->SlotLabel = SlotLabel; 1736 Info->Alignment = Alignment; 1737 1738 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1), 1739 1); 1740 Toks[0].startToken(); 1741 Toks[0].setKind(tok::annot_pragma_pack); 1742 Toks[0].setLocation(PackLoc); 1743 Toks[0].setAnnotationEndLoc(RParenLoc); 1744 Toks[0].setAnnotationValue(static_cast<void*>(Info)); 1745 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 1746 /*IsReinject=*/false); 1747 } 1748 1749 // #pragma ms_struct on 1750 // #pragma ms_struct off 1751 void PragmaMSStructHandler::HandlePragma(Preprocessor &PP, 1752 PragmaIntroducer Introducer, 1753 Token &MSStructTok) { 1754 PragmaMSStructKind Kind = PMSST_OFF; 1755 1756 Token Tok; 1757 PP.Lex(Tok); 1758 if (Tok.isNot(tok::identifier)) { 1759 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct); 1760 return; 1761 } 1762 SourceLocation EndLoc = Tok.getLocation(); 1763 const IdentifierInfo *II = Tok.getIdentifierInfo(); 1764 if (II->isStr("on")) { 1765 Kind = PMSST_ON; 1766 PP.Lex(Tok); 1767 } 1768 else if (II->isStr("off") || II->isStr("reset")) 1769 PP.Lex(Tok); 1770 else { 1771 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct); 1772 return; 1773 } 1774 1775 if (Tok.isNot(tok::eod)) { 1776 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 1777 << "ms_struct"; 1778 return; 1779 } 1780 1781 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1), 1782 1); 1783 Toks[0].startToken(); 1784 Toks[0].setKind(tok::annot_pragma_msstruct); 1785 Toks[0].setLocation(MSStructTok.getLocation()); 1786 Toks[0].setAnnotationEndLoc(EndLoc); 1787 Toks[0].setAnnotationValue(reinterpret_cast<void*>( 1788 static_cast<uintptr_t>(Kind))); 1789 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 1790 /*IsReinject=*/false); 1791 } 1792 1793 // #pragma clang section bss="abc" data="" rodata="def" text="" relro="" 1794 void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP, 1795 PragmaIntroducer Introducer, 1796 Token &FirstToken) { 1797 1798 Token Tok; 1799 auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid; 1800 1801 PP.Lex(Tok); // eat 'section' 1802 while (Tok.isNot(tok::eod)) { 1803 if (Tok.isNot(tok::identifier)) { 1804 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section"; 1805 return; 1806 } 1807 1808 const IdentifierInfo *SecType = Tok.getIdentifierInfo(); 1809 if (SecType->isStr("bss")) 1810 SecKind = Sema::PragmaClangSectionKind::PCSK_BSS; 1811 else if (SecType->isStr("data")) 1812 SecKind = Sema::PragmaClangSectionKind::PCSK_Data; 1813 else if (SecType->isStr("rodata")) 1814 SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata; 1815 else if (SecType->isStr("relro")) 1816 SecKind = Sema::PragmaClangSectionKind::PCSK_Relro; 1817 else if (SecType->isStr("text")) 1818 SecKind = Sema::PragmaClangSectionKind::PCSK_Text; 1819 else { 1820 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section"; 1821 return; 1822 } 1823 1824 PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text'] 1825 if (Tok.isNot(tok::equal)) { 1826 PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind; 1827 return; 1828 } 1829 1830 std::string SecName; 1831 if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false)) 1832 return; 1833 1834 Actions.ActOnPragmaClangSection(Tok.getLocation(), 1835 (SecName.size()? Sema::PragmaClangSectionAction::PCSA_Set : 1836 Sema::PragmaClangSectionAction::PCSA_Clear), 1837 SecKind, SecName); 1838 } 1839 } 1840 1841 // #pragma 'align' '=' {'native','natural','mac68k','power','reset'} 1842 // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'} 1843 static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok, 1844 bool IsOptions) { 1845 Token Tok; 1846 1847 if (IsOptions) { 1848 PP.Lex(Tok); 1849 if (Tok.isNot(tok::identifier) || 1850 !Tok.getIdentifierInfo()->isStr("align")) { 1851 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align); 1852 return; 1853 } 1854 } 1855 1856 PP.Lex(Tok); 1857 if (Tok.isNot(tok::equal)) { 1858 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal) 1859 << IsOptions; 1860 return; 1861 } 1862 1863 PP.Lex(Tok); 1864 if (Tok.isNot(tok::identifier)) { 1865 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 1866 << (IsOptions ? "options" : "align"); 1867 return; 1868 } 1869 1870 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural; 1871 const IdentifierInfo *II = Tok.getIdentifierInfo(); 1872 if (II->isStr("native")) 1873 Kind = Sema::POAK_Native; 1874 else if (II->isStr("natural")) 1875 Kind = Sema::POAK_Natural; 1876 else if (II->isStr("packed")) 1877 Kind = Sema::POAK_Packed; 1878 else if (II->isStr("power")) 1879 Kind = Sema::POAK_Power; 1880 else if (II->isStr("mac68k")) 1881 Kind = Sema::POAK_Mac68k; 1882 else if (II->isStr("reset")) 1883 Kind = Sema::POAK_Reset; 1884 else { 1885 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option) 1886 << IsOptions; 1887 return; 1888 } 1889 1890 SourceLocation EndLoc = Tok.getLocation(); 1891 PP.Lex(Tok); 1892 if (Tok.isNot(tok::eod)) { 1893 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 1894 << (IsOptions ? "options" : "align"); 1895 return; 1896 } 1897 1898 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1), 1899 1); 1900 Toks[0].startToken(); 1901 Toks[0].setKind(tok::annot_pragma_align); 1902 Toks[0].setLocation(FirstTok.getLocation()); 1903 Toks[0].setAnnotationEndLoc(EndLoc); 1904 Toks[0].setAnnotationValue(reinterpret_cast<void*>( 1905 static_cast<uintptr_t>(Kind))); 1906 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 1907 /*IsReinject=*/false); 1908 } 1909 1910 void PragmaAlignHandler::HandlePragma(Preprocessor &PP, 1911 PragmaIntroducer Introducer, 1912 Token &AlignTok) { 1913 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false); 1914 } 1915 1916 void PragmaOptionsHandler::HandlePragma(Preprocessor &PP, 1917 PragmaIntroducer Introducer, 1918 Token &OptionsTok) { 1919 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true); 1920 } 1921 1922 // #pragma unused(identifier) 1923 void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, 1924 PragmaIntroducer Introducer, 1925 Token &UnusedTok) { 1926 // FIXME: Should we be expanding macros here? My guess is no. 1927 SourceLocation UnusedLoc = UnusedTok.getLocation(); 1928 1929 // Lex the left '('. 1930 Token Tok; 1931 PP.Lex(Tok); 1932 if (Tok.isNot(tok::l_paren)) { 1933 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused"; 1934 return; 1935 } 1936 1937 // Lex the declaration reference(s). 1938 SmallVector<Token, 5> Identifiers; 1939 SourceLocation RParenLoc; 1940 bool LexID = true; 1941 1942 while (true) { 1943 PP.Lex(Tok); 1944 1945 if (LexID) { 1946 if (Tok.is(tok::identifier)) { 1947 Identifiers.push_back(Tok); 1948 LexID = false; 1949 continue; 1950 } 1951 1952 // Illegal token! 1953 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var); 1954 return; 1955 } 1956 1957 // We are execting a ')' or a ','. 1958 if (Tok.is(tok::comma)) { 1959 LexID = true; 1960 continue; 1961 } 1962 1963 if (Tok.is(tok::r_paren)) { 1964 RParenLoc = Tok.getLocation(); 1965 break; 1966 } 1967 1968 // Illegal token! 1969 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused"; 1970 return; 1971 } 1972 1973 PP.Lex(Tok); 1974 if (Tok.isNot(tok::eod)) { 1975 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << 1976 "unused"; 1977 return; 1978 } 1979 1980 // Verify that we have a location for the right parenthesis. 1981 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'"); 1982 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments"); 1983 1984 // For each identifier token, insert into the token stream a 1985 // annot_pragma_unused token followed by the identifier token. 1986 // This allows us to cache a "#pragma unused" that occurs inside an inline 1987 // C++ member function. 1988 1989 MutableArrayRef<Token> Toks( 1990 PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()), 1991 2 * Identifiers.size()); 1992 for (unsigned i=0; i != Identifiers.size(); i++) { 1993 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1]; 1994 pragmaUnusedTok.startToken(); 1995 pragmaUnusedTok.setKind(tok::annot_pragma_unused); 1996 pragmaUnusedTok.setLocation(UnusedLoc); 1997 idTok = Identifiers[i]; 1998 } 1999 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 2000 /*IsReinject=*/false); 2001 } 2002 2003 // #pragma weak identifier 2004 // #pragma weak identifier '=' identifier 2005 void PragmaWeakHandler::HandlePragma(Preprocessor &PP, 2006 PragmaIntroducer Introducer, 2007 Token &WeakTok) { 2008 SourceLocation WeakLoc = WeakTok.getLocation(); 2009 2010 Token Tok; 2011 PP.Lex(Tok); 2012 if (Tok.isNot(tok::identifier)) { 2013 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak"; 2014 return; 2015 } 2016 2017 Token WeakName = Tok; 2018 bool HasAlias = false; 2019 Token AliasName; 2020 2021 PP.Lex(Tok); 2022 if (Tok.is(tok::equal)) { 2023 HasAlias = true; 2024 PP.Lex(Tok); 2025 if (Tok.isNot(tok::identifier)) { 2026 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 2027 << "weak"; 2028 return; 2029 } 2030 AliasName = Tok; 2031 PP.Lex(Tok); 2032 } 2033 2034 if (Tok.isNot(tok::eod)) { 2035 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak"; 2036 return; 2037 } 2038 2039 if (HasAlias) { 2040 MutableArrayRef<Token> Toks( 2041 PP.getPreprocessorAllocator().Allocate<Token>(3), 3); 2042 Token &pragmaUnusedTok = Toks[0]; 2043 pragmaUnusedTok.startToken(); 2044 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias); 2045 pragmaUnusedTok.setLocation(WeakLoc); 2046 pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation()); 2047 Toks[1] = WeakName; 2048 Toks[2] = AliasName; 2049 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 2050 /*IsReinject=*/false); 2051 } else { 2052 MutableArrayRef<Token> Toks( 2053 PP.getPreprocessorAllocator().Allocate<Token>(2), 2); 2054 Token &pragmaUnusedTok = Toks[0]; 2055 pragmaUnusedTok.startToken(); 2056 pragmaUnusedTok.setKind(tok::annot_pragma_weak); 2057 pragmaUnusedTok.setLocation(WeakLoc); 2058 pragmaUnusedTok.setAnnotationEndLoc(WeakLoc); 2059 Toks[1] = WeakName; 2060 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 2061 /*IsReinject=*/false); 2062 } 2063 } 2064 2065 // #pragma redefine_extname identifier identifier 2066 void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP, 2067 PragmaIntroducer Introducer, 2068 Token &RedefToken) { 2069 SourceLocation RedefLoc = RedefToken.getLocation(); 2070 2071 Token Tok; 2072 PP.Lex(Tok); 2073 if (Tok.isNot(tok::identifier)) { 2074 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << 2075 "redefine_extname"; 2076 return; 2077 } 2078 2079 Token RedefName = Tok; 2080 PP.Lex(Tok); 2081 2082 if (Tok.isNot(tok::identifier)) { 2083 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 2084 << "redefine_extname"; 2085 return; 2086 } 2087 2088 Token AliasName = Tok; 2089 PP.Lex(Tok); 2090 2091 if (Tok.isNot(tok::eod)) { 2092 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << 2093 "redefine_extname"; 2094 return; 2095 } 2096 2097 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3), 2098 3); 2099 Token &pragmaRedefTok = Toks[0]; 2100 pragmaRedefTok.startToken(); 2101 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname); 2102 pragmaRedefTok.setLocation(RedefLoc); 2103 pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation()); 2104 Toks[1] = RedefName; 2105 Toks[2] = AliasName; 2106 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 2107 /*IsReinject=*/false); 2108 } 2109 2110 void PragmaFPContractHandler::HandlePragma(Preprocessor &PP, 2111 PragmaIntroducer Introducer, 2112 Token &Tok) { 2113 tok::OnOffSwitch OOS; 2114 if (PP.LexOnOffSwitch(OOS)) 2115 return; 2116 2117 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1), 2118 1); 2119 Toks[0].startToken(); 2120 Toks[0].setKind(tok::annot_pragma_fp_contract); 2121 Toks[0].setLocation(Tok.getLocation()); 2122 Toks[0].setAnnotationEndLoc(Tok.getLocation()); 2123 Toks[0].setAnnotationValue(reinterpret_cast<void*>( 2124 static_cast<uintptr_t>(OOS))); 2125 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 2126 /*IsReinject=*/false); 2127 } 2128 2129 void PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP, 2130 PragmaIntroducer Introducer, 2131 Token &Tok) { 2132 PP.LexUnexpandedToken(Tok); 2133 if (Tok.isNot(tok::identifier)) { 2134 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << 2135 "OPENCL"; 2136 return; 2137 } 2138 IdentifierInfo *Ext = Tok.getIdentifierInfo(); 2139 SourceLocation NameLoc = Tok.getLocation(); 2140 2141 PP.Lex(Tok); 2142 if (Tok.isNot(tok::colon)) { 2143 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext; 2144 return; 2145 } 2146 2147 PP.Lex(Tok); 2148 if (Tok.isNot(tok::identifier)) { 2149 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0; 2150 return; 2151 } 2152 IdentifierInfo *Pred = Tok.getIdentifierInfo(); 2153 2154 OpenCLExtState State; 2155 if (Pred->isStr("enable")) { 2156 State = Enable; 2157 } else if (Pred->isStr("disable")) { 2158 State = Disable; 2159 } else if (Pred->isStr("begin")) 2160 State = Begin; 2161 else if (Pred->isStr("end")) 2162 State = End; 2163 else { 2164 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) 2165 << Ext->isStr("all"); 2166 return; 2167 } 2168 SourceLocation StateLoc = Tok.getLocation(); 2169 2170 PP.Lex(Tok); 2171 if (Tok.isNot(tok::eod)) { 2172 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << 2173 "OPENCL EXTENSION"; 2174 return; 2175 } 2176 2177 auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1); 2178 Info->first = Ext; 2179 Info->second = State; 2180 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1), 2181 1); 2182 Toks[0].startToken(); 2183 Toks[0].setKind(tok::annot_pragma_opencl_extension); 2184 Toks[0].setLocation(NameLoc); 2185 Toks[0].setAnnotationValue(static_cast<void*>(Info)); 2186 Toks[0].setAnnotationEndLoc(StateLoc); 2187 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 2188 /*IsReinject=*/false); 2189 2190 if (PP.getPPCallbacks()) 2191 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext, 2192 StateLoc, State); 2193 } 2194 2195 /// Handle '#pragma omp ...' when OpenMP is disabled. 2196 /// 2197 void PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP, 2198 PragmaIntroducer Introducer, 2199 Token &FirstTok) { 2200 if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored, 2201 FirstTok.getLocation())) { 2202 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored); 2203 PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored, 2204 diag::Severity::Ignored, SourceLocation()); 2205 } 2206 PP.DiscardUntilEndOfDirective(); 2207 } 2208 2209 /// Handle '#pragma omp ...' when OpenMP is enabled. 2210 /// 2211 void PragmaOpenMPHandler::HandlePragma(Preprocessor &PP, 2212 PragmaIntroducer Introducer, 2213 Token &FirstTok) { 2214 SmallVector<Token, 16> Pragma; 2215 Token Tok; 2216 Tok.startToken(); 2217 Tok.setKind(tok::annot_pragma_openmp); 2218 Tok.setLocation(Introducer.Loc); 2219 2220 while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof)) { 2221 Pragma.push_back(Tok); 2222 PP.Lex(Tok); 2223 if (Tok.is(tok::annot_pragma_openmp)) { 2224 PP.Diag(Tok, diag::err_omp_unexpected_directive) << 0; 2225 unsigned InnerPragmaCnt = 1; 2226 while (InnerPragmaCnt != 0) { 2227 PP.Lex(Tok); 2228 if (Tok.is(tok::annot_pragma_openmp)) 2229 ++InnerPragmaCnt; 2230 else if (Tok.is(tok::annot_pragma_openmp_end)) 2231 --InnerPragmaCnt; 2232 } 2233 PP.Lex(Tok); 2234 } 2235 } 2236 SourceLocation EodLoc = Tok.getLocation(); 2237 Tok.startToken(); 2238 Tok.setKind(tok::annot_pragma_openmp_end); 2239 Tok.setLocation(EodLoc); 2240 Pragma.push_back(Tok); 2241 2242 auto Toks = std::make_unique<Token[]>(Pragma.size()); 2243 std::copy(Pragma.begin(), Pragma.end(), Toks.get()); 2244 PP.EnterTokenStream(std::move(Toks), Pragma.size(), 2245 /*DisableMacroExpansion=*/false, /*IsReinject=*/false); 2246 } 2247 2248 /// Handle '#pragma pointers_to_members' 2249 // The grammar for this pragma is as follows: 2250 // 2251 // <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance' 2252 // 2253 // #pragma pointers_to_members '(' 'best_case' ')' 2254 // #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')' 2255 // #pragma pointers_to_members '(' inheritance-model ')' 2256 void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP, 2257 PragmaIntroducer Introducer, 2258 Token &Tok) { 2259 SourceLocation PointersToMembersLoc = Tok.getLocation(); 2260 PP.Lex(Tok); 2261 if (Tok.isNot(tok::l_paren)) { 2262 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen) 2263 << "pointers_to_members"; 2264 return; 2265 } 2266 PP.Lex(Tok); 2267 const IdentifierInfo *Arg = Tok.getIdentifierInfo(); 2268 if (!Arg) { 2269 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 2270 << "pointers_to_members"; 2271 return; 2272 } 2273 PP.Lex(Tok); 2274 2275 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod; 2276 if (Arg->isStr("best_case")) { 2277 RepresentationMethod = LangOptions::PPTMK_BestCase; 2278 } else { 2279 if (Arg->isStr("full_generality")) { 2280 if (Tok.is(tok::comma)) { 2281 PP.Lex(Tok); 2282 2283 Arg = Tok.getIdentifierInfo(); 2284 if (!Arg) { 2285 PP.Diag(Tok.getLocation(), 2286 diag::err_pragma_pointers_to_members_unknown_kind) 2287 << Tok.getKind() << /*OnlyInheritanceModels*/ 0; 2288 return; 2289 } 2290 PP.Lex(Tok); 2291 } else if (Tok.is(tok::r_paren)) { 2292 // #pragma pointers_to_members(full_generality) implicitly specifies 2293 // virtual_inheritance. 2294 Arg = nullptr; 2295 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance; 2296 } else { 2297 PP.Diag(Tok.getLocation(), diag::err_expected_punc) 2298 << "full_generality"; 2299 return; 2300 } 2301 } 2302 2303 if (Arg) { 2304 if (Arg->isStr("single_inheritance")) { 2305 RepresentationMethod = 2306 LangOptions::PPTMK_FullGeneralitySingleInheritance; 2307 } else if (Arg->isStr("multiple_inheritance")) { 2308 RepresentationMethod = 2309 LangOptions::PPTMK_FullGeneralityMultipleInheritance; 2310 } else if (Arg->isStr("virtual_inheritance")) { 2311 RepresentationMethod = 2312 LangOptions::PPTMK_FullGeneralityVirtualInheritance; 2313 } else { 2314 PP.Diag(Tok.getLocation(), 2315 diag::err_pragma_pointers_to_members_unknown_kind) 2316 << Arg << /*HasPointerDeclaration*/ 1; 2317 return; 2318 } 2319 } 2320 } 2321 2322 if (Tok.isNot(tok::r_paren)) { 2323 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after) 2324 << (Arg ? Arg->getName() : "full_generality"); 2325 return; 2326 } 2327 2328 SourceLocation EndLoc = Tok.getLocation(); 2329 PP.Lex(Tok); 2330 if (Tok.isNot(tok::eod)) { 2331 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 2332 << "pointers_to_members"; 2333 return; 2334 } 2335 2336 Token AnnotTok; 2337 AnnotTok.startToken(); 2338 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members); 2339 AnnotTok.setLocation(PointersToMembersLoc); 2340 AnnotTok.setAnnotationEndLoc(EndLoc); 2341 AnnotTok.setAnnotationValue( 2342 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod))); 2343 PP.EnterToken(AnnotTok, /*IsReinject=*/true); 2344 } 2345 2346 /// Handle '#pragma vtordisp' 2347 // The grammar for this pragma is as follows: 2348 // 2349 // <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' ) 2350 // 2351 // #pragma vtordisp '(' ['push' ','] vtordisp-mode ')' 2352 // #pragma vtordisp '(' 'pop' ')' 2353 // #pragma vtordisp '(' ')' 2354 void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP, 2355 PragmaIntroducer Introducer, Token &Tok) { 2356 SourceLocation VtorDispLoc = Tok.getLocation(); 2357 PP.Lex(Tok); 2358 if (Tok.isNot(tok::l_paren)) { 2359 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp"; 2360 return; 2361 } 2362 PP.Lex(Tok); 2363 2364 Sema::PragmaMsStackAction Action = Sema::PSK_Set; 2365 const IdentifierInfo *II = Tok.getIdentifierInfo(); 2366 if (II) { 2367 if (II->isStr("push")) { 2368 // #pragma vtordisp(push, mode) 2369 PP.Lex(Tok); 2370 if (Tok.isNot(tok::comma)) { 2371 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp"; 2372 return; 2373 } 2374 PP.Lex(Tok); 2375 Action = Sema::PSK_Push_Set; 2376 // not push, could be on/off 2377 } else if (II->isStr("pop")) { 2378 // #pragma vtordisp(pop) 2379 PP.Lex(Tok); 2380 Action = Sema::PSK_Pop; 2381 } 2382 // not push or pop, could be on/off 2383 } else { 2384 if (Tok.is(tok::r_paren)) { 2385 // #pragma vtordisp() 2386 Action = Sema::PSK_Reset; 2387 } 2388 } 2389 2390 2391 uint64_t Value = 0; 2392 if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) { 2393 const IdentifierInfo *II = Tok.getIdentifierInfo(); 2394 if (II && II->isStr("off")) { 2395 PP.Lex(Tok); 2396 Value = 0; 2397 } else if (II && II->isStr("on")) { 2398 PP.Lex(Tok); 2399 Value = 1; 2400 } else if (Tok.is(tok::numeric_constant) && 2401 PP.parseSimpleIntegerLiteral(Tok, Value)) { 2402 if (Value > 2) { 2403 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer) 2404 << 0 << 2 << "vtordisp"; 2405 return; 2406 } 2407 } else { 2408 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) 2409 << "vtordisp"; 2410 return; 2411 } 2412 } 2413 2414 // Finish the pragma: ')' $ 2415 if (Tok.isNot(tok::r_paren)) { 2416 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp"; 2417 return; 2418 } 2419 SourceLocation EndLoc = Tok.getLocation(); 2420 PP.Lex(Tok); 2421 if (Tok.isNot(tok::eod)) { 2422 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 2423 << "vtordisp"; 2424 return; 2425 } 2426 2427 // Enter the annotation. 2428 Token AnnotTok; 2429 AnnotTok.startToken(); 2430 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp); 2431 AnnotTok.setLocation(VtorDispLoc); 2432 AnnotTok.setAnnotationEndLoc(EndLoc); 2433 AnnotTok.setAnnotationValue(reinterpret_cast<void *>( 2434 static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF)))); 2435 PP.EnterToken(AnnotTok, /*IsReinject=*/false); 2436 } 2437 2438 /// Handle all MS pragmas. Simply forwards the tokens after inserting 2439 /// an annotation token. 2440 void PragmaMSPragma::HandlePragma(Preprocessor &PP, 2441 PragmaIntroducer Introducer, Token &Tok) { 2442 Token EoF, AnnotTok; 2443 EoF.startToken(); 2444 EoF.setKind(tok::eof); 2445 AnnotTok.startToken(); 2446 AnnotTok.setKind(tok::annot_pragma_ms_pragma); 2447 AnnotTok.setLocation(Tok.getLocation()); 2448 AnnotTok.setAnnotationEndLoc(Tok.getLocation()); 2449 SmallVector<Token, 8> TokenVector; 2450 // Suck up all of the tokens before the eod. 2451 for (; Tok.isNot(tok::eod); PP.Lex(Tok)) { 2452 TokenVector.push_back(Tok); 2453 AnnotTok.setAnnotationEndLoc(Tok.getLocation()); 2454 } 2455 // Add a sentinel EoF token to the end of the list. 2456 TokenVector.push_back(EoF); 2457 // We must allocate this array with new because EnterTokenStream is going to 2458 // delete it later. 2459 auto TokenArray = std::make_unique<Token[]>(TokenVector.size()); 2460 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get()); 2461 auto Value = new (PP.getPreprocessorAllocator()) 2462 std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray), 2463 TokenVector.size()); 2464 AnnotTok.setAnnotationValue(Value); 2465 PP.EnterToken(AnnotTok, /*IsReinject*/ false); 2466 } 2467 2468 /// Handle the Microsoft \#pragma detect_mismatch extension. 2469 /// 2470 /// The syntax is: 2471 /// \code 2472 /// #pragma detect_mismatch("name", "value") 2473 /// \endcode 2474 /// Where 'name' and 'value' are quoted strings. The values are embedded in 2475 /// the object file and passed along to the linker. If the linker detects a 2476 /// mismatch in the object file's values for the given name, a LNK2038 error 2477 /// is emitted. See MSDN for more details. 2478 void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP, 2479 PragmaIntroducer Introducer, 2480 Token &Tok) { 2481 SourceLocation DetectMismatchLoc = Tok.getLocation(); 2482 PP.Lex(Tok); 2483 if (Tok.isNot(tok::l_paren)) { 2484 PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren; 2485 return; 2486 } 2487 2488 // Read the name to embed, which must be a string literal. 2489 std::string NameString; 2490 if (!PP.LexStringLiteral(Tok, NameString, 2491 "pragma detect_mismatch", 2492 /*AllowMacroExpansion=*/true)) 2493 return; 2494 2495 // Read the comma followed by a second string literal. 2496 std::string ValueString; 2497 if (Tok.isNot(tok::comma)) { 2498 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed); 2499 return; 2500 } 2501 2502 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch", 2503 /*AllowMacroExpansion=*/true)) 2504 return; 2505 2506 if (Tok.isNot(tok::r_paren)) { 2507 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren; 2508 return; 2509 } 2510 PP.Lex(Tok); // Eat the r_paren. 2511 2512 if (Tok.isNot(tok::eod)) { 2513 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed); 2514 return; 2515 } 2516 2517 // If the pragma is lexically sound, notify any interested PPCallbacks. 2518 if (PP.getPPCallbacks()) 2519 PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString, 2520 ValueString); 2521 2522 Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString); 2523 } 2524 2525 /// Handle the microsoft \#pragma comment extension. 2526 /// 2527 /// The syntax is: 2528 /// \code 2529 /// #pragma comment(linker, "foo") 2530 /// \endcode 2531 /// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user. 2532 /// "foo" is a string, which is fully macro expanded, and permits string 2533 /// concatenation, embedded escape characters etc. See MSDN for more details. 2534 void PragmaCommentHandler::HandlePragma(Preprocessor &PP, 2535 PragmaIntroducer Introducer, 2536 Token &Tok) { 2537 SourceLocation CommentLoc = Tok.getLocation(); 2538 PP.Lex(Tok); 2539 if (Tok.isNot(tok::l_paren)) { 2540 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed); 2541 return; 2542 } 2543 2544 // Read the identifier. 2545 PP.Lex(Tok); 2546 if (Tok.isNot(tok::identifier)) { 2547 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed); 2548 return; 2549 } 2550 2551 // Verify that this is one of the 5 whitelisted options. 2552 IdentifierInfo *II = Tok.getIdentifierInfo(); 2553 PragmaMSCommentKind Kind = 2554 llvm::StringSwitch<PragmaMSCommentKind>(II->getName()) 2555 .Case("linker", PCK_Linker) 2556 .Case("lib", PCK_Lib) 2557 .Case("compiler", PCK_Compiler) 2558 .Case("exestr", PCK_ExeStr) 2559 .Case("user", PCK_User) 2560 .Default(PCK_Unknown); 2561 if (Kind == PCK_Unknown) { 2562 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind); 2563 return; 2564 } 2565 2566 if (PP.getTargetInfo().getTriple().isOSBinFormatELF() && Kind != PCK_Lib) { 2567 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored) 2568 << II->getName(); 2569 return; 2570 } 2571 2572 // On PS4, issue a warning about any pragma comments other than 2573 // #pragma comment lib. 2574 if (PP.getTargetInfo().getTriple().isPS4() && Kind != PCK_Lib) { 2575 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored) 2576 << II->getName(); 2577 return; 2578 } 2579 2580 // Read the optional string if present. 2581 PP.Lex(Tok); 2582 std::string ArgumentString; 2583 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString, 2584 "pragma comment", 2585 /*AllowMacroExpansion=*/true)) 2586 return; 2587 2588 // FIXME: warn that 'exestr' is deprecated. 2589 // FIXME: If the kind is "compiler" warn if the string is present (it is 2590 // ignored). 2591 // The MSDN docs say that "lib" and "linker" require a string and have a short 2592 // whitelist of linker options they support, but in practice MSVC doesn't 2593 // issue a diagnostic. Therefore neither does clang. 2594 2595 if (Tok.isNot(tok::r_paren)) { 2596 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed); 2597 return; 2598 } 2599 PP.Lex(Tok); // eat the r_paren. 2600 2601 if (Tok.isNot(tok::eod)) { 2602 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed); 2603 return; 2604 } 2605 2606 // If the pragma is lexically sound, notify any interested PPCallbacks. 2607 if (PP.getPPCallbacks()) 2608 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString); 2609 2610 Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString); 2611 } 2612 2613 // #pragma clang optimize off 2614 // #pragma clang optimize on 2615 void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP, 2616 PragmaIntroducer Introducer, 2617 Token &FirstToken) { 2618 Token Tok; 2619 PP.Lex(Tok); 2620 if (Tok.is(tok::eod)) { 2621 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument) 2622 << "clang optimize" << /*Expected=*/true << "'on' or 'off'"; 2623 return; 2624 } 2625 if (Tok.isNot(tok::identifier)) { 2626 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument) 2627 << PP.getSpelling(Tok); 2628 return; 2629 } 2630 const IdentifierInfo *II = Tok.getIdentifierInfo(); 2631 // The only accepted values are 'on' or 'off'. 2632 bool IsOn = false; 2633 if (II->isStr("on")) { 2634 IsOn = true; 2635 } else if (!II->isStr("off")) { 2636 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument) 2637 << PP.getSpelling(Tok); 2638 return; 2639 } 2640 PP.Lex(Tok); 2641 2642 if (Tok.isNot(tok::eod)) { 2643 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument) 2644 << PP.getSpelling(Tok); 2645 return; 2646 } 2647 2648 Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation()); 2649 } 2650 2651 namespace { 2652 /// Used as the annotation value for tok::annot_pragma_fp. 2653 struct TokFPAnnotValue { 2654 enum FlagKinds { Contract }; 2655 enum FlagValues { On, Off, Fast }; 2656 2657 FlagKinds FlagKind; 2658 FlagValues FlagValue; 2659 }; 2660 } // end anonymous namespace 2661 2662 void PragmaFPHandler::HandlePragma(Preprocessor &PP, 2663 PragmaIntroducer Introducer, Token &Tok) { 2664 // fp 2665 Token PragmaName = Tok; 2666 SmallVector<Token, 1> TokenList; 2667 2668 PP.Lex(Tok); 2669 if (Tok.isNot(tok::identifier)) { 2670 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option) 2671 << /*MissingOption=*/true << ""; 2672 return; 2673 } 2674 2675 while (Tok.is(tok::identifier)) { 2676 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo(); 2677 2678 auto FlagKind = 2679 llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagKinds>>( 2680 OptionInfo->getName()) 2681 .Case("contract", TokFPAnnotValue::Contract) 2682 .Default(None); 2683 if (!FlagKind) { 2684 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option) 2685 << /*MissingOption=*/false << OptionInfo; 2686 return; 2687 } 2688 PP.Lex(Tok); 2689 2690 // Read '(' 2691 if (Tok.isNot(tok::l_paren)) { 2692 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren; 2693 return; 2694 } 2695 PP.Lex(Tok); 2696 2697 if (Tok.isNot(tok::identifier)) { 2698 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument) 2699 << PP.getSpelling(Tok) << OptionInfo->getName(); 2700 return; 2701 } 2702 const IdentifierInfo *II = Tok.getIdentifierInfo(); 2703 2704 auto FlagValue = 2705 llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagValues>>( 2706 II->getName()) 2707 .Case("on", TokFPAnnotValue::On) 2708 .Case("off", TokFPAnnotValue::Off) 2709 .Case("fast", TokFPAnnotValue::Fast) 2710 .Default(llvm::None); 2711 2712 if (!FlagValue) { 2713 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument) 2714 << PP.getSpelling(Tok) << OptionInfo->getName(); 2715 return; 2716 } 2717 PP.Lex(Tok); 2718 2719 // Read ')' 2720 if (Tok.isNot(tok::r_paren)) { 2721 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren; 2722 return; 2723 } 2724 PP.Lex(Tok); 2725 2726 auto *AnnotValue = new (PP.getPreprocessorAllocator()) 2727 TokFPAnnotValue{*FlagKind, *FlagValue}; 2728 // Generate the loop hint token. 2729 Token FPTok; 2730 FPTok.startToken(); 2731 FPTok.setKind(tok::annot_pragma_fp); 2732 FPTok.setLocation(PragmaName.getLocation()); 2733 FPTok.setAnnotationEndLoc(PragmaName.getLocation()); 2734 FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue)); 2735 TokenList.push_back(FPTok); 2736 } 2737 2738 if (Tok.isNot(tok::eod)) { 2739 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 2740 << "clang fp"; 2741 return; 2742 } 2743 2744 auto TokenArray = std::make_unique<Token[]>(TokenList.size()); 2745 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get()); 2746 2747 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(), 2748 /*DisableMacroExpansion=*/false, /*IsReinject=*/false); 2749 } 2750 2751 void Parser::HandlePragmaFP() { 2752 assert(Tok.is(tok::annot_pragma_fp)); 2753 auto *AnnotValue = 2754 reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue()); 2755 2756 LangOptions::FPContractModeKind FPC; 2757 switch (AnnotValue->FlagValue) { 2758 case TokFPAnnotValue::On: 2759 FPC = LangOptions::FPC_On; 2760 break; 2761 case TokFPAnnotValue::Fast: 2762 FPC = LangOptions::FPC_Fast; 2763 break; 2764 case TokFPAnnotValue::Off: 2765 FPC = LangOptions::FPC_Off; 2766 break; 2767 } 2768 2769 Actions.ActOnPragmaFPContract(FPC); 2770 ConsumeAnnotationToken(); 2771 } 2772 2773 /// Parses loop or unroll pragma hint value and fills in Info. 2774 static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName, 2775 Token Option, bool ValueInParens, 2776 PragmaLoopHintInfo &Info) { 2777 SmallVector<Token, 1> ValueList; 2778 int OpenParens = ValueInParens ? 1 : 0; 2779 // Read constant expression. 2780 while (Tok.isNot(tok::eod)) { 2781 if (Tok.is(tok::l_paren)) 2782 OpenParens++; 2783 else if (Tok.is(tok::r_paren)) { 2784 OpenParens--; 2785 if (OpenParens == 0 && ValueInParens) 2786 break; 2787 } 2788 2789 ValueList.push_back(Tok); 2790 PP.Lex(Tok); 2791 } 2792 2793 if (ValueInParens) { 2794 // Read ')' 2795 if (Tok.isNot(tok::r_paren)) { 2796 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren; 2797 return true; 2798 } 2799 PP.Lex(Tok); 2800 } 2801 2802 Token EOFTok; 2803 EOFTok.startToken(); 2804 EOFTok.setKind(tok::eof); 2805 EOFTok.setLocation(Tok.getLocation()); 2806 ValueList.push_back(EOFTok); // Terminates expression for parsing. 2807 2808 Info.Toks = llvm::makeArrayRef(ValueList).copy(PP.getPreprocessorAllocator()); 2809 2810 Info.PragmaName = PragmaName; 2811 Info.Option = Option; 2812 return false; 2813 } 2814 2815 /// Handle the \#pragma clang loop directive. 2816 /// #pragma clang 'loop' loop-hints 2817 /// 2818 /// loop-hints: 2819 /// loop-hint loop-hints[opt] 2820 /// 2821 /// loop-hint: 2822 /// 'vectorize' '(' loop-hint-keyword ')' 2823 /// 'interleave' '(' loop-hint-keyword ')' 2824 /// 'unroll' '(' unroll-hint-keyword ')' 2825 /// 'vectorize_predicate' '(' loop-hint-keyword ')' 2826 /// 'vectorize_width' '(' loop-hint-value ')' 2827 /// 'interleave_count' '(' loop-hint-value ')' 2828 /// 'unroll_count' '(' loop-hint-value ')' 2829 /// 'pipeline' '(' disable ')' 2830 /// 'pipeline_initiation_interval' '(' loop-hint-value ')' 2831 /// 2832 /// loop-hint-keyword: 2833 /// 'enable' 2834 /// 'disable' 2835 /// 'assume_safety' 2836 /// 2837 /// unroll-hint-keyword: 2838 /// 'enable' 2839 /// 'disable' 2840 /// 'full' 2841 /// 2842 /// loop-hint-value: 2843 /// constant-expression 2844 /// 2845 /// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to 2846 /// try vectorizing the instructions of the loop it precedes. Specifying 2847 /// interleave(enable) or interleave_count(_value_) instructs llvm to try 2848 /// interleaving multiple iterations of the loop it precedes. The width of the 2849 /// vector instructions is specified by vectorize_width() and the number of 2850 /// interleaved loop iterations is specified by interleave_count(). Specifying a 2851 /// value of 1 effectively disables vectorization/interleaving, even if it is 2852 /// possible and profitable, and 0 is invalid. The loop vectorizer currently 2853 /// only works on inner loops. 2854 /// 2855 /// The unroll and unroll_count directives control the concatenation 2856 /// unroller. Specifying unroll(enable) instructs llvm to unroll the loop 2857 /// completely if the trip count is known at compile time and unroll partially 2858 /// if the trip count is not known. Specifying unroll(full) is similar to 2859 /// unroll(enable) but will unroll the loop only if the trip count is known at 2860 /// compile time. Specifying unroll(disable) disables unrolling for the 2861 /// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the 2862 /// loop the number of times indicated by the value. 2863 void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP, 2864 PragmaIntroducer Introducer, 2865 Token &Tok) { 2866 // Incoming token is "loop" from "#pragma clang loop". 2867 Token PragmaName = Tok; 2868 SmallVector<Token, 1> TokenList; 2869 2870 // Lex the optimization option and verify it is an identifier. 2871 PP.Lex(Tok); 2872 if (Tok.isNot(tok::identifier)) { 2873 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option) 2874 << /*MissingOption=*/true << ""; 2875 return; 2876 } 2877 2878 while (Tok.is(tok::identifier)) { 2879 Token Option = Tok; 2880 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo(); 2881 2882 bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName()) 2883 .Case("vectorize", true) 2884 .Case("interleave", true) 2885 .Case("unroll", true) 2886 .Case("distribute", true) 2887 .Case("vectorize_predicate", true) 2888 .Case("vectorize_width", true) 2889 .Case("interleave_count", true) 2890 .Case("unroll_count", true) 2891 .Case("pipeline", true) 2892 .Case("pipeline_initiation_interval", true) 2893 .Default(false); 2894 if (!OptionValid) { 2895 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option) 2896 << /*MissingOption=*/false << OptionInfo; 2897 return; 2898 } 2899 PP.Lex(Tok); 2900 2901 // Read '(' 2902 if (Tok.isNot(tok::l_paren)) { 2903 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren; 2904 return; 2905 } 2906 PP.Lex(Tok); 2907 2908 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo; 2909 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true, 2910 *Info)) 2911 return; 2912 2913 // Generate the loop hint token. 2914 Token LoopHintTok; 2915 LoopHintTok.startToken(); 2916 LoopHintTok.setKind(tok::annot_pragma_loop_hint); 2917 LoopHintTok.setLocation(PragmaName.getLocation()); 2918 LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation()); 2919 LoopHintTok.setAnnotationValue(static_cast<void *>(Info)); 2920 TokenList.push_back(LoopHintTok); 2921 } 2922 2923 if (Tok.isNot(tok::eod)) { 2924 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 2925 << "clang loop"; 2926 return; 2927 } 2928 2929 auto TokenArray = std::make_unique<Token[]>(TokenList.size()); 2930 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get()); 2931 2932 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(), 2933 /*DisableMacroExpansion=*/false, /*IsReinject=*/false); 2934 } 2935 2936 /// Handle the loop unroll optimization pragmas. 2937 /// #pragma unroll 2938 /// #pragma unroll unroll-hint-value 2939 /// #pragma unroll '(' unroll-hint-value ')' 2940 /// #pragma nounroll 2941 /// #pragma unroll_and_jam 2942 /// #pragma unroll_and_jam unroll-hint-value 2943 /// #pragma unroll_and_jam '(' unroll-hint-value ')' 2944 /// #pragma nounroll_and_jam 2945 /// 2946 /// unroll-hint-value: 2947 /// constant-expression 2948 /// 2949 /// Loop unrolling hints can be specified with '#pragma unroll' or 2950 /// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally 2951 /// contained in parentheses. With no argument the directive instructs llvm to 2952 /// try to unroll the loop completely. A positive integer argument can be 2953 /// specified to indicate the number of times the loop should be unrolled. To 2954 /// maximize compatibility with other compilers the unroll count argument can be 2955 /// specified with or without parentheses. Specifying, '#pragma nounroll' 2956 /// disables unrolling of the loop. 2957 void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP, 2958 PragmaIntroducer Introducer, 2959 Token &Tok) { 2960 // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for 2961 // "#pragma nounroll". 2962 Token PragmaName = Tok; 2963 PP.Lex(Tok); 2964 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo; 2965 if (Tok.is(tok::eod)) { 2966 // nounroll or unroll pragma without an argument. 2967 Info->PragmaName = PragmaName; 2968 Info->Option.startToken(); 2969 } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll" || 2970 PragmaName.getIdentifierInfo()->getName() == "nounroll_and_jam") { 2971 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 2972 << PragmaName.getIdentifierInfo()->getName(); 2973 return; 2974 } else { 2975 // Unroll pragma with an argument: "#pragma unroll N" or 2976 // "#pragma unroll(N)". 2977 // Read '(' if it exists. 2978 bool ValueInParens = Tok.is(tok::l_paren); 2979 if (ValueInParens) 2980 PP.Lex(Tok); 2981 2982 Token Option; 2983 Option.startToken(); 2984 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info)) 2985 return; 2986 2987 // In CUDA, the argument to '#pragma unroll' should not be contained in 2988 // parentheses. 2989 if (PP.getLangOpts().CUDA && ValueInParens) 2990 PP.Diag(Info->Toks[0].getLocation(), 2991 diag::warn_pragma_unroll_cuda_value_in_parens); 2992 2993 if (Tok.isNot(tok::eod)) { 2994 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 2995 << "unroll"; 2996 return; 2997 } 2998 } 2999 3000 // Generate the hint token. 3001 auto TokenArray = std::make_unique<Token[]>(1); 3002 TokenArray[0].startToken(); 3003 TokenArray[0].setKind(tok::annot_pragma_loop_hint); 3004 TokenArray[0].setLocation(PragmaName.getLocation()); 3005 TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation()); 3006 TokenArray[0].setAnnotationValue(static_cast<void *>(Info)); 3007 PP.EnterTokenStream(std::move(TokenArray), 1, 3008 /*DisableMacroExpansion=*/false, /*IsReinject=*/false); 3009 } 3010 3011 /// Handle the Microsoft \#pragma intrinsic extension. 3012 /// 3013 /// The syntax is: 3014 /// \code 3015 /// #pragma intrinsic(memset) 3016 /// #pragma intrinsic(strlen, memcpy) 3017 /// \endcode 3018 /// 3019 /// Pragma intrisic tells the compiler to use a builtin version of the 3020 /// function. Clang does it anyway, so the pragma doesn't really do anything. 3021 /// Anyway, we emit a warning if the function specified in \#pragma intrinsic 3022 /// isn't an intrinsic in clang and suggest to include intrin.h. 3023 void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP, 3024 PragmaIntroducer Introducer, 3025 Token &Tok) { 3026 PP.Lex(Tok); 3027 3028 if (Tok.isNot(tok::l_paren)) { 3029 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) 3030 << "intrinsic"; 3031 return; 3032 } 3033 PP.Lex(Tok); 3034 3035 bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H"); 3036 3037 while (Tok.is(tok::identifier)) { 3038 IdentifierInfo *II = Tok.getIdentifierInfo(); 3039 if (!II->getBuiltinID()) 3040 PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin) 3041 << II << SuggestIntrinH; 3042 3043 PP.Lex(Tok); 3044 if (Tok.isNot(tok::comma)) 3045 break; 3046 PP.Lex(Tok); 3047 } 3048 3049 if (Tok.isNot(tok::r_paren)) { 3050 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) 3051 << "intrinsic"; 3052 return; 3053 } 3054 PP.Lex(Tok); 3055 3056 if (Tok.isNot(tok::eod)) 3057 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 3058 << "intrinsic"; 3059 } 3060 3061 // #pragma optimize("gsty", on|off) 3062 void PragmaMSOptimizeHandler::HandlePragma(Preprocessor &PP, 3063 PragmaIntroducer Introducer, 3064 Token &Tok) { 3065 SourceLocation StartLoc = Tok.getLocation(); 3066 PP.Lex(Tok); 3067 3068 if (Tok.isNot(tok::l_paren)) { 3069 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "optimize"; 3070 return; 3071 } 3072 PP.Lex(Tok); 3073 3074 if (Tok.isNot(tok::string_literal)) { 3075 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_string) << "optimize"; 3076 return; 3077 } 3078 // We could syntax check the string but it's probably not worth the effort. 3079 PP.Lex(Tok); 3080 3081 if (Tok.isNot(tok::comma)) { 3082 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_comma) << "optimize"; 3083 return; 3084 } 3085 PP.Lex(Tok); 3086 3087 if (Tok.is(tok::eod) || Tok.is(tok::r_paren)) { 3088 PP.Diag(Tok.getLocation(), diag::warn_pragma_missing_argument) 3089 << "optimize" << /*Expected=*/true << "'on' or 'off'"; 3090 return; 3091 } 3092 IdentifierInfo *II = Tok.getIdentifierInfo(); 3093 if (!II || (!II->isStr("on") && !II->isStr("off"))) { 3094 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument) 3095 << PP.getSpelling(Tok) << "optimize" << /*Expected=*/true 3096 << "'on' or 'off'"; 3097 return; 3098 } 3099 PP.Lex(Tok); 3100 3101 if (Tok.isNot(tok::r_paren)) { 3102 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "optimize"; 3103 return; 3104 } 3105 PP.Lex(Tok); 3106 3107 if (Tok.isNot(tok::eod)) { 3108 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 3109 << "optimize"; 3110 return; 3111 } 3112 PP.Diag(StartLoc, diag::warn_pragma_optimize); 3113 } 3114 3115 void PragmaForceCUDAHostDeviceHandler::HandlePragma( 3116 Preprocessor &PP, PragmaIntroducer Introducer, Token &Tok) { 3117 Token FirstTok = Tok; 3118 3119 PP.Lex(Tok); 3120 IdentifierInfo *Info = Tok.getIdentifierInfo(); 3121 if (!Info || (!Info->isStr("begin") && !Info->isStr("end"))) { 3122 PP.Diag(FirstTok.getLocation(), 3123 diag::warn_pragma_force_cuda_host_device_bad_arg); 3124 return; 3125 } 3126 3127 if (Info->isStr("begin")) 3128 Actions.PushForceCUDAHostDevice(); 3129 else if (!Actions.PopForceCUDAHostDevice()) 3130 PP.Diag(FirstTok.getLocation(), 3131 diag::err_pragma_cannot_end_force_cuda_host_device); 3132 3133 PP.Lex(Tok); 3134 if (!Tok.is(tok::eod)) 3135 PP.Diag(FirstTok.getLocation(), 3136 diag::warn_pragma_force_cuda_host_device_bad_arg); 3137 } 3138 3139 /// Handle the #pragma clang attribute directive. 3140 /// 3141 /// The syntax is: 3142 /// \code 3143 /// #pragma clang attribute push (attribute, subject-set) 3144 /// #pragma clang attribute push 3145 /// #pragma clang attribute (attribute, subject-set) 3146 /// #pragma clang attribute pop 3147 /// \endcode 3148 /// 3149 /// There are also 'namespace' variants of push and pop directives. The bare 3150 /// '#pragma clang attribute (attribute, subject-set)' version doesn't require a 3151 /// namespace, since it always applies attributes to the most recently pushed 3152 /// group, regardless of namespace. 3153 /// \code 3154 /// #pragma clang attribute namespace.push (attribute, subject-set) 3155 /// #pragma clang attribute namespace.push 3156 /// #pragma clang attribute namespace.pop 3157 /// \endcode 3158 /// 3159 /// The subject-set clause defines the set of declarations which receive the 3160 /// attribute. Its exact syntax is described in the LanguageExtensions document 3161 /// in Clang's documentation. 3162 /// 3163 /// This directive instructs the compiler to begin/finish applying the specified 3164 /// attribute to the set of attribute-specific declarations in the active range 3165 /// of the pragma. 3166 void PragmaAttributeHandler::HandlePragma(Preprocessor &PP, 3167 PragmaIntroducer Introducer, 3168 Token &FirstToken) { 3169 Token Tok; 3170 PP.Lex(Tok); 3171 auto *Info = new (PP.getPreprocessorAllocator()) 3172 PragmaAttributeInfo(AttributesForPragmaAttribute); 3173 3174 // Parse the optional namespace followed by a period. 3175 if (Tok.is(tok::identifier)) { 3176 IdentifierInfo *II = Tok.getIdentifierInfo(); 3177 if (!II->isStr("push") && !II->isStr("pop")) { 3178 Info->Namespace = II; 3179 PP.Lex(Tok); 3180 3181 if (!Tok.is(tok::period)) { 3182 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_period) 3183 << II; 3184 return; 3185 } 3186 PP.Lex(Tok); 3187 } 3188 } 3189 3190 if (!Tok.isOneOf(tok::identifier, tok::l_paren)) { 3191 PP.Diag(Tok.getLocation(), 3192 diag::err_pragma_attribute_expected_push_pop_paren); 3193 return; 3194 } 3195 3196 // Determine what action this pragma clang attribute represents. 3197 if (Tok.is(tok::l_paren)) { 3198 if (Info->Namespace) { 3199 PP.Diag(Tok.getLocation(), 3200 diag::err_pragma_attribute_namespace_on_attribute); 3201 PP.Diag(Tok.getLocation(), 3202 diag::note_pragma_attribute_namespace_on_attribute); 3203 return; 3204 } 3205 Info->Action = PragmaAttributeInfo::Attribute; 3206 } else { 3207 const IdentifierInfo *II = Tok.getIdentifierInfo(); 3208 if (II->isStr("push")) 3209 Info->Action = PragmaAttributeInfo::Push; 3210 else if (II->isStr("pop")) 3211 Info->Action = PragmaAttributeInfo::Pop; 3212 else { 3213 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument) 3214 << PP.getSpelling(Tok); 3215 return; 3216 } 3217 3218 PP.Lex(Tok); 3219 } 3220 3221 // Parse the actual attribute. 3222 if ((Info->Action == PragmaAttributeInfo::Push && Tok.isNot(tok::eod)) || 3223 Info->Action == PragmaAttributeInfo::Attribute) { 3224 if (Tok.isNot(tok::l_paren)) { 3225 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren; 3226 return; 3227 } 3228 PP.Lex(Tok); 3229 3230 // Lex the attribute tokens. 3231 SmallVector<Token, 16> AttributeTokens; 3232 int OpenParens = 1; 3233 while (Tok.isNot(tok::eod)) { 3234 if (Tok.is(tok::l_paren)) 3235 OpenParens++; 3236 else if (Tok.is(tok::r_paren)) { 3237 OpenParens--; 3238 if (OpenParens == 0) 3239 break; 3240 } 3241 3242 AttributeTokens.push_back(Tok); 3243 PP.Lex(Tok); 3244 } 3245 3246 if (AttributeTokens.empty()) { 3247 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute); 3248 return; 3249 } 3250 if (Tok.isNot(tok::r_paren)) { 3251 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren; 3252 return; 3253 } 3254 SourceLocation EndLoc = Tok.getLocation(); 3255 PP.Lex(Tok); 3256 3257 // Terminate the attribute for parsing. 3258 Token EOFTok; 3259 EOFTok.startToken(); 3260 EOFTok.setKind(tok::eof); 3261 EOFTok.setLocation(EndLoc); 3262 AttributeTokens.push_back(EOFTok); 3263 3264 Info->Tokens = 3265 llvm::makeArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator()); 3266 } 3267 3268 if (Tok.isNot(tok::eod)) 3269 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 3270 << "clang attribute"; 3271 3272 // Generate the annotated pragma token. 3273 auto TokenArray = std::make_unique<Token[]>(1); 3274 TokenArray[0].startToken(); 3275 TokenArray[0].setKind(tok::annot_pragma_attribute); 3276 TokenArray[0].setLocation(FirstToken.getLocation()); 3277 TokenArray[0].setAnnotationEndLoc(FirstToken.getLocation()); 3278 TokenArray[0].setAnnotationValue(static_cast<void *>(Info)); 3279 PP.EnterTokenStream(std::move(TokenArray), 1, 3280 /*DisableMacroExpansion=*/false, /*IsReinject=*/false); 3281 } 3282