clang API Documentation
00001 //===--- ParsePragma.cpp - Language specific pragma parsing ---------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the language specific #pragma handlers. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "RAIIObjectsForParser.h" 00015 #include "clang/AST/ASTContext.h" 00016 #include "clang/Basic/TargetInfo.h" 00017 #include "clang/Lex/Preprocessor.h" 00018 #include "clang/Parse/ParseDiagnostic.h" 00019 #include "clang/Parse/Parser.h" 00020 #include "clang/Sema/LoopHint.h" 00021 #include "clang/Sema/Scope.h" 00022 #include "llvm/ADT/StringSwitch.h" 00023 using namespace clang; 00024 00025 namespace { 00026 00027 struct PragmaAlignHandler : public PragmaHandler { 00028 explicit PragmaAlignHandler() : PragmaHandler("align") {} 00029 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 00030 Token &FirstToken) override; 00031 }; 00032 00033 struct PragmaGCCVisibilityHandler : public PragmaHandler { 00034 explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {} 00035 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 00036 Token &FirstToken) override; 00037 }; 00038 00039 struct PragmaOptionsHandler : public PragmaHandler { 00040 explicit PragmaOptionsHandler() : PragmaHandler("options") {} 00041 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 00042 Token &FirstToken) override; 00043 }; 00044 00045 struct PragmaPackHandler : public PragmaHandler { 00046 explicit PragmaPackHandler() : PragmaHandler("pack") {} 00047 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 00048 Token &FirstToken) override; 00049 }; 00050 00051 struct PragmaMSStructHandler : public PragmaHandler { 00052 explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {} 00053 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 00054 Token &FirstToken) override; 00055 }; 00056 00057 struct PragmaUnusedHandler : public PragmaHandler { 00058 PragmaUnusedHandler() : PragmaHandler("unused") {} 00059 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 00060 Token &FirstToken) override; 00061 }; 00062 00063 struct PragmaWeakHandler : public PragmaHandler { 00064 explicit PragmaWeakHandler() : PragmaHandler("weak") {} 00065 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 00066 Token &FirstToken) override; 00067 }; 00068 00069 struct PragmaRedefineExtnameHandler : public PragmaHandler { 00070 explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {} 00071 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 00072 Token &FirstToken) override; 00073 }; 00074 00075 struct PragmaOpenCLExtensionHandler : public PragmaHandler { 00076 PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {} 00077 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 00078 Token &FirstToken) override; 00079 }; 00080 00081 00082 struct PragmaFPContractHandler : public PragmaHandler { 00083 PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {} 00084 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 00085 Token &FirstToken) override; 00086 }; 00087 00088 struct PragmaNoOpenMPHandler : public PragmaHandler { 00089 PragmaNoOpenMPHandler() : PragmaHandler("omp") { } 00090 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 00091 Token &FirstToken) override; 00092 }; 00093 00094 struct PragmaOpenMPHandler : public PragmaHandler { 00095 PragmaOpenMPHandler() : PragmaHandler("omp") { } 00096 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 00097 Token &FirstToken) override; 00098 }; 00099 00100 /// PragmaCommentHandler - "\#pragma comment ...". 00101 struct PragmaCommentHandler : public PragmaHandler { 00102 PragmaCommentHandler(Sema &Actions) 00103 : PragmaHandler("comment"), Actions(Actions) {} 00104 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 00105 Token &FirstToken) override; 00106 private: 00107 Sema &Actions; 00108 }; 00109 00110 struct PragmaDetectMismatchHandler : public PragmaHandler { 00111 PragmaDetectMismatchHandler(Sema &Actions) 00112 : PragmaHandler("detect_mismatch"), Actions(Actions) {} 00113 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 00114 Token &FirstToken) override; 00115 private: 00116 Sema &Actions; 00117 }; 00118 00119 struct PragmaMSPointersToMembers : public PragmaHandler { 00120 explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {} 00121 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 00122 Token &FirstToken) override; 00123 }; 00124 00125 struct PragmaMSVtorDisp : public PragmaHandler { 00126 explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {} 00127 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 00128 Token &FirstToken) override; 00129 }; 00130 00131 struct PragmaMSPragma : public PragmaHandler { 00132 explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {} 00133 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 00134 Token &FirstToken) override; 00135 }; 00136 00137 /// PragmaOptimizeHandler - "\#pragma clang optimize on/off". 00138 struct PragmaOptimizeHandler : public PragmaHandler { 00139 PragmaOptimizeHandler(Sema &S) 00140 : PragmaHandler("optimize"), Actions(S) {} 00141 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 00142 Token &FirstToken) override; 00143 private: 00144 Sema &Actions; 00145 }; 00146 00147 struct PragmaLoopHintHandler : public PragmaHandler { 00148 PragmaLoopHintHandler() : PragmaHandler("loop") {} 00149 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 00150 Token &FirstToken) override; 00151 }; 00152 00153 struct PragmaUnrollHintHandler : public PragmaHandler { 00154 PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {} 00155 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 00156 Token &FirstToken) override; 00157 }; 00158 00159 } // end namespace 00160 00161 void Parser::initializePragmaHandlers() { 00162 AlignHandler.reset(new PragmaAlignHandler()); 00163 PP.AddPragmaHandler(AlignHandler.get()); 00164 00165 GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler()); 00166 PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get()); 00167 00168 OptionsHandler.reset(new PragmaOptionsHandler()); 00169 PP.AddPragmaHandler(OptionsHandler.get()); 00170 00171 PackHandler.reset(new PragmaPackHandler()); 00172 PP.AddPragmaHandler(PackHandler.get()); 00173 00174 MSStructHandler.reset(new PragmaMSStructHandler()); 00175 PP.AddPragmaHandler(MSStructHandler.get()); 00176 00177 UnusedHandler.reset(new PragmaUnusedHandler()); 00178 PP.AddPragmaHandler(UnusedHandler.get()); 00179 00180 WeakHandler.reset(new PragmaWeakHandler()); 00181 PP.AddPragmaHandler(WeakHandler.get()); 00182 00183 RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler()); 00184 PP.AddPragmaHandler(RedefineExtnameHandler.get()); 00185 00186 FPContractHandler.reset(new PragmaFPContractHandler()); 00187 PP.AddPragmaHandler("STDC", FPContractHandler.get()); 00188 00189 if (getLangOpts().OpenCL) { 00190 OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler()); 00191 PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get()); 00192 00193 PP.AddPragmaHandler("OPENCL", FPContractHandler.get()); 00194 } 00195 if (getLangOpts().OpenMP) 00196 OpenMPHandler.reset(new PragmaOpenMPHandler()); 00197 else 00198 OpenMPHandler.reset(new PragmaNoOpenMPHandler()); 00199 PP.AddPragmaHandler(OpenMPHandler.get()); 00200 00201 if (getLangOpts().MicrosoftExt) { 00202 MSCommentHandler.reset(new PragmaCommentHandler(Actions)); 00203 PP.AddPragmaHandler(MSCommentHandler.get()); 00204 MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions)); 00205 PP.AddPragmaHandler(MSDetectMismatchHandler.get()); 00206 MSPointersToMembers.reset(new PragmaMSPointersToMembers()); 00207 PP.AddPragmaHandler(MSPointersToMembers.get()); 00208 MSVtorDisp.reset(new PragmaMSVtorDisp()); 00209 PP.AddPragmaHandler(MSVtorDisp.get()); 00210 MSInitSeg.reset(new PragmaMSPragma("init_seg")); 00211 PP.AddPragmaHandler(MSInitSeg.get()); 00212 MSDataSeg.reset(new PragmaMSPragma("data_seg")); 00213 PP.AddPragmaHandler(MSDataSeg.get()); 00214 MSBSSSeg.reset(new PragmaMSPragma("bss_seg")); 00215 PP.AddPragmaHandler(MSBSSSeg.get()); 00216 MSConstSeg.reset(new PragmaMSPragma("const_seg")); 00217 PP.AddPragmaHandler(MSConstSeg.get()); 00218 MSCodeSeg.reset(new PragmaMSPragma("code_seg")); 00219 PP.AddPragmaHandler(MSCodeSeg.get()); 00220 MSSection.reset(new PragmaMSPragma("section")); 00221 PP.AddPragmaHandler(MSSection.get()); 00222 } 00223 00224 OptimizeHandler.reset(new PragmaOptimizeHandler(Actions)); 00225 PP.AddPragmaHandler("clang", OptimizeHandler.get()); 00226 00227 LoopHintHandler.reset(new PragmaLoopHintHandler()); 00228 PP.AddPragmaHandler("clang", LoopHintHandler.get()); 00229 00230 UnrollHintHandler.reset(new PragmaUnrollHintHandler("unroll")); 00231 PP.AddPragmaHandler(UnrollHintHandler.get()); 00232 00233 NoUnrollHintHandler.reset(new PragmaUnrollHintHandler("nounroll")); 00234 PP.AddPragmaHandler(NoUnrollHintHandler.get()); 00235 } 00236 00237 void Parser::resetPragmaHandlers() { 00238 // Remove the pragma handlers we installed. 00239 PP.RemovePragmaHandler(AlignHandler.get()); 00240 AlignHandler.reset(); 00241 PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get()); 00242 GCCVisibilityHandler.reset(); 00243 PP.RemovePragmaHandler(OptionsHandler.get()); 00244 OptionsHandler.reset(); 00245 PP.RemovePragmaHandler(PackHandler.get()); 00246 PackHandler.reset(); 00247 PP.RemovePragmaHandler(MSStructHandler.get()); 00248 MSStructHandler.reset(); 00249 PP.RemovePragmaHandler(UnusedHandler.get()); 00250 UnusedHandler.reset(); 00251 PP.RemovePragmaHandler(WeakHandler.get()); 00252 WeakHandler.reset(); 00253 PP.RemovePragmaHandler(RedefineExtnameHandler.get()); 00254 RedefineExtnameHandler.reset(); 00255 00256 if (getLangOpts().OpenCL) { 00257 PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get()); 00258 OpenCLExtensionHandler.reset(); 00259 PP.RemovePragmaHandler("OPENCL", FPContractHandler.get()); 00260 } 00261 PP.RemovePragmaHandler(OpenMPHandler.get()); 00262 OpenMPHandler.reset(); 00263 00264 if (getLangOpts().MicrosoftExt) { 00265 PP.RemovePragmaHandler(MSCommentHandler.get()); 00266 MSCommentHandler.reset(); 00267 PP.RemovePragmaHandler(MSDetectMismatchHandler.get()); 00268 MSDetectMismatchHandler.reset(); 00269 PP.RemovePragmaHandler(MSPointersToMembers.get()); 00270 MSPointersToMembers.reset(); 00271 PP.RemovePragmaHandler(MSVtorDisp.get()); 00272 MSVtorDisp.reset(); 00273 PP.RemovePragmaHandler(MSInitSeg.get()); 00274 MSInitSeg.reset(); 00275 PP.RemovePragmaHandler(MSDataSeg.get()); 00276 MSDataSeg.reset(); 00277 PP.RemovePragmaHandler(MSBSSSeg.get()); 00278 MSBSSSeg.reset(); 00279 PP.RemovePragmaHandler(MSConstSeg.get()); 00280 MSConstSeg.reset(); 00281 PP.RemovePragmaHandler(MSCodeSeg.get()); 00282 MSCodeSeg.reset(); 00283 PP.RemovePragmaHandler(MSSection.get()); 00284 MSSection.reset(); 00285 } 00286 00287 PP.RemovePragmaHandler("STDC", FPContractHandler.get()); 00288 FPContractHandler.reset(); 00289 00290 PP.RemovePragmaHandler("clang", OptimizeHandler.get()); 00291 OptimizeHandler.reset(); 00292 00293 PP.RemovePragmaHandler("clang", LoopHintHandler.get()); 00294 LoopHintHandler.reset(); 00295 00296 PP.RemovePragmaHandler(UnrollHintHandler.get()); 00297 UnrollHintHandler.reset(); 00298 00299 PP.RemovePragmaHandler(NoUnrollHintHandler.get()); 00300 NoUnrollHintHandler.reset(); 00301 } 00302 00303 /// \brief Handle the annotation token produced for #pragma unused(...) 00304 /// 00305 /// Each annot_pragma_unused is followed by the argument token so e.g. 00306 /// "#pragma unused(x,y)" becomes: 00307 /// annot_pragma_unused 'x' annot_pragma_unused 'y' 00308 void Parser::HandlePragmaUnused() { 00309 assert(Tok.is(tok::annot_pragma_unused)); 00310 SourceLocation UnusedLoc = ConsumeToken(); 00311 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc); 00312 ConsumeToken(); // The argument token. 00313 } 00314 00315 void Parser::HandlePragmaVisibility() { 00316 assert(Tok.is(tok::annot_pragma_vis)); 00317 const IdentifierInfo *VisType = 00318 static_cast<IdentifierInfo *>(Tok.getAnnotationValue()); 00319 SourceLocation VisLoc = ConsumeToken(); 00320 Actions.ActOnPragmaVisibility(VisType, VisLoc); 00321 } 00322 00323 struct PragmaPackInfo { 00324 Sema::PragmaPackKind Kind; 00325 IdentifierInfo *Name; 00326 Token Alignment; 00327 SourceLocation LParenLoc; 00328 SourceLocation RParenLoc; 00329 }; 00330 00331 void Parser::HandlePragmaPack() { 00332 assert(Tok.is(tok::annot_pragma_pack)); 00333 PragmaPackInfo *Info = 00334 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue()); 00335 SourceLocation PragmaLoc = ConsumeToken(); 00336 ExprResult Alignment; 00337 if (Info->Alignment.is(tok::numeric_constant)) { 00338 Alignment = Actions.ActOnNumericConstant(Info->Alignment); 00339 if (Alignment.isInvalid()) 00340 return; 00341 } 00342 Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc, 00343 Info->LParenLoc, Info->RParenLoc); 00344 } 00345 00346 void Parser::HandlePragmaMSStruct() { 00347 assert(Tok.is(tok::annot_pragma_msstruct)); 00348 Sema::PragmaMSStructKind Kind = 00349 static_cast<Sema::PragmaMSStructKind>( 00350 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); 00351 Actions.ActOnPragmaMSStruct(Kind); 00352 ConsumeToken(); // The annotation token. 00353 } 00354 00355 void Parser::HandlePragmaAlign() { 00356 assert(Tok.is(tok::annot_pragma_align)); 00357 Sema::PragmaOptionsAlignKind Kind = 00358 static_cast<Sema::PragmaOptionsAlignKind>( 00359 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); 00360 SourceLocation PragmaLoc = ConsumeToken(); 00361 Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc); 00362 } 00363 00364 void Parser::HandlePragmaWeak() { 00365 assert(Tok.is(tok::annot_pragma_weak)); 00366 SourceLocation PragmaLoc = ConsumeToken(); 00367 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc, 00368 Tok.getLocation()); 00369 ConsumeToken(); // The weak name. 00370 } 00371 00372 void Parser::HandlePragmaWeakAlias() { 00373 assert(Tok.is(tok::annot_pragma_weakalias)); 00374 SourceLocation PragmaLoc = ConsumeToken(); 00375 IdentifierInfo *WeakName = Tok.getIdentifierInfo(); 00376 SourceLocation WeakNameLoc = Tok.getLocation(); 00377 ConsumeToken(); 00378 IdentifierInfo *AliasName = Tok.getIdentifierInfo(); 00379 SourceLocation AliasNameLoc = Tok.getLocation(); 00380 ConsumeToken(); 00381 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc, 00382 WeakNameLoc, AliasNameLoc); 00383 00384 } 00385 00386 void Parser::HandlePragmaRedefineExtname() { 00387 assert(Tok.is(tok::annot_pragma_redefine_extname)); 00388 SourceLocation RedefLoc = ConsumeToken(); 00389 IdentifierInfo *RedefName = Tok.getIdentifierInfo(); 00390 SourceLocation RedefNameLoc = Tok.getLocation(); 00391 ConsumeToken(); 00392 IdentifierInfo *AliasName = Tok.getIdentifierInfo(); 00393 SourceLocation AliasNameLoc = Tok.getLocation(); 00394 ConsumeToken(); 00395 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc, 00396 RedefNameLoc, AliasNameLoc); 00397 } 00398 00399 void Parser::HandlePragmaFPContract() { 00400 assert(Tok.is(tok::annot_pragma_fp_contract)); 00401 tok::OnOffSwitch OOS = 00402 static_cast<tok::OnOffSwitch>( 00403 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); 00404 Actions.ActOnPragmaFPContract(OOS); 00405 ConsumeToken(); // The annotation token. 00406 } 00407 00408 StmtResult Parser::HandlePragmaCaptured() 00409 { 00410 assert(Tok.is(tok::annot_pragma_captured)); 00411 ConsumeToken(); 00412 00413 if (Tok.isNot(tok::l_brace)) { 00414 PP.Diag(Tok, diag::err_expected) << tok::l_brace; 00415 return StmtError(); 00416 } 00417 00418 SourceLocation Loc = Tok.getLocation(); 00419 00420 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope); 00421 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default, 00422 /*NumParams=*/1); 00423 00424 StmtResult R = ParseCompoundStatement(); 00425 CapturedRegionScope.Exit(); 00426 00427 if (R.isInvalid()) { 00428 Actions.ActOnCapturedRegionError(); 00429 return StmtError(); 00430 } 00431 00432 return Actions.ActOnCapturedRegionEnd(R.get()); 00433 } 00434 00435 namespace { 00436 typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData; 00437 } 00438 00439 void Parser::HandlePragmaOpenCLExtension() { 00440 assert(Tok.is(tok::annot_pragma_opencl_extension)); 00441 OpenCLExtData data = 00442 OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue()); 00443 unsigned state = data.getInt(); 00444 IdentifierInfo *ename = data.getPointer(); 00445 SourceLocation NameLoc = Tok.getLocation(); 00446 ConsumeToken(); // The annotation token. 00447 00448 OpenCLOptions &f = Actions.getOpenCLOptions(); 00449 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions, 00450 // overriding all previously issued extension directives, but only if the 00451 // behavior is set to disable." 00452 if (state == 0 && ename->isStr("all")) { 00453 #define OPENCLEXT(nm) f.nm = 0; 00454 #include "clang/Basic/OpenCLExtensions.def" 00455 } 00456 #define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; } 00457 #include "clang/Basic/OpenCLExtensions.def" 00458 else { 00459 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename; 00460 return; 00461 } 00462 } 00463 00464 void Parser::HandlePragmaMSPointersToMembers() { 00465 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members)); 00466 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod = 00467 static_cast<LangOptions::PragmaMSPointersToMembersKind>( 00468 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); 00469 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token. 00470 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc); 00471 } 00472 00473 void Parser::HandlePragmaMSVtorDisp() { 00474 assert(Tok.is(tok::annot_pragma_ms_vtordisp)); 00475 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()); 00476 Sema::PragmaVtorDispKind Kind = 00477 static_cast<Sema::PragmaVtorDispKind>((Value >> 16) & 0xFFFF); 00478 MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF); 00479 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token. 00480 Actions.ActOnPragmaMSVtorDisp(Kind, PragmaLoc, Mode); 00481 } 00482 00483 void Parser::HandlePragmaMSPragma() { 00484 assert(Tok.is(tok::annot_pragma_ms_pragma)); 00485 // Grab the tokens out of the annotation and enter them into the stream. 00486 auto TheTokens = (std::pair<Token*, size_t> *)Tok.getAnnotationValue(); 00487 PP.EnterTokenStream(TheTokens->first, TheTokens->second, true, true); 00488 SourceLocation PragmaLocation = ConsumeToken(); // The annotation token. 00489 assert(Tok.isAnyIdentifier()); 00490 StringRef PragmaName = Tok.getIdentifierInfo()->getName(); 00491 PP.Lex(Tok); // pragma kind 00492 00493 // Figure out which #pragma we're dealing with. The switch has no default 00494 // because lex shouldn't emit the annotation token for unrecognized pragmas. 00495 typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation); 00496 PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName) 00497 .Case("data_seg", &Parser::HandlePragmaMSSegment) 00498 .Case("bss_seg", &Parser::HandlePragmaMSSegment) 00499 .Case("const_seg", &Parser::HandlePragmaMSSegment) 00500 .Case("code_seg", &Parser::HandlePragmaMSSegment) 00501 .Case("section", &Parser::HandlePragmaMSSection) 00502 .Case("init_seg", &Parser::HandlePragmaMSInitSeg); 00503 00504 if (!(this->*Handler)(PragmaName, PragmaLocation)) { 00505 // Pragma handling failed, and has been diagnosed. Slurp up the tokens 00506 // until eof (really end of line) to prevent follow-on errors. 00507 while (Tok.isNot(tok::eof)) 00508 PP.Lex(Tok); 00509 PP.Lex(Tok); 00510 } 00511 } 00512 00513 bool Parser::HandlePragmaMSSection(StringRef PragmaName, 00514 SourceLocation PragmaLocation) { 00515 if (Tok.isNot(tok::l_paren)) { 00516 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName; 00517 return false; 00518 } 00519 PP.Lex(Tok); // ( 00520 // Parsing code for pragma section 00521 if (Tok.isNot(tok::string_literal)) { 00522 PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name) 00523 << PragmaName; 00524 return false; 00525 } 00526 ExprResult StringResult = ParseStringLiteralExpression(); 00527 if (StringResult.isInvalid()) 00528 return false; // Already diagnosed. 00529 StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get()); 00530 if (SegmentName->getCharByteWidth() != 1) { 00531 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string) 00532 << PragmaName; 00533 return false; 00534 } 00535 int SectionFlags = ASTContext::PSF_Read; 00536 bool SectionFlagsAreDefault = true; 00537 while (Tok.is(tok::comma)) { 00538 PP.Lex(Tok); // , 00539 // Ignore "long" and "short". 00540 // They are undocumented, but widely used, section attributes which appear 00541 // to do nothing. 00542 if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) { 00543 PP.Lex(Tok); // long/short 00544 continue; 00545 } 00546 00547 if (!Tok.isAnyIdentifier()) { 00548 PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren) 00549 << PragmaName; 00550 return false; 00551 } 00552 ASTContext::PragmaSectionFlag Flag = 00553 llvm::StringSwitch<ASTContext::PragmaSectionFlag>( 00554 Tok.getIdentifierInfo()->getName()) 00555 .Case("read", ASTContext::PSF_Read) 00556 .Case("write", ASTContext::PSF_Write) 00557 .Case("execute", ASTContext::PSF_Execute) 00558 .Case("shared", ASTContext::PSF_Invalid) 00559 .Case("nopage", ASTContext::PSF_Invalid) 00560 .Case("nocache", ASTContext::PSF_Invalid) 00561 .Case("discard", ASTContext::PSF_Invalid) 00562 .Case("remove", ASTContext::PSF_Invalid) 00563 .Default(ASTContext::PSF_None); 00564 if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) { 00565 PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None 00566 ? diag::warn_pragma_invalid_specific_action 00567 : diag::warn_pragma_unsupported_action) 00568 << PragmaName << Tok.getIdentifierInfo()->getName(); 00569 return false; 00570 } 00571 SectionFlags |= Flag; 00572 SectionFlagsAreDefault = false; 00573 PP.Lex(Tok); // Identifier 00574 } 00575 // If no section attributes are specified, the section will be marked as 00576 // read/write. 00577 if (SectionFlagsAreDefault) 00578 SectionFlags |= ASTContext::PSF_Write; 00579 if (Tok.isNot(tok::r_paren)) { 00580 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName; 00581 return false; 00582 } 00583 PP.Lex(Tok); // ) 00584 if (Tok.isNot(tok::eof)) { 00585 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol) 00586 << PragmaName; 00587 return false; 00588 } 00589 PP.Lex(Tok); // eof 00590 Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName); 00591 return true; 00592 } 00593 00594 bool Parser::HandlePragmaMSSegment(StringRef PragmaName, 00595 SourceLocation PragmaLocation) { 00596 if (Tok.isNot(tok::l_paren)) { 00597 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName; 00598 return false; 00599 } 00600 PP.Lex(Tok); // ( 00601 Sema::PragmaMsStackAction Action = Sema::PSK_Reset; 00602 StringRef SlotLabel; 00603 if (Tok.isAnyIdentifier()) { 00604 StringRef PushPop = Tok.getIdentifierInfo()->getName(); 00605 if (PushPop == "push") 00606 Action = Sema::PSK_Push; 00607 else if (PushPop == "pop") 00608 Action = Sema::PSK_Pop; 00609 else { 00610 PP.Diag(PragmaLocation, 00611 diag::warn_pragma_expected_section_push_pop_or_name) 00612 << PragmaName; 00613 return false; 00614 } 00615 if (Action != Sema::PSK_Reset) { 00616 PP.Lex(Tok); // push | pop 00617 if (Tok.is(tok::comma)) { 00618 PP.Lex(Tok); // , 00619 // If we've got a comma, we either need a label or a string. 00620 if (Tok.isAnyIdentifier()) { 00621 SlotLabel = Tok.getIdentifierInfo()->getName(); 00622 PP.Lex(Tok); // identifier 00623 if (Tok.is(tok::comma)) 00624 PP.Lex(Tok); 00625 else if (Tok.isNot(tok::r_paren)) { 00626 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) 00627 << PragmaName; 00628 return false; 00629 } 00630 } 00631 } else if (Tok.isNot(tok::r_paren)) { 00632 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName; 00633 return false; 00634 } 00635 } 00636 } 00637 // Grab the string literal for our section name. 00638 StringLiteral *SegmentName = nullptr; 00639 if (Tok.isNot(tok::r_paren)) { 00640 if (Tok.isNot(tok::string_literal)) { 00641 unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ? 00642 diag::warn_pragma_expected_section_name : 00643 diag::warn_pragma_expected_section_label_or_name : 00644 diag::warn_pragma_expected_section_push_pop_or_name; 00645 PP.Diag(PragmaLocation, DiagID) << PragmaName; 00646 return false; 00647 } 00648 ExprResult StringResult = ParseStringLiteralExpression(); 00649 if (StringResult.isInvalid()) 00650 return false; // Already diagnosed. 00651 SegmentName = cast<StringLiteral>(StringResult.get()); 00652 if (SegmentName->getCharByteWidth() != 1) { 00653 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string) 00654 << PragmaName; 00655 return false; 00656 } 00657 // Setting section "" has no effect 00658 if (SegmentName->getLength()) 00659 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set); 00660 } 00661 if (Tok.isNot(tok::r_paren)) { 00662 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName; 00663 return false; 00664 } 00665 PP.Lex(Tok); // ) 00666 if (Tok.isNot(tok::eof)) { 00667 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol) 00668 << PragmaName; 00669 return false; 00670 } 00671 PP.Lex(Tok); // eof 00672 Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel, 00673 SegmentName, PragmaName); 00674 return true; 00675 } 00676 00677 // #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} ) 00678 bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName, 00679 SourceLocation PragmaLocation) { 00680 if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) { 00681 PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target); 00682 return false; 00683 } 00684 00685 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen, 00686 PragmaName)) 00687 return false; 00688 00689 // Parse either the known section names or the string section name. 00690 StringLiteral *SegmentName = nullptr; 00691 if (Tok.isAnyIdentifier()) { 00692 auto *II = Tok.getIdentifierInfo(); 00693 StringRef Section = llvm::StringSwitch<StringRef>(II->getName()) 00694 .Case("compiler", "\".CRT$XCC\"") 00695 .Case("lib", "\".CRT$XCL\"") 00696 .Case("user", "\".CRT$XCU\"") 00697 .Default(""); 00698 00699 if (!Section.empty()) { 00700 // Pretend the user wrote the appropriate string literal here. 00701 Token Toks[1]; 00702 Toks[0].startToken(); 00703 Toks[0].setKind(tok::string_literal); 00704 Toks[0].setLocation(Tok.getLocation()); 00705 Toks[0].setLiteralData(Section.data()); 00706 Toks[0].setLength(Section.size()); 00707 SegmentName = 00708 cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get()); 00709 PP.Lex(Tok); 00710 } 00711 } else if (Tok.is(tok::string_literal)) { 00712 ExprResult StringResult = ParseStringLiteralExpression(); 00713 if (StringResult.isInvalid()) 00714 return false; 00715 SegmentName = cast<StringLiteral>(StringResult.get()); 00716 if (SegmentName->getCharByteWidth() != 1) { 00717 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string) 00718 << PragmaName; 00719 return false; 00720 } 00721 // FIXME: Add support for the '[, func-name]' part of the pragma. 00722 } 00723 00724 if (!SegmentName) { 00725 PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName; 00726 return false; 00727 } 00728 00729 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen, 00730 PragmaName) || 00731 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol, 00732 PragmaName)) 00733 return false; 00734 00735 Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName); 00736 return true; 00737 } 00738 00739 struct PragmaLoopHintInfo { 00740 Token PragmaName; 00741 Token Option; 00742 Token *Toks; 00743 size_t TokSize; 00744 PragmaLoopHintInfo() : Toks(nullptr), TokSize(0) {} 00745 }; 00746 00747 static std::string PragmaLoopHintString(Token PragmaName, Token Option) { 00748 std::string PragmaString; 00749 if (PragmaName.getIdentifierInfo()->getName() == "loop") { 00750 PragmaString = "clang loop "; 00751 PragmaString += Option.getIdentifierInfo()->getName(); 00752 } else { 00753 assert(PragmaName.getIdentifierInfo()->getName() == "unroll" && 00754 "Unexpected pragma name"); 00755 PragmaString = "unroll"; 00756 } 00757 return PragmaString; 00758 } 00759 00760 bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { 00761 assert(Tok.is(tok::annot_pragma_loop_hint)); 00762 PragmaLoopHintInfo *Info = 00763 static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue()); 00764 00765 IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo(); 00766 Hint.PragmaNameLoc = IdentifierLoc::create( 00767 Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo); 00768 00769 // It is possible that the loop hint has no option identifier, such as 00770 // #pragma unroll(4). 00771 IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier) 00772 ? Info->Option.getIdentifierInfo() 00773 : nullptr; 00774 Hint.OptionLoc = IdentifierLoc::create( 00775 Actions.Context, Info->Option.getLocation(), OptionInfo); 00776 00777 Token *Toks = Info->Toks; 00778 size_t TokSize = Info->TokSize; 00779 00780 // Return a valid hint if pragma unroll or nounroll were specified 00781 // without an argument. 00782 bool PragmaUnroll = PragmaNameInfo->getName() == "unroll"; 00783 bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll"; 00784 if (TokSize == 0 && (PragmaUnroll || PragmaNoUnroll)) { 00785 ConsumeToken(); // The annotation token. 00786 Hint.Range = Info->PragmaName.getLocation(); 00787 return true; 00788 } 00789 00790 // The constant expression is always followed by an eof token, which increases 00791 // the TokSize by 1. 00792 assert(TokSize > 0 && 00793 "PragmaLoopHintInfo::Toks must contain at least one token."); 00794 00795 // If no option is specified the argument is assumed to be a constant expr. 00796 bool StateOption = false; 00797 if (OptionInfo) { // Pragma unroll does not specify an option. 00798 StateOption = llvm::StringSwitch<bool>(OptionInfo->getName()) 00799 .Case("vectorize", true) 00800 .Case("interleave", true) 00801 .Case("unroll", true) 00802 .Default(false); 00803 } 00804 00805 // Verify loop hint has an argument. 00806 if (Toks[0].is(tok::eof)) { 00807 ConsumeToken(); // The annotation token. 00808 Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument) 00809 << /*StateArgument=*/StateOption << /*FullKeyword=*/PragmaUnroll; 00810 return false; 00811 } 00812 00813 // Validate the argument. 00814 if (StateOption) { 00815 ConsumeToken(); // The annotation token. 00816 bool OptionUnroll = OptionInfo->isStr("unroll"); 00817 SourceLocation StateLoc = Toks[0].getLocation(); 00818 IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo(); 00819 if (!StateInfo || ((OptionUnroll ? !StateInfo->isStr("full") 00820 : !StateInfo->isStr("enable")) && 00821 !StateInfo->isStr("disable"))) { 00822 Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword) 00823 << /*FullKeyword=*/OptionUnroll; 00824 return false; 00825 } 00826 if (TokSize > 2) 00827 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 00828 << PragmaLoopHintString(Info->PragmaName, Info->Option); 00829 Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo); 00830 } else { 00831 // Enter constant expression including eof terminator into token stream. 00832 PP.EnterTokenStream(Toks, TokSize, /*DisableMacroExpansion=*/false, 00833 /*OwnsTokens=*/false); 00834 ConsumeToken(); // The annotation token. 00835 00836 ExprResult R = ParseConstantExpression(); 00837 00838 // Tokens following an error in an ill-formed constant expression will 00839 // remain in the token stream and must be removed. 00840 if (Tok.isNot(tok::eof)) { 00841 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 00842 << PragmaLoopHintString(Info->PragmaName, Info->Option); 00843 while (Tok.isNot(tok::eof)) 00844 ConsumeAnyToken(); 00845 } 00846 00847 ConsumeToken(); // Consume the constant expression eof terminator. 00848 00849 if (R.isInvalid() || 00850 Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation())) 00851 return false; 00852 00853 // Argument is a constant expression with an integer type. 00854 Hint.ValueExpr = R.get(); 00855 } 00856 00857 Hint.Range = SourceRange(Info->PragmaName.getLocation(), 00858 Info->Toks[TokSize - 1].getLocation()); 00859 return true; 00860 } 00861 00862 // #pragma GCC visibility comes in two variants: 00863 // 'push' '(' [visibility] ')' 00864 // 'pop' 00865 void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP, 00866 PragmaIntroducerKind Introducer, 00867 Token &VisTok) { 00868 SourceLocation VisLoc = VisTok.getLocation(); 00869 00870 Token Tok; 00871 PP.LexUnexpandedToken(Tok); 00872 00873 const IdentifierInfo *PushPop = Tok.getIdentifierInfo(); 00874 00875 const IdentifierInfo *VisType; 00876 if (PushPop && PushPop->isStr("pop")) { 00877 VisType = nullptr; 00878 } else if (PushPop && PushPop->isStr("push")) { 00879 PP.LexUnexpandedToken(Tok); 00880 if (Tok.isNot(tok::l_paren)) { 00881 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) 00882 << "visibility"; 00883 return; 00884 } 00885 PP.LexUnexpandedToken(Tok); 00886 VisType = Tok.getIdentifierInfo(); 00887 if (!VisType) { 00888 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 00889 << "visibility"; 00890 return; 00891 } 00892 PP.LexUnexpandedToken(Tok); 00893 if (Tok.isNot(tok::r_paren)) { 00894 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) 00895 << "visibility"; 00896 return; 00897 } 00898 } else { 00899 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 00900 << "visibility"; 00901 return; 00902 } 00903 PP.LexUnexpandedToken(Tok); 00904 if (Tok.isNot(tok::eod)) { 00905 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 00906 << "visibility"; 00907 return; 00908 } 00909 00910 Token *Toks = new Token[1]; 00911 Toks[0].startToken(); 00912 Toks[0].setKind(tok::annot_pragma_vis); 00913 Toks[0].setLocation(VisLoc); 00914 Toks[0].setAnnotationValue( 00915 const_cast<void*>(static_cast<const void*>(VisType))); 00916 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, 00917 /*OwnsTokens=*/true); 00918 } 00919 00920 // #pragma pack(...) comes in the following delicious flavors: 00921 // pack '(' [integer] ')' 00922 // pack '(' 'show' ')' 00923 // pack '(' ('push' | 'pop') [',' identifier] [, integer] ')' 00924 void PragmaPackHandler::HandlePragma(Preprocessor &PP, 00925 PragmaIntroducerKind Introducer, 00926 Token &PackTok) { 00927 SourceLocation PackLoc = PackTok.getLocation(); 00928 00929 Token Tok; 00930 PP.Lex(Tok); 00931 if (Tok.isNot(tok::l_paren)) { 00932 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack"; 00933 return; 00934 } 00935 00936 Sema::PragmaPackKind Kind = Sema::PPK_Default; 00937 IdentifierInfo *Name = nullptr; 00938 Token Alignment; 00939 Alignment.startToken(); 00940 SourceLocation LParenLoc = Tok.getLocation(); 00941 PP.Lex(Tok); 00942 if (Tok.is(tok::numeric_constant)) { 00943 Alignment = Tok; 00944 00945 PP.Lex(Tok); 00946 00947 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting 00948 // the push/pop stack. 00949 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4) 00950 if (PP.getLangOpts().ApplePragmaPack) 00951 Kind = Sema::PPK_Push; 00952 } else if (Tok.is(tok::identifier)) { 00953 const IdentifierInfo *II = Tok.getIdentifierInfo(); 00954 if (II->isStr("show")) { 00955 Kind = Sema::PPK_Show; 00956 PP.Lex(Tok); 00957 } else { 00958 if (II->isStr("push")) { 00959 Kind = Sema::PPK_Push; 00960 } else if (II->isStr("pop")) { 00961 Kind = Sema::PPK_Pop; 00962 } else { 00963 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack"; 00964 return; 00965 } 00966 PP.Lex(Tok); 00967 00968 if (Tok.is(tok::comma)) { 00969 PP.Lex(Tok); 00970 00971 if (Tok.is(tok::numeric_constant)) { 00972 Alignment = Tok; 00973 00974 PP.Lex(Tok); 00975 } else if (Tok.is(tok::identifier)) { 00976 Name = Tok.getIdentifierInfo(); 00977 PP.Lex(Tok); 00978 00979 if (Tok.is(tok::comma)) { 00980 PP.Lex(Tok); 00981 00982 if (Tok.isNot(tok::numeric_constant)) { 00983 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed); 00984 return; 00985 } 00986 00987 Alignment = Tok; 00988 00989 PP.Lex(Tok); 00990 } 00991 } else { 00992 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed); 00993 return; 00994 } 00995 } 00996 } 00997 } else if (PP.getLangOpts().ApplePragmaPack) { 00998 // In MSVC/gcc, #pragma pack() resets the alignment without affecting 00999 // the push/pop stack. 01000 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop). 01001 Kind = Sema::PPK_Pop; 01002 } 01003 01004 if (Tok.isNot(tok::r_paren)) { 01005 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack"; 01006 return; 01007 } 01008 01009 SourceLocation RParenLoc = Tok.getLocation(); 01010 PP.Lex(Tok); 01011 if (Tok.isNot(tok::eod)) { 01012 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack"; 01013 return; 01014 } 01015 01016 PragmaPackInfo *Info = 01017 (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate( 01018 sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>()); 01019 new (Info) PragmaPackInfo(); 01020 Info->Kind = Kind; 01021 Info->Name = Name; 01022 Info->Alignment = Alignment; 01023 Info->LParenLoc = LParenLoc; 01024 Info->RParenLoc = RParenLoc; 01025 01026 Token *Toks = 01027 (Token*) PP.getPreprocessorAllocator().Allocate( 01028 sizeof(Token) * 1, llvm::alignOf<Token>()); 01029 new (Toks) Token(); 01030 Toks[0].startToken(); 01031 Toks[0].setKind(tok::annot_pragma_pack); 01032 Toks[0].setLocation(PackLoc); 01033 Toks[0].setAnnotationValue(static_cast<void*>(Info)); 01034 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, 01035 /*OwnsTokens=*/false); 01036 } 01037 01038 // #pragma ms_struct on 01039 // #pragma ms_struct off 01040 void PragmaMSStructHandler::HandlePragma(Preprocessor &PP, 01041 PragmaIntroducerKind Introducer, 01042 Token &MSStructTok) { 01043 Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF; 01044 01045 Token Tok; 01046 PP.Lex(Tok); 01047 if (Tok.isNot(tok::identifier)) { 01048 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct); 01049 return; 01050 } 01051 const IdentifierInfo *II = Tok.getIdentifierInfo(); 01052 if (II->isStr("on")) { 01053 Kind = Sema::PMSST_ON; 01054 PP.Lex(Tok); 01055 } 01056 else if (II->isStr("off") || II->isStr("reset")) 01057 PP.Lex(Tok); 01058 else { 01059 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct); 01060 return; 01061 } 01062 01063 if (Tok.isNot(tok::eod)) { 01064 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 01065 << "ms_struct"; 01066 return; 01067 } 01068 01069 Token *Toks = 01070 (Token*) PP.getPreprocessorAllocator().Allocate( 01071 sizeof(Token) * 1, llvm::alignOf<Token>()); 01072 new (Toks) Token(); 01073 Toks[0].startToken(); 01074 Toks[0].setKind(tok::annot_pragma_msstruct); 01075 Toks[0].setLocation(MSStructTok.getLocation()); 01076 Toks[0].setAnnotationValue(reinterpret_cast<void*>( 01077 static_cast<uintptr_t>(Kind))); 01078 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, 01079 /*OwnsTokens=*/false); 01080 } 01081 01082 // #pragma 'align' '=' {'native','natural','mac68k','power','reset'} 01083 // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'} 01084 static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok, 01085 bool IsOptions) { 01086 Token Tok; 01087 01088 if (IsOptions) { 01089 PP.Lex(Tok); 01090 if (Tok.isNot(tok::identifier) || 01091 !Tok.getIdentifierInfo()->isStr("align")) { 01092 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align); 01093 return; 01094 } 01095 } 01096 01097 PP.Lex(Tok); 01098 if (Tok.isNot(tok::equal)) { 01099 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal) 01100 << IsOptions; 01101 return; 01102 } 01103 01104 PP.Lex(Tok); 01105 if (Tok.isNot(tok::identifier)) { 01106 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 01107 << (IsOptions ? "options" : "align"); 01108 return; 01109 } 01110 01111 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural; 01112 const IdentifierInfo *II = Tok.getIdentifierInfo(); 01113 if (II->isStr("native")) 01114 Kind = Sema::POAK_Native; 01115 else if (II->isStr("natural")) 01116 Kind = Sema::POAK_Natural; 01117 else if (II->isStr("packed")) 01118 Kind = Sema::POAK_Packed; 01119 else if (II->isStr("power")) 01120 Kind = Sema::POAK_Power; 01121 else if (II->isStr("mac68k")) 01122 Kind = Sema::POAK_Mac68k; 01123 else if (II->isStr("reset")) 01124 Kind = Sema::POAK_Reset; 01125 else { 01126 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option) 01127 << IsOptions; 01128 return; 01129 } 01130 01131 PP.Lex(Tok); 01132 if (Tok.isNot(tok::eod)) { 01133 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 01134 << (IsOptions ? "options" : "align"); 01135 return; 01136 } 01137 01138 Token *Toks = 01139 (Token*) PP.getPreprocessorAllocator().Allocate( 01140 sizeof(Token) * 1, llvm::alignOf<Token>()); 01141 new (Toks) Token(); 01142 Toks[0].startToken(); 01143 Toks[0].setKind(tok::annot_pragma_align); 01144 Toks[0].setLocation(FirstTok.getLocation()); 01145 Toks[0].setAnnotationValue(reinterpret_cast<void*>( 01146 static_cast<uintptr_t>(Kind))); 01147 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, 01148 /*OwnsTokens=*/false); 01149 } 01150 01151 void PragmaAlignHandler::HandlePragma(Preprocessor &PP, 01152 PragmaIntroducerKind Introducer, 01153 Token &AlignTok) { 01154 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false); 01155 } 01156 01157 void PragmaOptionsHandler::HandlePragma(Preprocessor &PP, 01158 PragmaIntroducerKind Introducer, 01159 Token &OptionsTok) { 01160 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true); 01161 } 01162 01163 // #pragma unused(identifier) 01164 void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, 01165 PragmaIntroducerKind Introducer, 01166 Token &UnusedTok) { 01167 // FIXME: Should we be expanding macros here? My guess is no. 01168 SourceLocation UnusedLoc = UnusedTok.getLocation(); 01169 01170 // Lex the left '('. 01171 Token Tok; 01172 PP.Lex(Tok); 01173 if (Tok.isNot(tok::l_paren)) { 01174 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused"; 01175 return; 01176 } 01177 01178 // Lex the declaration reference(s). 01179 SmallVector<Token, 5> Identifiers; 01180 SourceLocation RParenLoc; 01181 bool LexID = true; 01182 01183 while (true) { 01184 PP.Lex(Tok); 01185 01186 if (LexID) { 01187 if (Tok.is(tok::identifier)) { 01188 Identifiers.push_back(Tok); 01189 LexID = false; 01190 continue; 01191 } 01192 01193 // Illegal token! 01194 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var); 01195 return; 01196 } 01197 01198 // We are execting a ')' or a ','. 01199 if (Tok.is(tok::comma)) { 01200 LexID = true; 01201 continue; 01202 } 01203 01204 if (Tok.is(tok::r_paren)) { 01205 RParenLoc = Tok.getLocation(); 01206 break; 01207 } 01208 01209 // Illegal token! 01210 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused"; 01211 return; 01212 } 01213 01214 PP.Lex(Tok); 01215 if (Tok.isNot(tok::eod)) { 01216 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << 01217 "unused"; 01218 return; 01219 } 01220 01221 // Verify that we have a location for the right parenthesis. 01222 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'"); 01223 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments"); 01224 01225 // For each identifier token, insert into the token stream a 01226 // annot_pragma_unused token followed by the identifier token. 01227 // This allows us to cache a "#pragma unused" that occurs inside an inline 01228 // C++ member function. 01229 01230 Token *Toks = 01231 (Token*) PP.getPreprocessorAllocator().Allocate( 01232 sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>()); 01233 for (unsigned i=0; i != Identifiers.size(); i++) { 01234 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1]; 01235 pragmaUnusedTok.startToken(); 01236 pragmaUnusedTok.setKind(tok::annot_pragma_unused); 01237 pragmaUnusedTok.setLocation(UnusedLoc); 01238 idTok = Identifiers[i]; 01239 } 01240 PP.EnterTokenStream(Toks, 2*Identifiers.size(), 01241 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false); 01242 } 01243 01244 // #pragma weak identifier 01245 // #pragma weak identifier '=' identifier 01246 void PragmaWeakHandler::HandlePragma(Preprocessor &PP, 01247 PragmaIntroducerKind Introducer, 01248 Token &WeakTok) { 01249 SourceLocation WeakLoc = WeakTok.getLocation(); 01250 01251 Token Tok; 01252 PP.Lex(Tok); 01253 if (Tok.isNot(tok::identifier)) { 01254 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak"; 01255 return; 01256 } 01257 01258 Token WeakName = Tok; 01259 bool HasAlias = false; 01260 Token AliasName; 01261 01262 PP.Lex(Tok); 01263 if (Tok.is(tok::equal)) { 01264 HasAlias = true; 01265 PP.Lex(Tok); 01266 if (Tok.isNot(tok::identifier)) { 01267 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 01268 << "weak"; 01269 return; 01270 } 01271 AliasName = Tok; 01272 PP.Lex(Tok); 01273 } 01274 01275 if (Tok.isNot(tok::eod)) { 01276 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak"; 01277 return; 01278 } 01279 01280 if (HasAlias) { 01281 Token *Toks = 01282 (Token*) PP.getPreprocessorAllocator().Allocate( 01283 sizeof(Token) * 3, llvm::alignOf<Token>()); 01284 Token &pragmaUnusedTok = Toks[0]; 01285 pragmaUnusedTok.startToken(); 01286 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias); 01287 pragmaUnusedTok.setLocation(WeakLoc); 01288 Toks[1] = WeakName; 01289 Toks[2] = AliasName; 01290 PP.EnterTokenStream(Toks, 3, 01291 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false); 01292 } else { 01293 Token *Toks = 01294 (Token*) PP.getPreprocessorAllocator().Allocate( 01295 sizeof(Token) * 2, llvm::alignOf<Token>()); 01296 Token &pragmaUnusedTok = Toks[0]; 01297 pragmaUnusedTok.startToken(); 01298 pragmaUnusedTok.setKind(tok::annot_pragma_weak); 01299 pragmaUnusedTok.setLocation(WeakLoc); 01300 Toks[1] = WeakName; 01301 PP.EnterTokenStream(Toks, 2, 01302 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false); 01303 } 01304 } 01305 01306 // #pragma redefine_extname identifier identifier 01307 void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP, 01308 PragmaIntroducerKind Introducer, 01309 Token &RedefToken) { 01310 SourceLocation RedefLoc = RedefToken.getLocation(); 01311 01312 Token Tok; 01313 PP.Lex(Tok); 01314 if (Tok.isNot(tok::identifier)) { 01315 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << 01316 "redefine_extname"; 01317 return; 01318 } 01319 01320 Token RedefName = Tok; 01321 PP.Lex(Tok); 01322 01323 if (Tok.isNot(tok::identifier)) { 01324 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 01325 << "redefine_extname"; 01326 return; 01327 } 01328 01329 Token AliasName = Tok; 01330 PP.Lex(Tok); 01331 01332 if (Tok.isNot(tok::eod)) { 01333 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << 01334 "redefine_extname"; 01335 return; 01336 } 01337 01338 Token *Toks = 01339 (Token*) PP.getPreprocessorAllocator().Allocate( 01340 sizeof(Token) * 3, llvm::alignOf<Token>()); 01341 Token &pragmaRedefTok = Toks[0]; 01342 pragmaRedefTok.startToken(); 01343 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname); 01344 pragmaRedefTok.setLocation(RedefLoc); 01345 Toks[1] = RedefName; 01346 Toks[2] = AliasName; 01347 PP.EnterTokenStream(Toks, 3, 01348 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false); 01349 } 01350 01351 01352 void 01353 PragmaFPContractHandler::HandlePragma(Preprocessor &PP, 01354 PragmaIntroducerKind Introducer, 01355 Token &Tok) { 01356 tok::OnOffSwitch OOS; 01357 if (PP.LexOnOffSwitch(OOS)) 01358 return; 01359 01360 Token *Toks = 01361 (Token*) PP.getPreprocessorAllocator().Allocate( 01362 sizeof(Token) * 1, llvm::alignOf<Token>()); 01363 new (Toks) Token(); 01364 Toks[0].startToken(); 01365 Toks[0].setKind(tok::annot_pragma_fp_contract); 01366 Toks[0].setLocation(Tok.getLocation()); 01367 Toks[0].setAnnotationValue(reinterpret_cast<void*>( 01368 static_cast<uintptr_t>(OOS))); 01369 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, 01370 /*OwnsTokens=*/false); 01371 } 01372 01373 void 01374 PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP, 01375 PragmaIntroducerKind Introducer, 01376 Token &Tok) { 01377 PP.LexUnexpandedToken(Tok); 01378 if (Tok.isNot(tok::identifier)) { 01379 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << 01380 "OPENCL"; 01381 return; 01382 } 01383 IdentifierInfo *ename = Tok.getIdentifierInfo(); 01384 SourceLocation NameLoc = Tok.getLocation(); 01385 01386 PP.Lex(Tok); 01387 if (Tok.isNot(tok::colon)) { 01388 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename; 01389 return; 01390 } 01391 01392 PP.Lex(Tok); 01393 if (Tok.isNot(tok::identifier)) { 01394 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable); 01395 return; 01396 } 01397 IdentifierInfo *op = Tok.getIdentifierInfo(); 01398 01399 unsigned state; 01400 if (op->isStr("enable")) { 01401 state = 1; 01402 } else if (op->isStr("disable")) { 01403 state = 0; 01404 } else { 01405 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable); 01406 return; 01407 } 01408 SourceLocation StateLoc = Tok.getLocation(); 01409 01410 PP.Lex(Tok); 01411 if (Tok.isNot(tok::eod)) { 01412 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << 01413 "OPENCL EXTENSION"; 01414 return; 01415 } 01416 01417 OpenCLExtData data(ename, state); 01418 Token *Toks = 01419 (Token*) PP.getPreprocessorAllocator().Allocate( 01420 sizeof(Token) * 1, llvm::alignOf<Token>()); 01421 new (Toks) Token(); 01422 Toks[0].startToken(); 01423 Toks[0].setKind(tok::annot_pragma_opencl_extension); 01424 Toks[0].setLocation(NameLoc); 01425 Toks[0].setAnnotationValue(data.getOpaqueValue()); 01426 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, 01427 /*OwnsTokens=*/false); 01428 01429 if (PP.getPPCallbacks()) 01430 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename, 01431 StateLoc, state); 01432 } 01433 01434 /// \brief Handle '#pragma omp ...' when OpenMP is disabled. 01435 /// 01436 void 01437 PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP, 01438 PragmaIntroducerKind Introducer, 01439 Token &FirstTok) { 01440 if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored, 01441 FirstTok.getLocation())) { 01442 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored); 01443 PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored, 01444 diag::Severity::Ignored, SourceLocation()); 01445 } 01446 PP.DiscardUntilEndOfDirective(); 01447 } 01448 01449 /// \brief Handle '#pragma omp ...' when OpenMP is enabled. 01450 /// 01451 void 01452 PragmaOpenMPHandler::HandlePragma(Preprocessor &PP, 01453 PragmaIntroducerKind Introducer, 01454 Token &FirstTok) { 01455 SmallVector<Token, 16> Pragma; 01456 Token Tok; 01457 Tok.startToken(); 01458 Tok.setKind(tok::annot_pragma_openmp); 01459 Tok.setLocation(FirstTok.getLocation()); 01460 01461 while (Tok.isNot(tok::eod)) { 01462 Pragma.push_back(Tok); 01463 PP.Lex(Tok); 01464 } 01465 SourceLocation EodLoc = Tok.getLocation(); 01466 Tok.startToken(); 01467 Tok.setKind(tok::annot_pragma_openmp_end); 01468 Tok.setLocation(EodLoc); 01469 Pragma.push_back(Tok); 01470 01471 Token *Toks = new Token[Pragma.size()]; 01472 std::copy(Pragma.begin(), Pragma.end(), Toks); 01473 PP.EnterTokenStream(Toks, Pragma.size(), 01474 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true); 01475 } 01476 01477 /// \brief Handle '#pragma pointers_to_members' 01478 // The grammar for this pragma is as follows: 01479 // 01480 // <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance' 01481 // 01482 // #pragma pointers_to_members '(' 'best_case' ')' 01483 // #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')' 01484 // #pragma pointers_to_members '(' inheritance-model ')' 01485 void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP, 01486 PragmaIntroducerKind Introducer, 01487 Token &Tok) { 01488 SourceLocation PointersToMembersLoc = Tok.getLocation(); 01489 PP.Lex(Tok); 01490 if (Tok.isNot(tok::l_paren)) { 01491 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen) 01492 << "pointers_to_members"; 01493 return; 01494 } 01495 PP.Lex(Tok); 01496 const IdentifierInfo *Arg = Tok.getIdentifierInfo(); 01497 if (!Arg) { 01498 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 01499 << "pointers_to_members"; 01500 return; 01501 } 01502 PP.Lex(Tok); 01503 01504 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod; 01505 if (Arg->isStr("best_case")) { 01506 RepresentationMethod = LangOptions::PPTMK_BestCase; 01507 } else { 01508 if (Arg->isStr("full_generality")) { 01509 if (Tok.is(tok::comma)) { 01510 PP.Lex(Tok); 01511 01512 Arg = Tok.getIdentifierInfo(); 01513 if (!Arg) { 01514 PP.Diag(Tok.getLocation(), 01515 diag::err_pragma_pointers_to_members_unknown_kind) 01516 << Tok.getKind() << /*OnlyInheritanceModels*/ 0; 01517 return; 01518 } 01519 PP.Lex(Tok); 01520 } else if (Tok.is(tok::r_paren)) { 01521 // #pragma pointers_to_members(full_generality) implicitly specifies 01522 // virtual_inheritance. 01523 Arg = nullptr; 01524 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance; 01525 } else { 01526 PP.Diag(Tok.getLocation(), diag::err_expected_punc) 01527 << "full_generality"; 01528 return; 01529 } 01530 } 01531 01532 if (Arg) { 01533 if (Arg->isStr("single_inheritance")) { 01534 RepresentationMethod = 01535 LangOptions::PPTMK_FullGeneralitySingleInheritance; 01536 } else if (Arg->isStr("multiple_inheritance")) { 01537 RepresentationMethod = 01538 LangOptions::PPTMK_FullGeneralityMultipleInheritance; 01539 } else if (Arg->isStr("virtual_inheritance")) { 01540 RepresentationMethod = 01541 LangOptions::PPTMK_FullGeneralityVirtualInheritance; 01542 } else { 01543 PP.Diag(Tok.getLocation(), 01544 diag::err_pragma_pointers_to_members_unknown_kind) 01545 << Arg << /*HasPointerDeclaration*/ 1; 01546 return; 01547 } 01548 } 01549 } 01550 01551 if (Tok.isNot(tok::r_paren)) { 01552 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after) 01553 << (Arg ? Arg->getName() : "full_generality"); 01554 return; 01555 } 01556 01557 PP.Lex(Tok); 01558 if (Tok.isNot(tok::eod)) { 01559 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 01560 << "pointers_to_members"; 01561 return; 01562 } 01563 01564 Token AnnotTok; 01565 AnnotTok.startToken(); 01566 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members); 01567 AnnotTok.setLocation(PointersToMembersLoc); 01568 AnnotTok.setAnnotationValue( 01569 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod))); 01570 PP.EnterToken(AnnotTok); 01571 } 01572 01573 /// \brief Handle '#pragma vtordisp' 01574 // The grammar for this pragma is as follows: 01575 // 01576 // <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' ) 01577 // 01578 // #pragma vtordisp '(' ['push' ','] vtordisp-mode ')' 01579 // #pragma vtordisp '(' 'pop' ')' 01580 // #pragma vtordisp '(' ')' 01581 void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP, 01582 PragmaIntroducerKind Introducer, 01583 Token &Tok) { 01584 SourceLocation VtorDispLoc = Tok.getLocation(); 01585 PP.Lex(Tok); 01586 if (Tok.isNot(tok::l_paren)) { 01587 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp"; 01588 return; 01589 } 01590 PP.Lex(Tok); 01591 01592 Sema::PragmaVtorDispKind Kind = Sema::PVDK_Set; 01593 const IdentifierInfo *II = Tok.getIdentifierInfo(); 01594 if (II) { 01595 if (II->isStr("push")) { 01596 // #pragma vtordisp(push, mode) 01597 PP.Lex(Tok); 01598 if (Tok.isNot(tok::comma)) { 01599 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp"; 01600 return; 01601 } 01602 PP.Lex(Tok); 01603 Kind = Sema::PVDK_Push; 01604 // not push, could be on/off 01605 } else if (II->isStr("pop")) { 01606 // #pragma vtordisp(pop) 01607 PP.Lex(Tok); 01608 Kind = Sema::PVDK_Pop; 01609 } 01610 // not push or pop, could be on/off 01611 } else { 01612 if (Tok.is(tok::r_paren)) { 01613 // #pragma vtordisp() 01614 Kind = Sema::PVDK_Reset; 01615 } 01616 } 01617 01618 01619 uint64_t Value = 0; 01620 if (Kind == Sema::PVDK_Push || Kind == Sema::PVDK_Set) { 01621 const IdentifierInfo *II = Tok.getIdentifierInfo(); 01622 if (II && II->isStr("off")) { 01623 PP.Lex(Tok); 01624 Value = 0; 01625 } else if (II && II->isStr("on")) { 01626 PP.Lex(Tok); 01627 Value = 1; 01628 } else if (Tok.is(tok::numeric_constant) && 01629 PP.parseSimpleIntegerLiteral(Tok, Value)) { 01630 if (Value > 2) { 01631 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer) 01632 << 0 << 2 << "vtordisp"; 01633 return; 01634 } 01635 } else { 01636 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) 01637 << "vtordisp"; 01638 return; 01639 } 01640 } 01641 01642 // Finish the pragma: ')' $ 01643 if (Tok.isNot(tok::r_paren)) { 01644 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp"; 01645 return; 01646 } 01647 PP.Lex(Tok); 01648 if (Tok.isNot(tok::eod)) { 01649 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 01650 << "vtordisp"; 01651 return; 01652 } 01653 01654 // Enter the annotation. 01655 Token AnnotTok; 01656 AnnotTok.startToken(); 01657 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp); 01658 AnnotTok.setLocation(VtorDispLoc); 01659 AnnotTok.setAnnotationValue(reinterpret_cast<void *>( 01660 static_cast<uintptr_t>((Kind << 16) | (Value & 0xFFFF)))); 01661 PP.EnterToken(AnnotTok); 01662 } 01663 01664 /// \brief Handle all MS pragmas. Simply forwards the tokens after inserting 01665 /// an annotation token. 01666 void PragmaMSPragma::HandlePragma(Preprocessor &PP, 01667 PragmaIntroducerKind Introducer, 01668 Token &Tok) { 01669 Token EoF, AnnotTok; 01670 EoF.startToken(); 01671 EoF.setKind(tok::eof); 01672 AnnotTok.startToken(); 01673 AnnotTok.setKind(tok::annot_pragma_ms_pragma); 01674 AnnotTok.setLocation(Tok.getLocation()); 01675 SmallVector<Token, 8> TokenVector; 01676 // Suck up all of the tokens before the eod. 01677 for (; Tok.isNot(tok::eod); PP.Lex(Tok)) 01678 TokenVector.push_back(Tok); 01679 // Add a sentinal EoF token to the end of the list. 01680 TokenVector.push_back(EoF); 01681 // We must allocate this array with new because EnterTokenStream is going to 01682 // delete it later. 01683 Token *TokenArray = new Token[TokenVector.size()]; 01684 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray); 01685 auto Value = new (PP.getPreprocessorAllocator()) 01686 std::pair<Token*, size_t>(std::make_pair(TokenArray, TokenVector.size())); 01687 AnnotTok.setAnnotationValue(Value); 01688 PP.EnterToken(AnnotTok); 01689 } 01690 01691 /// \brief Handle the Microsoft \#pragma detect_mismatch extension. 01692 /// 01693 /// The syntax is: 01694 /// \code 01695 /// #pragma detect_mismatch("name", "value") 01696 /// \endcode 01697 /// Where 'name' and 'value' are quoted strings. The values are embedded in 01698 /// the object file and passed along to the linker. If the linker detects a 01699 /// mismatch in the object file's values for the given name, a LNK2038 error 01700 /// is emitted. See MSDN for more details. 01701 void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP, 01702 PragmaIntroducerKind Introducer, 01703 Token &Tok) { 01704 SourceLocation CommentLoc = Tok.getLocation(); 01705 PP.Lex(Tok); 01706 if (Tok.isNot(tok::l_paren)) { 01707 PP.Diag(CommentLoc, diag::err_expected) << tok::l_paren; 01708 return; 01709 } 01710 01711 // Read the name to embed, which must be a string literal. 01712 std::string NameString; 01713 if (!PP.LexStringLiteral(Tok, NameString, 01714 "pragma detect_mismatch", 01715 /*MacroExpansion=*/true)) 01716 return; 01717 01718 // Read the comma followed by a second string literal. 01719 std::string ValueString; 01720 if (Tok.isNot(tok::comma)) { 01721 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed); 01722 return; 01723 } 01724 01725 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch", 01726 /*MacroExpansion=*/true)) 01727 return; 01728 01729 if (Tok.isNot(tok::r_paren)) { 01730 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren; 01731 return; 01732 } 01733 PP.Lex(Tok); // Eat the r_paren. 01734 01735 if (Tok.isNot(tok::eod)) { 01736 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed); 01737 return; 01738 } 01739 01740 // If the pragma is lexically sound, notify any interested PPCallbacks. 01741 if (PP.getPPCallbacks()) 01742 PP.getPPCallbacks()->PragmaDetectMismatch(CommentLoc, NameString, 01743 ValueString); 01744 01745 Actions.ActOnPragmaDetectMismatch(NameString, ValueString); 01746 } 01747 01748 /// \brief Handle the microsoft \#pragma comment extension. 01749 /// 01750 /// The syntax is: 01751 /// \code 01752 /// #pragma comment(linker, "foo") 01753 /// \endcode 01754 /// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user. 01755 /// "foo" is a string, which is fully macro expanded, and permits string 01756 /// concatenation, embedded escape characters etc. See MSDN for more details. 01757 void PragmaCommentHandler::HandlePragma(Preprocessor &PP, 01758 PragmaIntroducerKind Introducer, 01759 Token &Tok) { 01760 SourceLocation CommentLoc = Tok.getLocation(); 01761 PP.Lex(Tok); 01762 if (Tok.isNot(tok::l_paren)) { 01763 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed); 01764 return; 01765 } 01766 01767 // Read the identifier. 01768 PP.Lex(Tok); 01769 if (Tok.isNot(tok::identifier)) { 01770 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed); 01771 return; 01772 } 01773 01774 // Verify that this is one of the 5 whitelisted options. 01775 IdentifierInfo *II = Tok.getIdentifierInfo(); 01776 Sema::PragmaMSCommentKind Kind = 01777 llvm::StringSwitch<Sema::PragmaMSCommentKind>(II->getName()) 01778 .Case("linker", Sema::PCK_Linker) 01779 .Case("lib", Sema::PCK_Lib) 01780 .Case("compiler", Sema::PCK_Compiler) 01781 .Case("exestr", Sema::PCK_ExeStr) 01782 .Case("user", Sema::PCK_User) 01783 .Default(Sema::PCK_Unknown); 01784 if (Kind == Sema::PCK_Unknown) { 01785 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind); 01786 return; 01787 } 01788 01789 // Read the optional string if present. 01790 PP.Lex(Tok); 01791 std::string ArgumentString; 01792 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString, 01793 "pragma comment", 01794 /*MacroExpansion=*/true)) 01795 return; 01796 01797 // FIXME: warn that 'exestr' is deprecated. 01798 // FIXME: If the kind is "compiler" warn if the string is present (it is 01799 // ignored). 01800 // The MSDN docs say that "lib" and "linker" require a string and have a short 01801 // whitelist of linker options they support, but in practice MSVC doesn't 01802 // issue a diagnostic. Therefore neither does clang. 01803 01804 if (Tok.isNot(tok::r_paren)) { 01805 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed); 01806 return; 01807 } 01808 PP.Lex(Tok); // eat the r_paren. 01809 01810 if (Tok.isNot(tok::eod)) { 01811 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed); 01812 return; 01813 } 01814 01815 // If the pragma is lexically sound, notify any interested PPCallbacks. 01816 if (PP.getPPCallbacks()) 01817 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString); 01818 01819 Actions.ActOnPragmaMSComment(Kind, ArgumentString); 01820 } 01821 01822 // #pragma clang optimize off 01823 // #pragma clang optimize on 01824 void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP, 01825 PragmaIntroducerKind Introducer, 01826 Token &FirstToken) { 01827 Token Tok; 01828 PP.Lex(Tok); 01829 if (Tok.is(tok::eod)) { 01830 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument) 01831 << "clang optimize" << /*Expected=*/true << "'on' or 'off'"; 01832 return; 01833 } 01834 if (Tok.isNot(tok::identifier)) { 01835 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument) 01836 << PP.getSpelling(Tok); 01837 return; 01838 } 01839 const IdentifierInfo *II = Tok.getIdentifierInfo(); 01840 // The only accepted values are 'on' or 'off'. 01841 bool IsOn = false; 01842 if (II->isStr("on")) { 01843 IsOn = true; 01844 } else if (!II->isStr("off")) { 01845 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument) 01846 << PP.getSpelling(Tok); 01847 return; 01848 } 01849 PP.Lex(Tok); 01850 01851 if (Tok.isNot(tok::eod)) { 01852 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument) 01853 << PP.getSpelling(Tok); 01854 return; 01855 } 01856 01857 Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation()); 01858 } 01859 01860 /// \brief Parses loop or unroll pragma hint value and fills in Info. 01861 static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName, 01862 Token Option, bool ValueInParens, 01863 PragmaLoopHintInfo &Info) { 01864 SmallVector<Token, 1> ValueList; 01865 int OpenParens = ValueInParens ? 1 : 0; 01866 // Read constant expression. 01867 while (Tok.isNot(tok::eod)) { 01868 if (Tok.is(tok::l_paren)) 01869 OpenParens++; 01870 else if (Tok.is(tok::r_paren)) { 01871 OpenParens--; 01872 if (OpenParens == 0 && ValueInParens) 01873 break; 01874 } 01875 01876 ValueList.push_back(Tok); 01877 PP.Lex(Tok); 01878 } 01879 01880 if (ValueInParens) { 01881 // Read ')' 01882 if (Tok.isNot(tok::r_paren)) { 01883 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren; 01884 return true; 01885 } 01886 PP.Lex(Tok); 01887 } 01888 01889 Token EOFTok; 01890 EOFTok.startToken(); 01891 EOFTok.setKind(tok::eof); 01892 EOFTok.setLocation(Tok.getLocation()); 01893 ValueList.push_back(EOFTok); // Terminates expression for parsing. 01894 01895 Token *TokenArray = (Token *)PP.getPreprocessorAllocator().Allocate( 01896 ValueList.size() * sizeof(Token), llvm::alignOf<Token>()); 01897 std::copy(ValueList.begin(), ValueList.end(), TokenArray); 01898 Info.Toks = TokenArray; 01899 Info.TokSize = ValueList.size(); 01900 01901 Info.PragmaName = PragmaName; 01902 Info.Option = Option; 01903 return false; 01904 } 01905 01906 /// \brief Handle the \#pragma clang loop directive. 01907 /// #pragma clang 'loop' loop-hints 01908 /// 01909 /// loop-hints: 01910 /// loop-hint loop-hints[opt] 01911 /// 01912 /// loop-hint: 01913 /// 'vectorize' '(' loop-hint-keyword ')' 01914 /// 'interleave' '(' loop-hint-keyword ')' 01915 /// 'unroll' '(' unroll-hint-keyword ')' 01916 /// 'vectorize_width' '(' loop-hint-value ')' 01917 /// 'interleave_count' '(' loop-hint-value ')' 01918 /// 'unroll_count' '(' loop-hint-value ')' 01919 /// 01920 /// loop-hint-keyword: 01921 /// 'enable' 01922 /// 'disable' 01923 /// 01924 /// unroll-hint-keyword: 01925 /// 'full' 01926 /// 'disable' 01927 /// 01928 /// loop-hint-value: 01929 /// constant-expression 01930 /// 01931 /// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to 01932 /// try vectorizing the instructions of the loop it precedes. Specifying 01933 /// interleave(enable) or interleave_count(_value_) instructs llvm to try 01934 /// interleaving multiple iterations of the loop it precedes. The width of the 01935 /// vector instructions is specified by vectorize_width() and the number of 01936 /// interleaved loop iterations is specified by interleave_count(). Specifying a 01937 /// value of 1 effectively disables vectorization/interleaving, even if it is 01938 /// possible and profitable, and 0 is invalid. The loop vectorizer currently 01939 /// only works on inner loops. 01940 /// 01941 /// The unroll and unroll_count directives control the concatenation 01942 /// unroller. Specifying unroll(full) instructs llvm to try to 01943 /// unroll the loop completely, and unroll(disable) disables unrolling 01944 /// for the loop. Specifying unroll_count(_value_) instructs llvm to 01945 /// try to unroll the loop the number of times indicated by the value. 01946 void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP, 01947 PragmaIntroducerKind Introducer, 01948 Token &Tok) { 01949 // Incoming token is "loop" from "#pragma clang loop". 01950 Token PragmaName = Tok; 01951 SmallVector<Token, 1> TokenList; 01952 01953 // Lex the optimization option and verify it is an identifier. 01954 PP.Lex(Tok); 01955 if (Tok.isNot(tok::identifier)) { 01956 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option) 01957 << /*MissingOption=*/true << ""; 01958 return; 01959 } 01960 01961 while (Tok.is(tok::identifier)) { 01962 Token Option = Tok; 01963 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo(); 01964 01965 bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName()) 01966 .Case("vectorize", true) 01967 .Case("interleave", true) 01968 .Case("unroll", true) 01969 .Case("vectorize_width", true) 01970 .Case("interleave_count", true) 01971 .Case("unroll_count", true) 01972 .Default(false); 01973 if (!OptionValid) { 01974 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option) 01975 << /*MissingOption=*/false << OptionInfo; 01976 return; 01977 } 01978 PP.Lex(Tok); 01979 01980 // Read '(' 01981 if (Tok.isNot(tok::l_paren)) { 01982 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren; 01983 return; 01984 } 01985 PP.Lex(Tok); 01986 01987 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo; 01988 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true, 01989 *Info)) 01990 return; 01991 01992 // Generate the loop hint token. 01993 Token LoopHintTok; 01994 LoopHintTok.startToken(); 01995 LoopHintTok.setKind(tok::annot_pragma_loop_hint); 01996 LoopHintTok.setLocation(PragmaName.getLocation()); 01997 LoopHintTok.setAnnotationValue(static_cast<void *>(Info)); 01998 TokenList.push_back(LoopHintTok); 01999 } 02000 02001 if (Tok.isNot(tok::eod)) { 02002 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 02003 << "clang loop"; 02004 return; 02005 } 02006 02007 Token *TokenArray = new Token[TokenList.size()]; 02008 std::copy(TokenList.begin(), TokenList.end(), TokenArray); 02009 02010 PP.EnterTokenStream(TokenArray, TokenList.size(), 02011 /*DisableMacroExpansion=*/false, 02012 /*OwnsTokens=*/true); 02013 } 02014 02015 /// \brief Handle the loop unroll optimization pragmas. 02016 /// #pragma unroll 02017 /// #pragma unroll unroll-hint-value 02018 /// #pragma unroll '(' unroll-hint-value ')' 02019 /// #pragma nounroll 02020 /// 02021 /// unroll-hint-value: 02022 /// constant-expression 02023 /// 02024 /// Loop unrolling hints can be specified with '#pragma unroll' or 02025 /// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally 02026 /// contained in parentheses. With no argument the directive instructs llvm to 02027 /// try to unroll the loop completely. A positive integer argument can be 02028 /// specified to indicate the number of times the loop should be unrolled. To 02029 /// maximize compatibility with other compilers the unroll count argument can be 02030 /// specified with or without parentheses. Specifying, '#pragma nounroll' 02031 /// disables unrolling of the loop. 02032 void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP, 02033 PragmaIntroducerKind Introducer, 02034 Token &Tok) { 02035 // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for 02036 // "#pragma nounroll". 02037 Token PragmaName = Tok; 02038 PP.Lex(Tok); 02039 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo; 02040 if (Tok.is(tok::eod)) { 02041 // nounroll or unroll pragma without an argument. 02042 Info->PragmaName = PragmaName; 02043 Info->Option.startToken(); 02044 } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll") { 02045 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 02046 << "nounroll"; 02047 return; 02048 } else { 02049 // Unroll pragma with an argument: "#pragma unroll N" or 02050 // "#pragma unroll(N)". 02051 // Read '(' if it exists. 02052 bool ValueInParens = Tok.is(tok::l_paren); 02053 if (ValueInParens) 02054 PP.Lex(Tok); 02055 02056 Token Option; 02057 Option.startToken(); 02058 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info)) 02059 return; 02060 02061 // In CUDA, the argument to '#pragma unroll' should not be contained in 02062 // parentheses. 02063 if (PP.getLangOpts().CUDA && ValueInParens) 02064 PP.Diag(Info->Toks[0].getLocation(), 02065 diag::warn_pragma_unroll_cuda_value_in_parens); 02066 02067 if (Tok.isNot(tok::eod)) { 02068 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 02069 << "unroll"; 02070 return; 02071 } 02072 } 02073 02074 // Generate the hint token. 02075 Token *TokenArray = new Token[1]; 02076 TokenArray[0].startToken(); 02077 TokenArray[0].setKind(tok::annot_pragma_loop_hint); 02078 TokenArray[0].setLocation(PragmaName.getLocation()); 02079 TokenArray[0].setAnnotationValue(static_cast<void *>(Info)); 02080 PP.EnterTokenStream(TokenArray, 1, /*DisableMacroExpansion=*/false, 02081 /*OwnsTokens=*/true); 02082 }