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