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