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