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