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/DiagnosticParse.h" 15 #include "clang/Basic/PragmaKinds.h" 16 #include "clang/Basic/TargetInfo.h" 17 #include "clang/Lex/Preprocessor.h" 18 #include "clang/Lex/Token.h" 19 #include "clang/Parse/LoopHint.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 // pack '(' 'packed' | 'full' | 'twobyte' | 'reset' ')' with -fzos-extensions 2130 void PragmaPackHandler::HandlePragma(Preprocessor &PP, 2131 PragmaIntroducer Introducer, 2132 Token &PackTok) { 2133 SourceLocation PackLoc = PackTok.getLocation(); 2134 2135 Token Tok; 2136 PP.Lex(Tok); 2137 if (Tok.isNot(tok::l_paren)) { 2138 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack"; 2139 return; 2140 } 2141 2142 Sema::PragmaMsStackAction Action = Sema::PSK_Reset; 2143 StringRef SlotLabel; 2144 Token Alignment; 2145 Alignment.startToken(); 2146 PP.Lex(Tok); 2147 if (Tok.is(tok::numeric_constant)) { 2148 Alignment = Tok; 2149 2150 PP.Lex(Tok); 2151 2152 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting 2153 // the push/pop stack. 2154 // In Apple gcc/XL, #pragma pack(4) is equivalent to #pragma pack(push, 4) 2155 Action = (PP.getLangOpts().ApplePragmaPack || PP.getLangOpts().XLPragmaPack) 2156 ? Sema::PSK_Push_Set 2157 : Sema::PSK_Set; 2158 } else if (Tok.is(tok::identifier)) { 2159 // Map pragma pack options to pack (integer). 2160 auto MapPack = [&](const char *Literal) { 2161 Action = Sema::PSK_Push_Set; 2162 Alignment = Tok; 2163 Alignment.setKind(tok::numeric_constant); 2164 Alignment.setLiteralData(Literal); 2165 Alignment.setLength(1); 2166 }; 2167 2168 const IdentifierInfo *II = Tok.getIdentifierInfo(); 2169 if (II->isStr("show")) { 2170 Action = Sema::PSK_Show; 2171 PP.Lex(Tok); 2172 } else if (II->isStr("packed") && PP.getLangOpts().ZOSExt) { 2173 // #pragma pack(packed) is the same as #pragma pack(1) 2174 MapPack("1"); 2175 PP.Lex(Tok); 2176 } else if (II->isStr("full") && PP.getLangOpts().ZOSExt) { 2177 // #pragma pack(full) is the same as #pragma pack(4) 2178 MapPack("4"); 2179 PP.Lex(Tok); 2180 } else if (II->isStr("twobyte") && PP.getLangOpts().ZOSExt) { 2181 // #pragma pack(twobyte) is the same as #pragma pack(2) 2182 MapPack("2"); 2183 PP.Lex(Tok); 2184 } else if (II->isStr("reset") && PP.getLangOpts().ZOSExt) { 2185 // #pragma pack(reset) is the same as #pragma pack(pop) on XL 2186 Action = Sema::PSK_Pop; 2187 PP.Lex(Tok); 2188 } else { 2189 if (II->isStr("push")) { 2190 Action = Sema::PSK_Push; 2191 } else if (II->isStr("pop")) { 2192 Action = Sema::PSK_Pop; 2193 } else { 2194 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack"; 2195 return; 2196 } 2197 PP.Lex(Tok); 2198 2199 if (Tok.is(tok::comma)) { 2200 PP.Lex(Tok); 2201 2202 if (Tok.is(tok::numeric_constant)) { 2203 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set); 2204 Alignment = Tok; 2205 2206 PP.Lex(Tok); 2207 } else if (Tok.is(tok::identifier)) { 2208 SlotLabel = Tok.getIdentifierInfo()->getName(); 2209 PP.Lex(Tok); 2210 2211 if (Tok.is(tok::comma)) { 2212 PP.Lex(Tok); 2213 2214 if (Tok.isNot(tok::numeric_constant)) { 2215 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed); 2216 return; 2217 } 2218 2219 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set); 2220 Alignment = Tok; 2221 2222 PP.Lex(Tok); 2223 } 2224 } else { 2225 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed); 2226 return; 2227 } 2228 } 2229 } 2230 } else if (PP.getLangOpts().ApplePragmaPack || 2231 PP.getLangOpts().XLPragmaPack) { 2232 // In MSVC/gcc, #pragma pack() resets the alignment without affecting 2233 // the push/pop stack. 2234 // In Apple gcc and IBM XL, #pragma pack() is equivalent to #pragma 2235 // pack(pop). 2236 Action = Sema::PSK_Pop; 2237 } 2238 2239 if (Tok.isNot(tok::r_paren)) { 2240 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack"; 2241 return; 2242 } 2243 2244 SourceLocation RParenLoc = Tok.getLocation(); 2245 PP.Lex(Tok); 2246 if (Tok.isNot(tok::eod)) { 2247 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack"; 2248 return; 2249 } 2250 2251 Sema::PragmaPackInfo *Info = 2252 PP.getPreprocessorAllocator().Allocate<Sema::PragmaPackInfo>(1); 2253 Info->Action = Action; 2254 Info->SlotLabel = SlotLabel; 2255 Info->Alignment = Alignment; 2256 2257 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1), 2258 1); 2259 Toks[0].startToken(); 2260 Toks[0].setKind(tok::annot_pragma_pack); 2261 Toks[0].setLocation(PackLoc); 2262 Toks[0].setAnnotationEndLoc(RParenLoc); 2263 Toks[0].setAnnotationValue(static_cast<void*>(Info)); 2264 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 2265 /*IsReinject=*/false); 2266 } 2267 2268 // #pragma ms_struct on 2269 // #pragma ms_struct off 2270 void PragmaMSStructHandler::HandlePragma(Preprocessor &PP, 2271 PragmaIntroducer Introducer, 2272 Token &MSStructTok) { 2273 PragmaMSStructKind Kind = PMSST_OFF; 2274 2275 Token Tok; 2276 PP.Lex(Tok); 2277 if (Tok.isNot(tok::identifier)) { 2278 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct); 2279 return; 2280 } 2281 SourceLocation EndLoc = Tok.getLocation(); 2282 const IdentifierInfo *II = Tok.getIdentifierInfo(); 2283 if (II->isStr("on")) { 2284 Kind = PMSST_ON; 2285 PP.Lex(Tok); 2286 } 2287 else if (II->isStr("off") || II->isStr("reset")) 2288 PP.Lex(Tok); 2289 else { 2290 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct); 2291 return; 2292 } 2293 2294 if (Tok.isNot(tok::eod)) { 2295 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 2296 << "ms_struct"; 2297 return; 2298 } 2299 2300 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1), 2301 1); 2302 Toks[0].startToken(); 2303 Toks[0].setKind(tok::annot_pragma_msstruct); 2304 Toks[0].setLocation(MSStructTok.getLocation()); 2305 Toks[0].setAnnotationEndLoc(EndLoc); 2306 Toks[0].setAnnotationValue(reinterpret_cast<void*>( 2307 static_cast<uintptr_t>(Kind))); 2308 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 2309 /*IsReinject=*/false); 2310 } 2311 2312 // #pragma clang section bss="abc" data="" rodata="def" text="" relro="" 2313 void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP, 2314 PragmaIntroducer Introducer, 2315 Token &FirstToken) { 2316 2317 Token Tok; 2318 auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid; 2319 2320 PP.Lex(Tok); // eat 'section' 2321 while (Tok.isNot(tok::eod)) { 2322 if (Tok.isNot(tok::identifier)) { 2323 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section"; 2324 return; 2325 } 2326 2327 const IdentifierInfo *SecType = Tok.getIdentifierInfo(); 2328 if (SecType->isStr("bss")) 2329 SecKind = Sema::PragmaClangSectionKind::PCSK_BSS; 2330 else if (SecType->isStr("data")) 2331 SecKind = Sema::PragmaClangSectionKind::PCSK_Data; 2332 else if (SecType->isStr("rodata")) 2333 SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata; 2334 else if (SecType->isStr("relro")) 2335 SecKind = Sema::PragmaClangSectionKind::PCSK_Relro; 2336 else if (SecType->isStr("text")) 2337 SecKind = Sema::PragmaClangSectionKind::PCSK_Text; 2338 else { 2339 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section"; 2340 return; 2341 } 2342 2343 SourceLocation PragmaLocation = Tok.getLocation(); 2344 PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text'] 2345 if (Tok.isNot(tok::equal)) { 2346 PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind; 2347 return; 2348 } 2349 2350 std::string SecName; 2351 if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false)) 2352 return; 2353 2354 Actions.ActOnPragmaClangSection( 2355 PragmaLocation, 2356 (SecName.size() ? Sema::PragmaClangSectionAction::PCSA_Set 2357 : Sema::PragmaClangSectionAction::PCSA_Clear), 2358 SecKind, SecName); 2359 } 2360 } 2361 2362 // #pragma 'align' '=' {'native','natural','mac68k','power','reset'} 2363 // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'} 2364 // #pragma 'align' '(' {'native','natural','mac68k','power','reset'} ')' 2365 static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok, 2366 bool IsOptions) { 2367 Token Tok; 2368 2369 if (IsOptions) { 2370 PP.Lex(Tok); 2371 if (Tok.isNot(tok::identifier) || 2372 !Tok.getIdentifierInfo()->isStr("align")) { 2373 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align); 2374 return; 2375 } 2376 } 2377 2378 PP.Lex(Tok); 2379 if (PP.getLangOpts().XLPragmaPack) { 2380 if (Tok.isNot(tok::l_paren)) { 2381 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "align"; 2382 return; 2383 } 2384 } else if (Tok.isNot(tok::equal)) { 2385 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal) 2386 << IsOptions; 2387 return; 2388 } 2389 2390 PP.Lex(Tok); 2391 if (Tok.isNot(tok::identifier)) { 2392 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 2393 << (IsOptions ? "options" : "align"); 2394 return; 2395 } 2396 2397 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural; 2398 const IdentifierInfo *II = Tok.getIdentifierInfo(); 2399 if (II->isStr("native")) 2400 Kind = Sema::POAK_Native; 2401 else if (II->isStr("natural")) 2402 Kind = Sema::POAK_Natural; 2403 else if (II->isStr("packed")) 2404 Kind = Sema::POAK_Packed; 2405 else if (II->isStr("power")) 2406 Kind = Sema::POAK_Power; 2407 else if (II->isStr("mac68k")) 2408 Kind = Sema::POAK_Mac68k; 2409 else if (II->isStr("reset")) 2410 Kind = Sema::POAK_Reset; 2411 else { 2412 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option) 2413 << IsOptions; 2414 return; 2415 } 2416 2417 if (PP.getLangOpts().XLPragmaPack) { 2418 PP.Lex(Tok); 2419 if (Tok.isNot(tok::r_paren)) { 2420 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "align"; 2421 return; 2422 } 2423 } 2424 2425 SourceLocation EndLoc = Tok.getLocation(); 2426 PP.Lex(Tok); 2427 if (Tok.isNot(tok::eod)) { 2428 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 2429 << (IsOptions ? "options" : "align"); 2430 return; 2431 } 2432 2433 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1), 2434 1); 2435 Toks[0].startToken(); 2436 Toks[0].setKind(tok::annot_pragma_align); 2437 Toks[0].setLocation(FirstTok.getLocation()); 2438 Toks[0].setAnnotationEndLoc(EndLoc); 2439 Toks[0].setAnnotationValue(reinterpret_cast<void*>( 2440 static_cast<uintptr_t>(Kind))); 2441 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 2442 /*IsReinject=*/false); 2443 } 2444 2445 void PragmaAlignHandler::HandlePragma(Preprocessor &PP, 2446 PragmaIntroducer Introducer, 2447 Token &AlignTok) { 2448 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false); 2449 } 2450 2451 void PragmaOptionsHandler::HandlePragma(Preprocessor &PP, 2452 PragmaIntroducer Introducer, 2453 Token &OptionsTok) { 2454 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true); 2455 } 2456 2457 // #pragma unused(identifier) 2458 void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, 2459 PragmaIntroducer Introducer, 2460 Token &UnusedTok) { 2461 // FIXME: Should we be expanding macros here? My guess is no. 2462 SourceLocation UnusedLoc = UnusedTok.getLocation(); 2463 2464 // Lex the left '('. 2465 Token Tok; 2466 PP.Lex(Tok); 2467 if (Tok.isNot(tok::l_paren)) { 2468 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused"; 2469 return; 2470 } 2471 2472 // Lex the declaration reference(s). 2473 SmallVector<Token, 5> Identifiers; 2474 SourceLocation RParenLoc; 2475 bool LexID = true; 2476 2477 while (true) { 2478 PP.Lex(Tok); 2479 2480 if (LexID) { 2481 if (Tok.is(tok::identifier)) { 2482 Identifiers.push_back(Tok); 2483 LexID = false; 2484 continue; 2485 } 2486 2487 // Illegal token! 2488 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var); 2489 return; 2490 } 2491 2492 // We are execting a ')' or a ','. 2493 if (Tok.is(tok::comma)) { 2494 LexID = true; 2495 continue; 2496 } 2497 2498 if (Tok.is(tok::r_paren)) { 2499 RParenLoc = Tok.getLocation(); 2500 break; 2501 } 2502 2503 // Illegal token! 2504 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused"; 2505 return; 2506 } 2507 2508 PP.Lex(Tok); 2509 if (Tok.isNot(tok::eod)) { 2510 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << 2511 "unused"; 2512 return; 2513 } 2514 2515 // Verify that we have a location for the right parenthesis. 2516 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'"); 2517 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments"); 2518 2519 // For each identifier token, insert into the token stream a 2520 // annot_pragma_unused token followed by the identifier token. 2521 // This allows us to cache a "#pragma unused" that occurs inside an inline 2522 // C++ member function. 2523 2524 MutableArrayRef<Token> Toks( 2525 PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()), 2526 2 * Identifiers.size()); 2527 for (unsigned i=0; i != Identifiers.size(); i++) { 2528 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1]; 2529 pragmaUnusedTok.startToken(); 2530 pragmaUnusedTok.setKind(tok::annot_pragma_unused); 2531 pragmaUnusedTok.setLocation(UnusedLoc); 2532 idTok = Identifiers[i]; 2533 } 2534 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 2535 /*IsReinject=*/false); 2536 } 2537 2538 // #pragma weak identifier 2539 // #pragma weak identifier '=' identifier 2540 void PragmaWeakHandler::HandlePragma(Preprocessor &PP, 2541 PragmaIntroducer Introducer, 2542 Token &WeakTok) { 2543 SourceLocation WeakLoc = WeakTok.getLocation(); 2544 2545 Token Tok; 2546 PP.Lex(Tok); 2547 if (Tok.isNot(tok::identifier)) { 2548 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak"; 2549 return; 2550 } 2551 2552 Token WeakName = Tok; 2553 bool HasAlias = false; 2554 Token AliasName; 2555 2556 PP.Lex(Tok); 2557 if (Tok.is(tok::equal)) { 2558 HasAlias = true; 2559 PP.Lex(Tok); 2560 if (Tok.isNot(tok::identifier)) { 2561 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 2562 << "weak"; 2563 return; 2564 } 2565 AliasName = Tok; 2566 PP.Lex(Tok); 2567 } 2568 2569 if (Tok.isNot(tok::eod)) { 2570 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak"; 2571 return; 2572 } 2573 2574 if (HasAlias) { 2575 MutableArrayRef<Token> Toks( 2576 PP.getPreprocessorAllocator().Allocate<Token>(3), 3); 2577 Token &pragmaUnusedTok = Toks[0]; 2578 pragmaUnusedTok.startToken(); 2579 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias); 2580 pragmaUnusedTok.setLocation(WeakLoc); 2581 pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation()); 2582 Toks[1] = WeakName; 2583 Toks[2] = AliasName; 2584 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 2585 /*IsReinject=*/false); 2586 } else { 2587 MutableArrayRef<Token> Toks( 2588 PP.getPreprocessorAllocator().Allocate<Token>(2), 2); 2589 Token &pragmaUnusedTok = Toks[0]; 2590 pragmaUnusedTok.startToken(); 2591 pragmaUnusedTok.setKind(tok::annot_pragma_weak); 2592 pragmaUnusedTok.setLocation(WeakLoc); 2593 pragmaUnusedTok.setAnnotationEndLoc(WeakLoc); 2594 Toks[1] = WeakName; 2595 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 2596 /*IsReinject=*/false); 2597 } 2598 } 2599 2600 // #pragma redefine_extname identifier identifier 2601 void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP, 2602 PragmaIntroducer Introducer, 2603 Token &RedefToken) { 2604 SourceLocation RedefLoc = RedefToken.getLocation(); 2605 2606 Token Tok; 2607 PP.Lex(Tok); 2608 if (Tok.isNot(tok::identifier)) { 2609 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << 2610 "redefine_extname"; 2611 return; 2612 } 2613 2614 Token RedefName = Tok; 2615 PP.Lex(Tok); 2616 2617 if (Tok.isNot(tok::identifier)) { 2618 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 2619 << "redefine_extname"; 2620 return; 2621 } 2622 2623 Token AliasName = Tok; 2624 PP.Lex(Tok); 2625 2626 if (Tok.isNot(tok::eod)) { 2627 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << 2628 "redefine_extname"; 2629 return; 2630 } 2631 2632 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3), 2633 3); 2634 Token &pragmaRedefTok = Toks[0]; 2635 pragmaRedefTok.startToken(); 2636 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname); 2637 pragmaRedefTok.setLocation(RedefLoc); 2638 pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation()); 2639 Toks[1] = RedefName; 2640 Toks[2] = AliasName; 2641 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 2642 /*IsReinject=*/false); 2643 } 2644 2645 void PragmaFPContractHandler::HandlePragma(Preprocessor &PP, 2646 PragmaIntroducer Introducer, 2647 Token &Tok) { 2648 tok::OnOffSwitch OOS; 2649 if (PP.LexOnOffSwitch(OOS)) 2650 return; 2651 2652 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1), 2653 1); 2654 Toks[0].startToken(); 2655 Toks[0].setKind(tok::annot_pragma_fp_contract); 2656 Toks[0].setLocation(Tok.getLocation()); 2657 Toks[0].setAnnotationEndLoc(Tok.getLocation()); 2658 Toks[0].setAnnotationValue(reinterpret_cast<void*>( 2659 static_cast<uintptr_t>(OOS))); 2660 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 2661 /*IsReinject=*/false); 2662 } 2663 2664 void PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP, 2665 PragmaIntroducer Introducer, 2666 Token &Tok) { 2667 PP.LexUnexpandedToken(Tok); 2668 if (Tok.isNot(tok::identifier)) { 2669 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << 2670 "OPENCL"; 2671 return; 2672 } 2673 IdentifierInfo *Ext = Tok.getIdentifierInfo(); 2674 SourceLocation NameLoc = Tok.getLocation(); 2675 2676 PP.Lex(Tok); 2677 if (Tok.isNot(tok::colon)) { 2678 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext; 2679 return; 2680 } 2681 2682 PP.Lex(Tok); 2683 if (Tok.isNot(tok::identifier)) { 2684 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0; 2685 return; 2686 } 2687 IdentifierInfo *Pred = Tok.getIdentifierInfo(); 2688 2689 OpenCLExtState State; 2690 if (Pred->isStr("enable")) { 2691 State = Enable; 2692 } else if (Pred->isStr("disable")) { 2693 State = Disable; 2694 } else if (Pred->isStr("begin")) 2695 State = Begin; 2696 else if (Pred->isStr("end")) 2697 State = End; 2698 else { 2699 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) 2700 << Ext->isStr("all"); 2701 return; 2702 } 2703 SourceLocation StateLoc = Tok.getLocation(); 2704 2705 PP.Lex(Tok); 2706 if (Tok.isNot(tok::eod)) { 2707 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << 2708 "OPENCL EXTENSION"; 2709 return; 2710 } 2711 2712 auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1); 2713 Info->first = Ext; 2714 Info->second = State; 2715 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1), 2716 1); 2717 Toks[0].startToken(); 2718 Toks[0].setKind(tok::annot_pragma_opencl_extension); 2719 Toks[0].setLocation(NameLoc); 2720 Toks[0].setAnnotationValue(static_cast<void*>(Info)); 2721 Toks[0].setAnnotationEndLoc(StateLoc); 2722 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 2723 /*IsReinject=*/false); 2724 2725 if (PP.getPPCallbacks()) 2726 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext, 2727 StateLoc, State); 2728 } 2729 2730 /// Handle '#pragma omp ...' when OpenMP is disabled and '#pragma acc ...' when 2731 /// OpenACC is disabled. 2732 template <diag::kind IgnoredDiag> 2733 void PragmaNoSupportHandler<IgnoredDiag>::HandlePragma( 2734 Preprocessor &PP, PragmaIntroducer Introducer, Token &FirstTok) { 2735 if (!PP.getDiagnostics().isIgnored(IgnoredDiag, FirstTok.getLocation())) { 2736 PP.Diag(FirstTok, IgnoredDiag); 2737 PP.getDiagnostics().setSeverity(IgnoredDiag, diag::Severity::Ignored, 2738 SourceLocation()); 2739 } 2740 PP.DiscardUntilEndOfDirective(); 2741 } 2742 2743 /// Handle '#pragma omp ...' when OpenMP is enabled, and handle '#pragma acc...' 2744 /// when OpenACC is enabled. 2745 template <tok::TokenKind StartTok, tok::TokenKind EndTok, 2746 diag::kind UnexpectedDiag> 2747 void PragmaSupportHandler<StartTok, EndTok, UnexpectedDiag>::HandlePragma( 2748 Preprocessor &PP, PragmaIntroducer Introducer, Token &FirstTok) { 2749 SmallVector<Token, 16> Pragma; 2750 Token Tok; 2751 Tok.startToken(); 2752 Tok.setKind(StartTok); 2753 Tok.setLocation(Introducer.Loc); 2754 2755 while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof)) { 2756 Pragma.push_back(Tok); 2757 PP.Lex(Tok); 2758 if (Tok.is(StartTok)) { 2759 PP.Diag(Tok, UnexpectedDiag) << 0; 2760 unsigned InnerPragmaCnt = 1; 2761 while (InnerPragmaCnt != 0) { 2762 PP.Lex(Tok); 2763 if (Tok.is(StartTok)) 2764 ++InnerPragmaCnt; 2765 else if (Tok.is(EndTok)) 2766 --InnerPragmaCnt; 2767 } 2768 PP.Lex(Tok); 2769 } 2770 } 2771 SourceLocation EodLoc = Tok.getLocation(); 2772 Tok.startToken(); 2773 Tok.setKind(EndTok); 2774 Tok.setLocation(EodLoc); 2775 Pragma.push_back(Tok); 2776 2777 auto Toks = std::make_unique<Token[]>(Pragma.size()); 2778 std::copy(Pragma.begin(), Pragma.end(), Toks.get()); 2779 PP.EnterTokenStream(std::move(Toks), Pragma.size(), 2780 /*DisableMacroExpansion=*/false, /*IsReinject=*/false); 2781 } 2782 2783 /// Handle '#pragma pointers_to_members' 2784 // The grammar for this pragma is as follows: 2785 // 2786 // <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance' 2787 // 2788 // #pragma pointers_to_members '(' 'best_case' ')' 2789 // #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')' 2790 // #pragma pointers_to_members '(' inheritance-model ')' 2791 void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP, 2792 PragmaIntroducer Introducer, 2793 Token &Tok) { 2794 SourceLocation PointersToMembersLoc = Tok.getLocation(); 2795 PP.Lex(Tok); 2796 if (Tok.isNot(tok::l_paren)) { 2797 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen) 2798 << "pointers_to_members"; 2799 return; 2800 } 2801 PP.Lex(Tok); 2802 const IdentifierInfo *Arg = Tok.getIdentifierInfo(); 2803 if (!Arg) { 2804 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 2805 << "pointers_to_members"; 2806 return; 2807 } 2808 PP.Lex(Tok); 2809 2810 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod; 2811 if (Arg->isStr("best_case")) { 2812 RepresentationMethod = LangOptions::PPTMK_BestCase; 2813 } else { 2814 if (Arg->isStr("full_generality")) { 2815 if (Tok.is(tok::comma)) { 2816 PP.Lex(Tok); 2817 2818 Arg = Tok.getIdentifierInfo(); 2819 if (!Arg) { 2820 PP.Diag(Tok.getLocation(), 2821 diag::err_pragma_pointers_to_members_unknown_kind) 2822 << Tok.getKind() << /*OnlyInheritanceModels*/ 0; 2823 return; 2824 } 2825 PP.Lex(Tok); 2826 } else if (Tok.is(tok::r_paren)) { 2827 // #pragma pointers_to_members(full_generality) implicitly specifies 2828 // virtual_inheritance. 2829 Arg = nullptr; 2830 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance; 2831 } else { 2832 PP.Diag(Tok.getLocation(), diag::err_expected_punc) 2833 << "full_generality"; 2834 return; 2835 } 2836 } 2837 2838 if (Arg) { 2839 if (Arg->isStr("single_inheritance")) { 2840 RepresentationMethod = 2841 LangOptions::PPTMK_FullGeneralitySingleInheritance; 2842 } else if (Arg->isStr("multiple_inheritance")) { 2843 RepresentationMethod = 2844 LangOptions::PPTMK_FullGeneralityMultipleInheritance; 2845 } else if (Arg->isStr("virtual_inheritance")) { 2846 RepresentationMethod = 2847 LangOptions::PPTMK_FullGeneralityVirtualInheritance; 2848 } else { 2849 PP.Diag(Tok.getLocation(), 2850 diag::err_pragma_pointers_to_members_unknown_kind) 2851 << Arg << /*HasPointerDeclaration*/ 1; 2852 return; 2853 } 2854 } 2855 } 2856 2857 if (Tok.isNot(tok::r_paren)) { 2858 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after) 2859 << (Arg ? Arg->getName() : "full_generality"); 2860 return; 2861 } 2862 2863 SourceLocation EndLoc = Tok.getLocation(); 2864 PP.Lex(Tok); 2865 if (Tok.isNot(tok::eod)) { 2866 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 2867 << "pointers_to_members"; 2868 return; 2869 } 2870 2871 Token AnnotTok; 2872 AnnotTok.startToken(); 2873 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members); 2874 AnnotTok.setLocation(PointersToMembersLoc); 2875 AnnotTok.setAnnotationEndLoc(EndLoc); 2876 AnnotTok.setAnnotationValue( 2877 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod))); 2878 PP.EnterToken(AnnotTok, /*IsReinject=*/true); 2879 } 2880 2881 /// Handle '#pragma vtordisp' 2882 // The grammar for this pragma is as follows: 2883 // 2884 // <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' ) 2885 // 2886 // #pragma vtordisp '(' ['push' ','] vtordisp-mode ')' 2887 // #pragma vtordisp '(' 'pop' ')' 2888 // #pragma vtordisp '(' ')' 2889 void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP, 2890 PragmaIntroducer Introducer, Token &Tok) { 2891 SourceLocation VtorDispLoc = Tok.getLocation(); 2892 PP.Lex(Tok); 2893 if (Tok.isNot(tok::l_paren)) { 2894 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp"; 2895 return; 2896 } 2897 PP.Lex(Tok); 2898 2899 Sema::PragmaMsStackAction Action = Sema::PSK_Set; 2900 const IdentifierInfo *II = Tok.getIdentifierInfo(); 2901 if (II) { 2902 if (II->isStr("push")) { 2903 // #pragma vtordisp(push, mode) 2904 PP.Lex(Tok); 2905 if (Tok.isNot(tok::comma)) { 2906 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp"; 2907 return; 2908 } 2909 PP.Lex(Tok); 2910 Action = Sema::PSK_Push_Set; 2911 // not push, could be on/off 2912 } else if (II->isStr("pop")) { 2913 // #pragma vtordisp(pop) 2914 PP.Lex(Tok); 2915 Action = Sema::PSK_Pop; 2916 } 2917 // not push or pop, could be on/off 2918 } else { 2919 if (Tok.is(tok::r_paren)) { 2920 // #pragma vtordisp() 2921 Action = Sema::PSK_Reset; 2922 } 2923 } 2924 2925 2926 uint64_t Value = 0; 2927 if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) { 2928 const IdentifierInfo *II = Tok.getIdentifierInfo(); 2929 if (II && II->isStr("off")) { 2930 PP.Lex(Tok); 2931 Value = 0; 2932 } else if (II && II->isStr("on")) { 2933 PP.Lex(Tok); 2934 Value = 1; 2935 } else if (Tok.is(tok::numeric_constant) && 2936 PP.parseSimpleIntegerLiteral(Tok, Value)) { 2937 if (Value > 2) { 2938 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer) 2939 << 0 << 2 << "vtordisp"; 2940 return; 2941 } 2942 } else { 2943 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) 2944 << "vtordisp"; 2945 return; 2946 } 2947 } 2948 2949 // Finish the pragma: ')' $ 2950 if (Tok.isNot(tok::r_paren)) { 2951 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp"; 2952 return; 2953 } 2954 SourceLocation EndLoc = Tok.getLocation(); 2955 PP.Lex(Tok); 2956 if (Tok.isNot(tok::eod)) { 2957 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 2958 << "vtordisp"; 2959 return; 2960 } 2961 2962 // Enter the annotation. 2963 Token AnnotTok; 2964 AnnotTok.startToken(); 2965 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp); 2966 AnnotTok.setLocation(VtorDispLoc); 2967 AnnotTok.setAnnotationEndLoc(EndLoc); 2968 AnnotTok.setAnnotationValue(reinterpret_cast<void *>( 2969 static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF)))); 2970 PP.EnterToken(AnnotTok, /*IsReinject=*/false); 2971 } 2972 2973 /// Handle all MS pragmas. Simply forwards the tokens after inserting 2974 /// an annotation token. 2975 void PragmaMSPragma::HandlePragma(Preprocessor &PP, 2976 PragmaIntroducer Introducer, Token &Tok) { 2977 Token EoF, AnnotTok; 2978 EoF.startToken(); 2979 EoF.setKind(tok::eof); 2980 AnnotTok.startToken(); 2981 AnnotTok.setKind(tok::annot_pragma_ms_pragma); 2982 AnnotTok.setLocation(Tok.getLocation()); 2983 AnnotTok.setAnnotationEndLoc(Tok.getLocation()); 2984 SmallVector<Token, 8> TokenVector; 2985 // Suck up all of the tokens before the eod. 2986 for (; Tok.isNot(tok::eod); PP.Lex(Tok)) { 2987 TokenVector.push_back(Tok); 2988 AnnotTok.setAnnotationEndLoc(Tok.getLocation()); 2989 } 2990 // Add a sentinel EoF token to the end of the list. 2991 TokenVector.push_back(EoF); 2992 // We must allocate this array with new because EnterTokenStream is going to 2993 // delete it later. 2994 markAsReinjectedForRelexing(TokenVector); 2995 auto TokenArray = std::make_unique<Token[]>(TokenVector.size()); 2996 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get()); 2997 auto Value = new (PP.getPreprocessorAllocator()) 2998 std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray), 2999 TokenVector.size()); 3000 AnnotTok.setAnnotationValue(Value); 3001 PP.EnterToken(AnnotTok, /*IsReinject*/ false); 3002 } 3003 3004 /// Handle the \#pragma float_control extension. 3005 /// 3006 /// The syntax is: 3007 /// \code 3008 /// #pragma float_control(keyword[, setting] [,push]) 3009 /// \endcode 3010 /// Where 'keyword' and 'setting' are identifiers. 3011 // 'keyword' can be: precise, except, push, pop 3012 // 'setting' can be: on, off 3013 /// The optional arguments 'setting' and 'push' are supported only 3014 /// when the keyword is 'precise' or 'except'. 3015 void PragmaFloatControlHandler::HandlePragma(Preprocessor &PP, 3016 PragmaIntroducer Introducer, 3017 Token &Tok) { 3018 Sema::PragmaMsStackAction Action = Sema::PSK_Set; 3019 SourceLocation FloatControlLoc = Tok.getLocation(); 3020 Token PragmaName = Tok; 3021 if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) { 3022 PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored) 3023 << PragmaName.getIdentifierInfo()->getName(); 3024 return; 3025 } 3026 PP.Lex(Tok); 3027 if (Tok.isNot(tok::l_paren)) { 3028 PP.Diag(FloatControlLoc, diag::err_expected) << tok::l_paren; 3029 return; 3030 } 3031 3032 // Read the identifier. 3033 PP.Lex(Tok); 3034 if (Tok.isNot(tok::identifier)) { 3035 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed); 3036 return; 3037 } 3038 3039 // Verify that this is one of the float control options. 3040 IdentifierInfo *II = Tok.getIdentifierInfo(); 3041 PragmaFloatControlKind Kind = 3042 llvm::StringSwitch<PragmaFloatControlKind>(II->getName()) 3043 .Case("precise", PFC_Precise) 3044 .Case("except", PFC_Except) 3045 .Case("push", PFC_Push) 3046 .Case("pop", PFC_Pop) 3047 .Default(PFC_Unknown); 3048 PP.Lex(Tok); // the identifier 3049 if (Kind == PFC_Unknown) { 3050 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed); 3051 return; 3052 } else if (Kind == PFC_Push || Kind == PFC_Pop) { 3053 if (Tok.isNot(tok::r_paren)) { 3054 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed); 3055 return; 3056 } 3057 PP.Lex(Tok); // Eat the r_paren 3058 Action = (Kind == PFC_Pop) ? Sema::PSK_Pop : Sema::PSK_Push; 3059 } else { 3060 if (Tok.is(tok::r_paren)) 3061 // Selecting Precise or Except 3062 PP.Lex(Tok); // the r_paren 3063 else if (Tok.isNot(tok::comma)) { 3064 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed); 3065 return; 3066 } else { 3067 PP.Lex(Tok); // , 3068 if (!Tok.isAnyIdentifier()) { 3069 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed); 3070 return; 3071 } 3072 StringRef PushOnOff = Tok.getIdentifierInfo()->getName(); 3073 if (PushOnOff == "on") 3074 // Kind is set correctly 3075 ; 3076 else if (PushOnOff == "off") { 3077 if (Kind == PFC_Precise) 3078 Kind = PFC_NoPrecise; 3079 if (Kind == PFC_Except) 3080 Kind = PFC_NoExcept; 3081 } else if (PushOnOff == "push") { 3082 Action = Sema::PSK_Push_Set; 3083 } else { 3084 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed); 3085 return; 3086 } 3087 PP.Lex(Tok); // the identifier 3088 if (Tok.is(tok::comma)) { 3089 PP.Lex(Tok); // , 3090 if (!Tok.isAnyIdentifier()) { 3091 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed); 3092 return; 3093 } 3094 StringRef ExpectedPush = Tok.getIdentifierInfo()->getName(); 3095 if (ExpectedPush == "push") { 3096 Action = Sema::PSK_Push_Set; 3097 } else { 3098 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed); 3099 return; 3100 } 3101 PP.Lex(Tok); // the push identifier 3102 } 3103 if (Tok.isNot(tok::r_paren)) { 3104 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed); 3105 return; 3106 } 3107 PP.Lex(Tok); // the r_paren 3108 } 3109 } 3110 SourceLocation EndLoc = Tok.getLocation(); 3111 if (Tok.isNot(tok::eod)) { 3112 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 3113 << "float_control"; 3114 return; 3115 } 3116 3117 // Note: there is no accomodation for PP callback for this pragma. 3118 3119 // Enter the annotation. 3120 auto TokenArray = std::make_unique<Token[]>(1); 3121 TokenArray[0].startToken(); 3122 TokenArray[0].setKind(tok::annot_pragma_float_control); 3123 TokenArray[0].setLocation(FloatControlLoc); 3124 TokenArray[0].setAnnotationEndLoc(EndLoc); 3125 // Create an encoding of Action and Value by shifting the Action into 3126 // the high 16 bits then union with the Kind. 3127 TokenArray[0].setAnnotationValue(reinterpret_cast<void *>( 3128 static_cast<uintptr_t>((Action << 16) | (Kind & 0xFFFF)))); 3129 PP.EnterTokenStream(std::move(TokenArray), 1, 3130 /*DisableMacroExpansion=*/false, /*IsReinject=*/false); 3131 } 3132 3133 /// Handle the Microsoft \#pragma detect_mismatch extension. 3134 /// 3135 /// The syntax is: 3136 /// \code 3137 /// #pragma detect_mismatch("name", "value") 3138 /// \endcode 3139 /// Where 'name' and 'value' are quoted strings. The values are embedded in 3140 /// the object file and passed along to the linker. If the linker detects a 3141 /// mismatch in the object file's values for the given name, a LNK2038 error 3142 /// is emitted. See MSDN for more details. 3143 void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP, 3144 PragmaIntroducer Introducer, 3145 Token &Tok) { 3146 SourceLocation DetectMismatchLoc = Tok.getLocation(); 3147 PP.Lex(Tok); 3148 if (Tok.isNot(tok::l_paren)) { 3149 PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren; 3150 return; 3151 } 3152 3153 // Read the name to embed, which must be a string literal. 3154 std::string NameString; 3155 if (!PP.LexStringLiteral(Tok, NameString, 3156 "pragma detect_mismatch", 3157 /*AllowMacroExpansion=*/true)) 3158 return; 3159 3160 // Read the comma followed by a second string literal. 3161 std::string ValueString; 3162 if (Tok.isNot(tok::comma)) { 3163 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed); 3164 return; 3165 } 3166 3167 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch", 3168 /*AllowMacroExpansion=*/true)) 3169 return; 3170 3171 if (Tok.isNot(tok::r_paren)) { 3172 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren; 3173 return; 3174 } 3175 PP.Lex(Tok); // Eat the r_paren. 3176 3177 if (Tok.isNot(tok::eod)) { 3178 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed); 3179 return; 3180 } 3181 3182 // If the pragma is lexically sound, notify any interested PPCallbacks. 3183 if (PP.getPPCallbacks()) 3184 PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString, 3185 ValueString); 3186 3187 Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString); 3188 } 3189 3190 /// Handle the microsoft \#pragma comment extension. 3191 /// 3192 /// The syntax is: 3193 /// \code 3194 /// #pragma comment(linker, "foo") 3195 /// \endcode 3196 /// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user. 3197 /// "foo" is a string, which is fully macro expanded, and permits string 3198 /// concatenation, embedded escape characters etc. See MSDN for more details. 3199 void PragmaCommentHandler::HandlePragma(Preprocessor &PP, 3200 PragmaIntroducer Introducer, 3201 Token &Tok) { 3202 SourceLocation CommentLoc = Tok.getLocation(); 3203 PP.Lex(Tok); 3204 if (Tok.isNot(tok::l_paren)) { 3205 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed); 3206 return; 3207 } 3208 3209 // Read the identifier. 3210 PP.Lex(Tok); 3211 if (Tok.isNot(tok::identifier)) { 3212 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed); 3213 return; 3214 } 3215 3216 // Verify that this is one of the 5 explicitly listed options. 3217 IdentifierInfo *II = Tok.getIdentifierInfo(); 3218 PragmaMSCommentKind Kind = 3219 llvm::StringSwitch<PragmaMSCommentKind>(II->getName()) 3220 .Case("linker", PCK_Linker) 3221 .Case("lib", PCK_Lib) 3222 .Case("compiler", PCK_Compiler) 3223 .Case("exestr", PCK_ExeStr) 3224 .Case("user", PCK_User) 3225 .Default(PCK_Unknown); 3226 if (Kind == PCK_Unknown) { 3227 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind); 3228 return; 3229 } 3230 3231 if (PP.getTargetInfo().getTriple().isOSBinFormatELF() && Kind != PCK_Lib) { 3232 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored) 3233 << II->getName(); 3234 return; 3235 } 3236 3237 // Read the optional string if present. 3238 PP.Lex(Tok); 3239 std::string ArgumentString; 3240 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString, 3241 "pragma comment", 3242 /*AllowMacroExpansion=*/true)) 3243 return; 3244 3245 // FIXME: warn that 'exestr' is deprecated. 3246 // FIXME: If the kind is "compiler" warn if the string is present (it is 3247 // ignored). 3248 // The MSDN docs say that "lib" and "linker" require a string and have a short 3249 // list of linker options they support, but in practice MSVC doesn't 3250 // issue a diagnostic. Therefore neither does clang. 3251 3252 if (Tok.isNot(tok::r_paren)) { 3253 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed); 3254 return; 3255 } 3256 PP.Lex(Tok); // eat the r_paren. 3257 3258 if (Tok.isNot(tok::eod)) { 3259 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed); 3260 return; 3261 } 3262 3263 // If the pragma is lexically sound, notify any interested PPCallbacks. 3264 if (PP.getPPCallbacks()) 3265 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString); 3266 3267 Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString); 3268 } 3269 3270 // #pragma clang optimize off 3271 // #pragma clang optimize on 3272 void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP, 3273 PragmaIntroducer Introducer, 3274 Token &FirstToken) { 3275 Token Tok; 3276 PP.Lex(Tok); 3277 if (Tok.is(tok::eod)) { 3278 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument) 3279 << "clang optimize" << /*Expected=*/true << "'on' or 'off'"; 3280 return; 3281 } 3282 if (Tok.isNot(tok::identifier)) { 3283 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument) 3284 << PP.getSpelling(Tok); 3285 return; 3286 } 3287 const IdentifierInfo *II = Tok.getIdentifierInfo(); 3288 // The only accepted values are 'on' or 'off'. 3289 bool IsOn = false; 3290 if (II->isStr("on")) { 3291 IsOn = true; 3292 } else if (!II->isStr("off")) { 3293 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument) 3294 << PP.getSpelling(Tok); 3295 return; 3296 } 3297 PP.Lex(Tok); 3298 3299 if (Tok.isNot(tok::eod)) { 3300 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument) 3301 << PP.getSpelling(Tok); 3302 return; 3303 } 3304 3305 Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation()); 3306 } 3307 3308 namespace { 3309 /// Used as the annotation value for tok::annot_pragma_fp. 3310 struct TokFPAnnotValue { 3311 enum FlagValues { On, Off, Fast }; 3312 3313 std::optional<LangOptions::FPModeKind> ContractValue; 3314 std::optional<LangOptions::FPModeKind> ReassociateValue; 3315 std::optional<LangOptions::FPModeKind> ReciprocalValue; 3316 std::optional<LangOptions::FPExceptionModeKind> ExceptionsValue; 3317 std::optional<LangOptions::FPEvalMethodKind> EvalMethodValue; 3318 }; 3319 } // end anonymous namespace 3320 3321 void PragmaFPHandler::HandlePragma(Preprocessor &PP, 3322 PragmaIntroducer Introducer, Token &Tok) { 3323 // fp 3324 Token PragmaName = Tok; 3325 SmallVector<Token, 1> TokenList; 3326 3327 PP.Lex(Tok); 3328 if (Tok.isNot(tok::identifier)) { 3329 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option) 3330 << /*MissingOption=*/true << ""; 3331 return; 3332 } 3333 3334 auto *AnnotValue = new (PP.getPreprocessorAllocator()) TokFPAnnotValue; 3335 while (Tok.is(tok::identifier)) { 3336 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo(); 3337 3338 auto FlagKind = 3339 llvm::StringSwitch<std::optional<PragmaFPKind>>(OptionInfo->getName()) 3340 .Case("contract", PFK_Contract) 3341 .Case("reassociate", PFK_Reassociate) 3342 .Case("exceptions", PFK_Exceptions) 3343 .Case("eval_method", PFK_EvalMethod) 3344 .Case("reciprocal", PFK_Reciprocal) 3345 .Default(std::nullopt); 3346 if (!FlagKind) { 3347 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option) 3348 << /*MissingOption=*/false << OptionInfo; 3349 return; 3350 } 3351 PP.Lex(Tok); 3352 3353 // Read '(' 3354 if (Tok.isNot(tok::l_paren)) { 3355 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren; 3356 return; 3357 } 3358 PP.Lex(Tok); 3359 bool isEvalMethodDouble = 3360 Tok.is(tok::kw_double) && FlagKind == PFK_EvalMethod; 3361 3362 // Don't diagnose if we have an eval_metod pragma with "double" kind. 3363 if (Tok.isNot(tok::identifier) && !isEvalMethodDouble) { 3364 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument) 3365 << PP.getSpelling(Tok) << OptionInfo->getName() 3366 << static_cast<int>(*FlagKind); 3367 return; 3368 } 3369 const IdentifierInfo *II = Tok.getIdentifierInfo(); 3370 3371 if (FlagKind == PFK_Contract) { 3372 AnnotValue->ContractValue = 3373 llvm::StringSwitch<std::optional<LangOptions::FPModeKind>>( 3374 II->getName()) 3375 .Case("on", LangOptions::FPModeKind::FPM_On) 3376 .Case("off", LangOptions::FPModeKind::FPM_Off) 3377 .Case("fast", LangOptions::FPModeKind::FPM_Fast) 3378 .Default(std::nullopt); 3379 if (!AnnotValue->ContractValue) { 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_Reassociate || FlagKind == PFK_Reciprocal) { 3385 auto &Value = FlagKind == PFK_Reassociate ? AnnotValue->ReassociateValue 3386 : AnnotValue->ReciprocalValue; 3387 Value = llvm::StringSwitch<std::optional<LangOptions::FPModeKind>>( 3388 II->getName()) 3389 .Case("on", LangOptions::FPModeKind::FPM_On) 3390 .Case("off", LangOptions::FPModeKind::FPM_Off) 3391 .Default(std::nullopt); 3392 if (!Value) { 3393 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument) 3394 << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind; 3395 return; 3396 } 3397 } else if (FlagKind == PFK_Exceptions) { 3398 AnnotValue->ExceptionsValue = 3399 llvm::StringSwitch<std::optional<LangOptions::FPExceptionModeKind>>( 3400 II->getName()) 3401 .Case("ignore", LangOptions::FPE_Ignore) 3402 .Case("maytrap", LangOptions::FPE_MayTrap) 3403 .Case("strict", LangOptions::FPE_Strict) 3404 .Default(std::nullopt); 3405 if (!AnnotValue->ExceptionsValue) { 3406 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument) 3407 << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind; 3408 return; 3409 } 3410 } else if (FlagKind == PFK_EvalMethod) { 3411 AnnotValue->EvalMethodValue = 3412 llvm::StringSwitch<std::optional<LangOptions::FPEvalMethodKind>>( 3413 II->getName()) 3414 .Case("source", LangOptions::FPEvalMethodKind::FEM_Source) 3415 .Case("double", LangOptions::FPEvalMethodKind::FEM_Double) 3416 .Case("extended", LangOptions::FPEvalMethodKind::FEM_Extended) 3417 .Default(std::nullopt); 3418 if (!AnnotValue->EvalMethodValue) { 3419 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument) 3420 << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind; 3421 return; 3422 } 3423 } 3424 PP.Lex(Tok); 3425 3426 // Read ')' 3427 if (Tok.isNot(tok::r_paren)) { 3428 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren; 3429 return; 3430 } 3431 PP.Lex(Tok); 3432 } 3433 3434 if (Tok.isNot(tok::eod)) { 3435 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 3436 << "clang fp"; 3437 return; 3438 } 3439 3440 Token FPTok; 3441 FPTok.startToken(); 3442 FPTok.setKind(tok::annot_pragma_fp); 3443 FPTok.setLocation(PragmaName.getLocation()); 3444 FPTok.setAnnotationEndLoc(PragmaName.getLocation()); 3445 FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue)); 3446 TokenList.push_back(FPTok); 3447 3448 auto TokenArray = std::make_unique<Token[]>(TokenList.size()); 3449 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get()); 3450 3451 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(), 3452 /*DisableMacroExpansion=*/false, /*IsReinject=*/false); 3453 } 3454 3455 void PragmaSTDC_FENV_ROUNDHandler::HandlePragma(Preprocessor &PP, 3456 PragmaIntroducer Introducer, 3457 Token &Tok) { 3458 Token PragmaName = Tok; 3459 SmallVector<Token, 1> TokenList; 3460 if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) { 3461 PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored) 3462 << PragmaName.getIdentifierInfo()->getName(); 3463 return; 3464 } 3465 3466 PP.Lex(Tok); 3467 if (Tok.isNot(tok::identifier)) { 3468 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 3469 << PragmaName.getIdentifierInfo()->getName(); 3470 return; 3471 } 3472 IdentifierInfo *II = Tok.getIdentifierInfo(); 3473 3474 auto RM = 3475 llvm::StringSwitch<llvm::RoundingMode>(II->getName()) 3476 .Case("FE_TOWARDZERO", llvm::RoundingMode::TowardZero) 3477 .Case("FE_TONEAREST", llvm::RoundingMode::NearestTiesToEven) 3478 .Case("FE_UPWARD", llvm::RoundingMode::TowardPositive) 3479 .Case("FE_DOWNWARD", llvm::RoundingMode::TowardNegative) 3480 .Case("FE_TONEARESTFROMZERO", llvm::RoundingMode::NearestTiesToAway) 3481 .Case("FE_DYNAMIC", llvm::RoundingMode::Dynamic) 3482 .Default(llvm::RoundingMode::Invalid); 3483 if (RM == llvm::RoundingMode::Invalid) { 3484 PP.Diag(Tok.getLocation(), diag::warn_stdc_unknown_rounding_mode); 3485 return; 3486 } 3487 PP.Lex(Tok); 3488 3489 if (Tok.isNot(tok::eod)) { 3490 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 3491 << "STDC FENV_ROUND"; 3492 return; 3493 } 3494 3495 // Until the pragma is fully implemented, issue a warning. 3496 PP.Diag(Tok.getLocation(), diag::warn_stdc_fenv_round_not_supported); 3497 3498 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1), 3499 1); 3500 Toks[0].startToken(); 3501 Toks[0].setKind(tok::annot_pragma_fenv_round); 3502 Toks[0].setLocation(Tok.getLocation()); 3503 Toks[0].setAnnotationEndLoc(Tok.getLocation()); 3504 Toks[0].setAnnotationValue( 3505 reinterpret_cast<void *>(static_cast<uintptr_t>(RM))); 3506 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 3507 /*IsReinject=*/false); 3508 } 3509 3510 void Parser::HandlePragmaFP() { 3511 assert(Tok.is(tok::annot_pragma_fp)); 3512 auto *AnnotValue = 3513 reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue()); 3514 3515 if (AnnotValue->ReassociateValue) 3516 Actions.ActOnPragmaFPValueChangingOption( 3517 Tok.getLocation(), PFK_Reassociate, 3518 *AnnotValue->ReassociateValue == LangOptions::FPModeKind::FPM_On); 3519 3520 if (AnnotValue->ReciprocalValue) 3521 Actions.ActOnPragmaFPValueChangingOption( 3522 Tok.getLocation(), PFK_Reciprocal, 3523 *AnnotValue->ReciprocalValue == LangOptions::FPModeKind::FPM_On); 3524 3525 if (AnnotValue->ContractValue) 3526 Actions.ActOnPragmaFPContract(Tok.getLocation(), 3527 *AnnotValue->ContractValue); 3528 if (AnnotValue->ExceptionsValue) 3529 Actions.ActOnPragmaFPExceptions(Tok.getLocation(), 3530 *AnnotValue->ExceptionsValue); 3531 if (AnnotValue->EvalMethodValue) 3532 Actions.ActOnPragmaFPEvalMethod(Tok.getLocation(), 3533 *AnnotValue->EvalMethodValue); 3534 ConsumeAnnotationToken(); 3535 } 3536 3537 /// Parses loop or unroll pragma hint value and fills in Info. 3538 static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName, 3539 Token Option, bool ValueInParens, 3540 PragmaLoopHintInfo &Info) { 3541 SmallVector<Token, 1> ValueList; 3542 int OpenParens = ValueInParens ? 1 : 0; 3543 // Read constant expression. 3544 while (Tok.isNot(tok::eod)) { 3545 if (Tok.is(tok::l_paren)) 3546 OpenParens++; 3547 else if (Tok.is(tok::r_paren)) { 3548 OpenParens--; 3549 if (OpenParens == 0 && ValueInParens) 3550 break; 3551 } 3552 3553 ValueList.push_back(Tok); 3554 PP.Lex(Tok); 3555 } 3556 3557 if (ValueInParens) { 3558 // Read ')' 3559 if (Tok.isNot(tok::r_paren)) { 3560 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren; 3561 return true; 3562 } 3563 PP.Lex(Tok); 3564 } 3565 3566 Token EOFTok; 3567 EOFTok.startToken(); 3568 EOFTok.setKind(tok::eof); 3569 EOFTok.setLocation(Tok.getLocation()); 3570 ValueList.push_back(EOFTok); // Terminates expression for parsing. 3571 3572 markAsReinjectedForRelexing(ValueList); 3573 Info.Toks = llvm::ArrayRef(ValueList).copy(PP.getPreprocessorAllocator()); 3574 3575 Info.PragmaName = PragmaName; 3576 Info.Option = Option; 3577 return false; 3578 } 3579 3580 /// Handle the \#pragma clang loop directive. 3581 /// #pragma clang 'loop' loop-hints 3582 /// 3583 /// loop-hints: 3584 /// loop-hint loop-hints[opt] 3585 /// 3586 /// loop-hint: 3587 /// 'vectorize' '(' loop-hint-keyword ')' 3588 /// 'interleave' '(' loop-hint-keyword ')' 3589 /// 'unroll' '(' unroll-hint-keyword ')' 3590 /// 'vectorize_predicate' '(' loop-hint-keyword ')' 3591 /// 'vectorize_width' '(' loop-hint-value ')' 3592 /// 'interleave_count' '(' loop-hint-value ')' 3593 /// 'unroll_count' '(' loop-hint-value ')' 3594 /// 'pipeline' '(' disable ')' 3595 /// 'pipeline_initiation_interval' '(' loop-hint-value ')' 3596 /// 3597 /// loop-hint-keyword: 3598 /// 'enable' 3599 /// 'disable' 3600 /// 'assume_safety' 3601 /// 3602 /// unroll-hint-keyword: 3603 /// 'enable' 3604 /// 'disable' 3605 /// 'full' 3606 /// 3607 /// loop-hint-value: 3608 /// constant-expression 3609 /// 3610 /// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to 3611 /// try vectorizing the instructions of the loop it precedes. Specifying 3612 /// interleave(enable) or interleave_count(_value_) instructs llvm to try 3613 /// interleaving multiple iterations of the loop it precedes. The width of the 3614 /// vector instructions is specified by vectorize_width() and the number of 3615 /// interleaved loop iterations is specified by interleave_count(). Specifying a 3616 /// value of 1 effectively disables vectorization/interleaving, even if it is 3617 /// possible and profitable, and 0 is invalid. The loop vectorizer currently 3618 /// only works on inner loops. 3619 /// 3620 /// The unroll and unroll_count directives control the concatenation 3621 /// unroller. Specifying unroll(enable) instructs llvm to unroll the loop 3622 /// completely if the trip count is known at compile time and unroll partially 3623 /// if the trip count is not known. Specifying unroll(full) is similar to 3624 /// unroll(enable) but will unroll the loop only if the trip count is known at 3625 /// compile time. Specifying unroll(disable) disables unrolling for the 3626 /// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the 3627 /// loop the number of times indicated by the value. 3628 void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP, 3629 PragmaIntroducer Introducer, 3630 Token &Tok) { 3631 // Incoming token is "loop" from "#pragma clang loop". 3632 Token PragmaName = Tok; 3633 SmallVector<Token, 1> TokenList; 3634 3635 // Lex the optimization option and verify it is an identifier. 3636 PP.Lex(Tok); 3637 if (Tok.isNot(tok::identifier)) { 3638 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option) 3639 << /*MissingOption=*/true << ""; 3640 return; 3641 } 3642 3643 while (Tok.is(tok::identifier)) { 3644 Token Option = Tok; 3645 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo(); 3646 3647 bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName()) 3648 .Case("vectorize", true) 3649 .Case("interleave", true) 3650 .Case("unroll", true) 3651 .Case("distribute", true) 3652 .Case("vectorize_predicate", true) 3653 .Case("vectorize_width", true) 3654 .Case("interleave_count", true) 3655 .Case("unroll_count", true) 3656 .Case("pipeline", true) 3657 .Case("pipeline_initiation_interval", true) 3658 .Default(false); 3659 if (!OptionValid) { 3660 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option) 3661 << /*MissingOption=*/false << OptionInfo; 3662 return; 3663 } 3664 PP.Lex(Tok); 3665 3666 // Read '(' 3667 if (Tok.isNot(tok::l_paren)) { 3668 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren; 3669 return; 3670 } 3671 PP.Lex(Tok); 3672 3673 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo; 3674 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true, 3675 *Info)) 3676 return; 3677 3678 // Generate the loop hint token. 3679 Token LoopHintTok; 3680 LoopHintTok.startToken(); 3681 LoopHintTok.setKind(tok::annot_pragma_loop_hint); 3682 LoopHintTok.setLocation(Introducer.Loc); 3683 LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation()); 3684 LoopHintTok.setAnnotationValue(static_cast<void *>(Info)); 3685 TokenList.push_back(LoopHintTok); 3686 } 3687 3688 if (Tok.isNot(tok::eod)) { 3689 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 3690 << "clang loop"; 3691 return; 3692 } 3693 3694 auto TokenArray = std::make_unique<Token[]>(TokenList.size()); 3695 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get()); 3696 3697 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(), 3698 /*DisableMacroExpansion=*/false, /*IsReinject=*/false); 3699 } 3700 3701 /// Handle the loop unroll optimization pragmas. 3702 /// #pragma unroll 3703 /// #pragma unroll unroll-hint-value 3704 /// #pragma unroll '(' unroll-hint-value ')' 3705 /// #pragma nounroll 3706 /// #pragma unroll_and_jam 3707 /// #pragma unroll_and_jam unroll-hint-value 3708 /// #pragma unroll_and_jam '(' unroll-hint-value ')' 3709 /// #pragma nounroll_and_jam 3710 /// 3711 /// unroll-hint-value: 3712 /// constant-expression 3713 /// 3714 /// Loop unrolling hints can be specified with '#pragma unroll' or 3715 /// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally 3716 /// contained in parentheses. With no argument the directive instructs llvm to 3717 /// try to unroll the loop completely. A positive integer argument can be 3718 /// specified to indicate the number of times the loop should be unrolled. To 3719 /// maximize compatibility with other compilers the unroll count argument can be 3720 /// specified with or without parentheses. Specifying, '#pragma nounroll' 3721 /// disables unrolling of the loop. 3722 void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP, 3723 PragmaIntroducer Introducer, 3724 Token &Tok) { 3725 // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for 3726 // "#pragma nounroll". 3727 Token PragmaName = Tok; 3728 PP.Lex(Tok); 3729 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo; 3730 if (Tok.is(tok::eod)) { 3731 // nounroll or unroll pragma without an argument. 3732 Info->PragmaName = PragmaName; 3733 Info->Option.startToken(); 3734 } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll" || 3735 PragmaName.getIdentifierInfo()->getName() == "nounroll_and_jam") { 3736 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 3737 << PragmaName.getIdentifierInfo()->getName(); 3738 return; 3739 } else { 3740 // Unroll pragma with an argument: "#pragma unroll N" or 3741 // "#pragma unroll(N)". 3742 // Read '(' if it exists. 3743 bool ValueInParens = Tok.is(tok::l_paren); 3744 if (ValueInParens) 3745 PP.Lex(Tok); 3746 3747 Token Option; 3748 Option.startToken(); 3749 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info)) 3750 return; 3751 3752 // In CUDA, the argument to '#pragma unroll' should not be contained in 3753 // parentheses. 3754 if (PP.getLangOpts().CUDA && ValueInParens) 3755 PP.Diag(Info->Toks[0].getLocation(), 3756 diag::warn_pragma_unroll_cuda_value_in_parens); 3757 3758 if (Tok.isNot(tok::eod)) { 3759 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 3760 << "unroll"; 3761 return; 3762 } 3763 } 3764 3765 // Generate the hint token. 3766 auto TokenArray = std::make_unique<Token[]>(1); 3767 TokenArray[0].startToken(); 3768 TokenArray[0].setKind(tok::annot_pragma_loop_hint); 3769 TokenArray[0].setLocation(Introducer.Loc); 3770 TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation()); 3771 TokenArray[0].setAnnotationValue(static_cast<void *>(Info)); 3772 PP.EnterTokenStream(std::move(TokenArray), 1, 3773 /*DisableMacroExpansion=*/false, /*IsReinject=*/false); 3774 } 3775 3776 /// Handle the Microsoft \#pragma intrinsic extension. 3777 /// 3778 /// The syntax is: 3779 /// \code 3780 /// #pragma intrinsic(memset) 3781 /// #pragma intrinsic(strlen, memcpy) 3782 /// \endcode 3783 /// 3784 /// Pragma intrisic tells the compiler to use a builtin version of the 3785 /// function. Clang does it anyway, so the pragma doesn't really do anything. 3786 /// Anyway, we emit a warning if the function specified in \#pragma intrinsic 3787 /// isn't an intrinsic in clang and suggest to include intrin.h. 3788 void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP, 3789 PragmaIntroducer Introducer, 3790 Token &Tok) { 3791 PP.Lex(Tok); 3792 3793 if (Tok.isNot(tok::l_paren)) { 3794 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) 3795 << "intrinsic"; 3796 return; 3797 } 3798 PP.Lex(Tok); 3799 3800 bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H"); 3801 3802 while (Tok.is(tok::identifier)) { 3803 IdentifierInfo *II = Tok.getIdentifierInfo(); 3804 if (!II->getBuiltinID()) 3805 PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin) 3806 << II << SuggestIntrinH; 3807 3808 PP.Lex(Tok); 3809 if (Tok.isNot(tok::comma)) 3810 break; 3811 PP.Lex(Tok); 3812 } 3813 3814 if (Tok.isNot(tok::r_paren)) { 3815 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) 3816 << "intrinsic"; 3817 return; 3818 } 3819 PP.Lex(Tok); 3820 3821 if (Tok.isNot(tok::eod)) 3822 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 3823 << "intrinsic"; 3824 } 3825 3826 bool Parser::HandlePragmaMSFunction(StringRef PragmaName, 3827 SourceLocation PragmaLocation) { 3828 Token FirstTok = Tok; 3829 3830 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen, 3831 PragmaName)) 3832 return false; 3833 3834 bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H"); 3835 3836 llvm::SmallVector<StringRef> NoBuiltins; 3837 while (Tok.is(tok::identifier)) { 3838 IdentifierInfo *II = Tok.getIdentifierInfo(); 3839 if (!II->getBuiltinID()) 3840 PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin) 3841 << II << SuggestIntrinH; 3842 else 3843 NoBuiltins.emplace_back(II->getName()); 3844 3845 PP.Lex(Tok); 3846 if (Tok.isNot(tok::comma)) 3847 break; 3848 PP.Lex(Tok); // , 3849 } 3850 3851 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen, 3852 PragmaName) || 3853 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol, 3854 PragmaName)) 3855 return false; 3856 3857 Actions.ActOnPragmaMSFunction(FirstTok.getLocation(), NoBuiltins); 3858 return true; 3859 } 3860 3861 // #pragma optimize("gsty", on|off) 3862 bool Parser::HandlePragmaMSOptimize(StringRef PragmaName, 3863 SourceLocation PragmaLocation) { 3864 Token FirstTok = Tok; 3865 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen, 3866 PragmaName)) 3867 return false; 3868 3869 if (Tok.isNot(tok::string_literal)) { 3870 PP.Diag(PragmaLocation, diag::warn_pragma_expected_string) << PragmaName; 3871 return false; 3872 } 3873 ExprResult StringResult = ParseStringLiteralExpression(); 3874 if (StringResult.isInvalid()) 3875 return false; // Already diagnosed. 3876 StringLiteral *OptimizationList = cast<StringLiteral>(StringResult.get()); 3877 if (OptimizationList->getCharByteWidth() != 1) { 3878 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string) 3879 << PragmaName; 3880 return false; 3881 } 3882 3883 if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_comma, 3884 PragmaName)) 3885 return false; 3886 3887 if (Tok.is(tok::eof) || Tok.is(tok::r_paren)) { 3888 PP.Diag(PragmaLocation, diag::warn_pragma_missing_argument) 3889 << PragmaName << /*Expected=*/true << "'on' or 'off'"; 3890 return false; 3891 } 3892 IdentifierInfo *II = Tok.getIdentifierInfo(); 3893 if (!II || (!II->isStr("on") && !II->isStr("off"))) { 3894 PP.Diag(PragmaLocation, diag::warn_pragma_invalid_argument) 3895 << PP.getSpelling(Tok) << PragmaName << /*Expected=*/true 3896 << "'on' or 'off'"; 3897 return false; 3898 } 3899 bool IsOn = II->isStr("on"); 3900 PP.Lex(Tok); 3901 3902 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen, 3903 PragmaName)) 3904 return false; 3905 3906 // TODO: Add support for "sgty" 3907 if (!OptimizationList->getString().empty()) { 3908 PP.Diag(PragmaLocation, diag::warn_pragma_invalid_argument) 3909 << OptimizationList->getString() << PragmaName << /*Expected=*/true 3910 << "\"\""; 3911 return false; 3912 } 3913 3914 if (ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol, 3915 PragmaName)) 3916 return false; 3917 3918 Actions.ActOnPragmaMSOptimize(FirstTok.getLocation(), IsOn); 3919 return true; 3920 } 3921 3922 void PragmaForceCUDAHostDeviceHandler::HandlePragma( 3923 Preprocessor &PP, PragmaIntroducer Introducer, Token &Tok) { 3924 Token FirstTok = Tok; 3925 3926 PP.Lex(Tok); 3927 IdentifierInfo *Info = Tok.getIdentifierInfo(); 3928 if (!Info || (!Info->isStr("begin") && !Info->isStr("end"))) { 3929 PP.Diag(FirstTok.getLocation(), 3930 diag::warn_pragma_force_cuda_host_device_bad_arg); 3931 return; 3932 } 3933 3934 if (Info->isStr("begin")) 3935 Actions.CUDA().PushForceHostDevice(); 3936 else if (!Actions.CUDA().PopForceHostDevice()) 3937 PP.Diag(FirstTok.getLocation(), 3938 diag::err_pragma_cannot_end_force_cuda_host_device); 3939 3940 PP.Lex(Tok); 3941 if (!Tok.is(tok::eod)) 3942 PP.Diag(FirstTok.getLocation(), 3943 diag::warn_pragma_force_cuda_host_device_bad_arg); 3944 } 3945 3946 /// Handle the #pragma clang attribute directive. 3947 /// 3948 /// The syntax is: 3949 /// \code 3950 /// #pragma clang attribute push (attribute, subject-set) 3951 /// #pragma clang attribute push 3952 /// #pragma clang attribute (attribute, subject-set) 3953 /// #pragma clang attribute pop 3954 /// \endcode 3955 /// 3956 /// There are also 'namespace' variants of push and pop directives. The bare 3957 /// '#pragma clang attribute (attribute, subject-set)' version doesn't require a 3958 /// namespace, since it always applies attributes to the most recently pushed 3959 /// group, regardless of namespace. 3960 /// \code 3961 /// #pragma clang attribute namespace.push (attribute, subject-set) 3962 /// #pragma clang attribute namespace.push 3963 /// #pragma clang attribute namespace.pop 3964 /// \endcode 3965 /// 3966 /// The subject-set clause defines the set of declarations which receive the 3967 /// attribute. Its exact syntax is described in the LanguageExtensions document 3968 /// in Clang's documentation. 3969 /// 3970 /// This directive instructs the compiler to begin/finish applying the specified 3971 /// attribute to the set of attribute-specific declarations in the active range 3972 /// of the pragma. 3973 void PragmaAttributeHandler::HandlePragma(Preprocessor &PP, 3974 PragmaIntroducer Introducer, 3975 Token &FirstToken) { 3976 Token Tok; 3977 PP.Lex(Tok); 3978 auto *Info = new (PP.getPreprocessorAllocator()) 3979 PragmaAttributeInfo(AttributesForPragmaAttribute); 3980 3981 // Parse the optional namespace followed by a period. 3982 if (Tok.is(tok::identifier)) { 3983 IdentifierInfo *II = Tok.getIdentifierInfo(); 3984 if (!II->isStr("push") && !II->isStr("pop")) { 3985 Info->Namespace = II; 3986 PP.Lex(Tok); 3987 3988 if (!Tok.is(tok::period)) { 3989 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_period) 3990 << II; 3991 return; 3992 } 3993 PP.Lex(Tok); 3994 } 3995 } 3996 3997 if (!Tok.isOneOf(tok::identifier, tok::l_paren)) { 3998 PP.Diag(Tok.getLocation(), 3999 diag::err_pragma_attribute_expected_push_pop_paren); 4000 return; 4001 } 4002 4003 // Determine what action this pragma clang attribute represents. 4004 if (Tok.is(tok::l_paren)) { 4005 if (Info->Namespace) { 4006 PP.Diag(Tok.getLocation(), 4007 diag::err_pragma_attribute_namespace_on_attribute); 4008 PP.Diag(Tok.getLocation(), 4009 diag::note_pragma_attribute_namespace_on_attribute); 4010 return; 4011 } 4012 Info->Action = PragmaAttributeInfo::Attribute; 4013 } else { 4014 const IdentifierInfo *II = Tok.getIdentifierInfo(); 4015 if (II->isStr("push")) 4016 Info->Action = PragmaAttributeInfo::Push; 4017 else if (II->isStr("pop")) 4018 Info->Action = PragmaAttributeInfo::Pop; 4019 else { 4020 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument) 4021 << PP.getSpelling(Tok); 4022 return; 4023 } 4024 4025 PP.Lex(Tok); 4026 } 4027 4028 // Parse the actual attribute. 4029 if ((Info->Action == PragmaAttributeInfo::Push && Tok.isNot(tok::eod)) || 4030 Info->Action == PragmaAttributeInfo::Attribute) { 4031 if (Tok.isNot(tok::l_paren)) { 4032 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren; 4033 return; 4034 } 4035 PP.Lex(Tok); 4036 4037 // Lex the attribute tokens. 4038 SmallVector<Token, 16> AttributeTokens; 4039 int OpenParens = 1; 4040 while (Tok.isNot(tok::eod)) { 4041 if (Tok.is(tok::l_paren)) 4042 OpenParens++; 4043 else if (Tok.is(tok::r_paren)) { 4044 OpenParens--; 4045 if (OpenParens == 0) 4046 break; 4047 } 4048 4049 AttributeTokens.push_back(Tok); 4050 PP.Lex(Tok); 4051 } 4052 4053 if (AttributeTokens.empty()) { 4054 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute); 4055 return; 4056 } 4057 if (Tok.isNot(tok::r_paren)) { 4058 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren; 4059 return; 4060 } 4061 SourceLocation EndLoc = Tok.getLocation(); 4062 PP.Lex(Tok); 4063 4064 // Terminate the attribute for parsing. 4065 Token EOFTok; 4066 EOFTok.startToken(); 4067 EOFTok.setKind(tok::eof); 4068 EOFTok.setLocation(EndLoc); 4069 AttributeTokens.push_back(EOFTok); 4070 4071 markAsReinjectedForRelexing(AttributeTokens); 4072 Info->Tokens = 4073 llvm::ArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator()); 4074 } 4075 4076 if (Tok.isNot(tok::eod)) 4077 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 4078 << "clang attribute"; 4079 4080 // Generate the annotated pragma token. 4081 auto TokenArray = std::make_unique<Token[]>(1); 4082 TokenArray[0].startToken(); 4083 TokenArray[0].setKind(tok::annot_pragma_attribute); 4084 TokenArray[0].setLocation(FirstToken.getLocation()); 4085 TokenArray[0].setAnnotationEndLoc(FirstToken.getLocation()); 4086 TokenArray[0].setAnnotationValue(static_cast<void *>(Info)); 4087 PP.EnterTokenStream(std::move(TokenArray), 1, 4088 /*DisableMacroExpansion=*/false, /*IsReinject=*/false); 4089 } 4090 4091 // Handle '#pragma clang max_tokens 12345'. 4092 void PragmaMaxTokensHereHandler::HandlePragma(Preprocessor &PP, 4093 PragmaIntroducer Introducer, 4094 Token &Tok) { 4095 PP.Lex(Tok); 4096 if (Tok.is(tok::eod)) { 4097 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument) 4098 << "clang max_tokens_here" << /*Expected=*/true << "integer"; 4099 return; 4100 } 4101 4102 SourceLocation Loc = Tok.getLocation(); 4103 uint64_t MaxTokens; 4104 if (Tok.isNot(tok::numeric_constant) || 4105 !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) { 4106 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer) 4107 << "clang max_tokens_here"; 4108 return; 4109 } 4110 4111 if (Tok.isNot(tok::eod)) { 4112 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 4113 << "clang max_tokens_here"; 4114 return; 4115 } 4116 4117 if (PP.getTokenCount() > MaxTokens) { 4118 PP.Diag(Loc, diag::warn_max_tokens) 4119 << PP.getTokenCount() << (unsigned)MaxTokens; 4120 } 4121 } 4122 4123 // Handle '#pragma clang max_tokens_total 12345'. 4124 void PragmaMaxTokensTotalHandler::HandlePragma(Preprocessor &PP, 4125 PragmaIntroducer Introducer, 4126 Token &Tok) { 4127 PP.Lex(Tok); 4128 if (Tok.is(tok::eod)) { 4129 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument) 4130 << "clang max_tokens_total" << /*Expected=*/true << "integer"; 4131 return; 4132 } 4133 4134 SourceLocation Loc = Tok.getLocation(); 4135 uint64_t MaxTokens; 4136 if (Tok.isNot(tok::numeric_constant) || 4137 !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) { 4138 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer) 4139 << "clang max_tokens_total"; 4140 return; 4141 } 4142 4143 if (Tok.isNot(tok::eod)) { 4144 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 4145 << "clang max_tokens_total"; 4146 return; 4147 } 4148 4149 PP.overrideMaxTokens(MaxTokens, Loc); 4150 } 4151 4152 // Handle '#pragma clang riscv intrinsic vector'. 4153 // '#pragma clang riscv intrinsic sifive_vector'. 4154 void PragmaRISCVHandler::HandlePragma(Preprocessor &PP, 4155 PragmaIntroducer Introducer, 4156 Token &FirstToken) { 4157 Token Tok; 4158 PP.Lex(Tok); 4159 IdentifierInfo *II = Tok.getIdentifierInfo(); 4160 4161 if (!II || !II->isStr("intrinsic")) { 4162 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument) 4163 << PP.getSpelling(Tok) << "riscv" << /*Expected=*/true << "'intrinsic'"; 4164 return; 4165 } 4166 4167 PP.Lex(Tok); 4168 II = Tok.getIdentifierInfo(); 4169 if (!II || !(II->isStr("vector") || II->isStr("sifive_vector"))) { 4170 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument) 4171 << PP.getSpelling(Tok) << "riscv" << /*Expected=*/true 4172 << "'vector' or 'sifive_vector'"; 4173 return; 4174 } 4175 4176 PP.Lex(Tok); 4177 if (Tok.isNot(tok::eod)) { 4178 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 4179 << "clang riscv intrinsic"; 4180 return; 4181 } 4182 4183 if (II->isStr("vector")) 4184 Actions.RISCV().DeclareRVVBuiltins = true; 4185 else if (II->isStr("sifive_vector")) 4186 Actions.RISCV().DeclareSiFiveVectorBuiltins = true; 4187 } 4188