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