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