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