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