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