diff options
Diffstat (limited to 'lib/Parse/ParsePragma.cpp')
-rw-r--r-- | lib/Parse/ParsePragma.cpp | 208 |
1 files changed, 175 insertions, 33 deletions
diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp index 198d5c6e9cb0..9a25f9c25c03 100644 --- a/lib/Parse/ParsePragma.cpp +++ b/lib/Parse/ParsePragma.cpp @@ -95,6 +95,44 @@ struct PragmaFPContractHandler : public PragmaHandler { Token &FirstToken) override; }; +// Pragma STDC implementations. + +/// PragmaSTDC_FENV_ACCESSHandler - "\#pragma STDC FENV_ACCESS ...". +struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler { + PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {} + + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &Tok) override { + tok::OnOffSwitch OOS; + if (PP.LexOnOffSwitch(OOS)) + return; + if (OOS == tok::OOS_ON) + PP.Diag(Tok, diag::warn_stdc_fenv_access_not_supported); + } +}; + +/// PragmaSTDC_CX_LIMITED_RANGEHandler - "\#pragma STDC CX_LIMITED_RANGE ...". +struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler { + PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {} + + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &Tok) override { + tok::OnOffSwitch OOS; + PP.LexOnOffSwitch(OOS); + } +}; + +/// PragmaSTDC_UnknownHandler - "\#pragma STDC ...". +struct PragmaSTDC_UnknownHandler : public PragmaHandler { + PragmaSTDC_UnknownHandler() = default; + + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &UnknownTok) override { + // C99 6.10.6p2, unknown forms are not allowed. + PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored); + } +}; + struct PragmaFPHandler : public PragmaHandler { PragmaFPHandler() : PragmaHandler("fp") {} void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, @@ -182,6 +220,12 @@ struct PragmaMSIntrinsicHandler : public PragmaHandler { Token &FirstToken) override; }; +struct PragmaMSOptimizeHandler : public PragmaHandler { + PragmaMSOptimizeHandler() : PragmaHandler("optimize") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +}; + struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler { PragmaForceCUDAHostDeviceHandler(Sema &Actions) : PragmaHandler("force_cuda_host_device"), Actions(Actions) {} @@ -233,6 +277,15 @@ void Parser::initializePragmaHandlers() { FPContractHandler.reset(new PragmaFPContractHandler()); PP.AddPragmaHandler("STDC", FPContractHandler.get()); + STDCFENVHandler.reset(new PragmaSTDC_FENV_ACCESSHandler()); + PP.AddPragmaHandler("STDC", STDCFENVHandler.get()); + + STDCCXLIMITHandler.reset(new PragmaSTDC_CX_LIMITED_RANGEHandler()); + PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get()); + + STDCUnknownHandler.reset(new PragmaSTDC_UnknownHandler()); + PP.AddPragmaHandler("STDC", STDCUnknownHandler.get()); + PCSectionHandler.reset(new PragmaClangSectionHandler(Actions)); PP.AddPragmaHandler("clang", PCSectionHandler.get()); @@ -248,7 +301,8 @@ void Parser::initializePragmaHandlers() { OpenMPHandler.reset(new PragmaNoOpenMPHandler()); PP.AddPragmaHandler(OpenMPHandler.get()); - if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) { + if (getLangOpts().MicrosoftExt || + getTargetInfo().getTriple().isOSBinFormatELF()) { MSCommentHandler.reset(new PragmaCommentHandler(Actions)); PP.AddPragmaHandler(MSCommentHandler.get()); } @@ -276,6 +330,8 @@ void Parser::initializePragmaHandlers() { PP.AddPragmaHandler(MSRuntimeChecks.get()); MSIntrinsic.reset(new PragmaMSIntrinsicHandler()); PP.AddPragmaHandler(MSIntrinsic.get()); + MSOptimize.reset(new PragmaMSOptimizeHandler()); + PP.AddPragmaHandler(MSOptimize.get()); } if (getLangOpts().CUDA) { @@ -330,7 +386,8 @@ void Parser::resetPragmaHandlers() { PP.RemovePragmaHandler(OpenMPHandler.get()); OpenMPHandler.reset(); - if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) { + if (getLangOpts().MicrosoftExt || + getTargetInfo().getTriple().isOSBinFormatELF()) { PP.RemovePragmaHandler(MSCommentHandler.get()); MSCommentHandler.reset(); } @@ -361,6 +418,8 @@ void Parser::resetPragmaHandlers() { MSRuntimeChecks.reset(); PP.RemovePragmaHandler(MSIntrinsic.get()); MSIntrinsic.reset(); + PP.RemovePragmaHandler(MSOptimize.get()); + MSOptimize.reset(); } if (getLangOpts().CUDA) { @@ -371,6 +430,15 @@ void Parser::resetPragmaHandlers() { PP.RemovePragmaHandler("STDC", FPContractHandler.get()); FPContractHandler.reset(); + PP.RemovePragmaHandler("STDC", STDCFENVHandler.get()); + STDCFENVHandler.reset(); + + PP.RemovePragmaHandler("STDC", STDCCXLIMITHandler.get()); + STDCCXLIMITHandler.reset(); + + PP.RemovePragmaHandler("STDC", STDCUnknownHandler.get()); + STDCUnknownHandler.reset(); + PP.RemovePragmaHandler("clang", OptimizeHandler.get()); OptimizeHandler.reset(); @@ -390,7 +458,7 @@ void Parser::resetPragmaHandlers() { AttributePragmaHandler.reset(); } -/// \brief Handle the annotation token produced for #pragma unused(...) +/// Handle the annotation token produced for #pragma unused(...) /// /// Each annot_pragma_unused is followed by the argument token so e.g. /// "#pragma unused(x,y)" becomes: @@ -451,8 +519,10 @@ void Parser::HandlePragmaAlign() { Sema::PragmaOptionsAlignKind Kind = static_cast<Sema::PragmaOptionsAlignKind>( reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); - SourceLocation PragmaLoc = ConsumeAnnotationToken(); - Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc); + Actions.ActOnPragmaOptionsAlign(Kind, Tok.getLocation()); + // Consume the token after processing the pragma to enable pragma-specific + // #include warnings. + ConsumeAnnotationToken(); } void Parser::HandlePragmaDump() { @@ -1175,7 +1245,7 @@ bool Parser::ParsePragmaAttributeSubjectMatchRuleSet( namespace { -/// Describes the stage at which attribute subject rule parsing was interruped. +/// Describes the stage at which attribute subject rule parsing was interrupted. enum class MissingAttributeSubjectRulesRecoveryPoint { Comma, ApplyTo, @@ -1201,7 +1271,7 @@ getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) { /// suggests the possible attribute subject rules in a fix-it together with /// any other missing tokens. DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic( - unsigned DiagID, AttributeList &Attribute, + unsigned DiagID, ParsedAttr &Attribute, MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) { SourceLocation Loc = PRef.getEndOfPreviousToken(); if (Loc.isInvalid()) @@ -1301,12 +1371,11 @@ void Parser::HandlePragmaAttribute() { if (Tok.isNot(tok::l_paren)) Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - AttributeList::AS_GNU); + ParsedAttr::AS_GNU); else ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr, /*ScopeName=*/nullptr, - /*ScopeLoc=*/SourceLocation(), - AttributeList::AS_GNU, + /*ScopeLoc=*/SourceLocation(), ParsedAttr::AS_GNU, /*Declarator=*/nullptr); if (ExpectAndConsume(tok::r_paren)) @@ -1320,9 +1389,9 @@ void Parser::HandlePragmaAttribute() { if (Tok.getIdentifierInfo()) { // If we suspect that this is an attribute suggest the use of // '__attribute__'. - if (AttributeList::getKind(Tok.getIdentifierInfo(), /*ScopeName=*/nullptr, - AttributeList::AS_GNU) != - AttributeList::UnknownAttribute) { + if (ParsedAttr::getKind(Tok.getIdentifierInfo(), /*ScopeName=*/nullptr, + ParsedAttr::AS_GNU) != + ParsedAttr::UnknownAttribute) { SourceLocation InsertStartLoc = Tok.getLocation(); ConsumeToken(); if (Tok.is(tok::l_paren)) { @@ -1340,26 +1409,26 @@ void Parser::HandlePragmaAttribute() { return; } - if (!Attrs.getList() || Attrs.getList()->isInvalid()) { + if (Attrs.empty() || Attrs.begin()->isInvalid()) { SkipToEnd(); return; } // Ensure that we don't have more than one attribute. - if (Attrs.getList()->getNext()) { - SourceLocation Loc = Attrs.getList()->getNext()->getLoc(); + if (Attrs.size() > 1) { + SourceLocation Loc = Attrs[1].getLoc(); Diag(Loc, diag::err_pragma_attribute_multiple_attributes); SkipToEnd(); return; } - if (!Attrs.getList()->isSupportedByPragmaAttribute()) { + ParsedAttr &Attribute = *Attrs.begin(); + if (!Attribute.isSupportedByPragmaAttribute()) { Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute) - << Attrs.getList()->getName(); + << Attribute.getName(); SkipToEnd(); return; } - AttributeList &Attribute = *Attrs.getList(); // Parse the subject-list. if (!TryConsumeToken(tok::comma)) { @@ -2030,7 +2099,7 @@ PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP, StateLoc, State); } -/// \brief Handle '#pragma omp ...' when OpenMP is disabled. +/// Handle '#pragma omp ...' when OpenMP is disabled. /// void PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP, @@ -2045,7 +2114,7 @@ PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP, PP.DiscardUntilEndOfDirective(); } -/// \brief Handle '#pragma omp ...' when OpenMP is enabled. +/// Handle '#pragma omp ...' when OpenMP is enabled. /// void PragmaOpenMPHandler::HandlePragma(Preprocessor &PP, @@ -2057,9 +2126,21 @@ PragmaOpenMPHandler::HandlePragma(Preprocessor &PP, Tok.setKind(tok::annot_pragma_openmp); Tok.setLocation(FirstTok.getLocation()); - while (Tok.isNot(tok::eod)) { + while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof)) { Pragma.push_back(Tok); PP.Lex(Tok); + if (Tok.is(tok::annot_pragma_openmp)) { + PP.Diag(Tok, diag::err_omp_unexpected_directive) << 0; + unsigned InnerPragmaCnt = 1; + while (InnerPragmaCnt != 0) { + PP.Lex(Tok); + if (Tok.is(tok::annot_pragma_openmp)) + ++InnerPragmaCnt; + else if (Tok.is(tok::annot_pragma_openmp_end)) + --InnerPragmaCnt; + } + PP.Lex(Tok); + } } SourceLocation EodLoc = Tok.getLocation(); Tok.startToken(); @@ -2073,7 +2154,7 @@ PragmaOpenMPHandler::HandlePragma(Preprocessor &PP, /*DisableMacroExpansion=*/false); } -/// \brief Handle '#pragma pointers_to_members' +/// Handle '#pragma pointers_to_members' // The grammar for this pragma is as follows: // // <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance' @@ -2171,7 +2252,7 @@ void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP, PP.EnterToken(AnnotTok); } -/// \brief Handle '#pragma vtordisp' +/// Handle '#pragma vtordisp' // The grammar for this pragma is as follows: // // <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' ) @@ -2264,7 +2345,7 @@ void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP, PP.EnterToken(AnnotTok); } -/// \brief Handle all MS pragmas. Simply forwards the tokens after inserting +/// Handle all MS pragmas. Simply forwards the tokens after inserting /// an annotation token. void PragmaMSPragma::HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, @@ -2282,7 +2363,7 @@ void PragmaMSPragma::HandlePragma(Preprocessor &PP, TokenVector.push_back(Tok); AnnotTok.setAnnotationEndLoc(Tok.getLocation()); } - // Add a sentinal EoF token to the end of the list. + // Add a sentinel EoF token to the end of the list. TokenVector.push_back(EoF); // We must allocate this array with new because EnterTokenStream is going to // delete it later. @@ -2295,7 +2376,7 @@ void PragmaMSPragma::HandlePragma(Preprocessor &PP, PP.EnterToken(AnnotTok); } -/// \brief Handle the Microsoft \#pragma detect_mismatch extension. +/// Handle the Microsoft \#pragma detect_mismatch extension. /// /// The syntax is: /// \code @@ -2352,7 +2433,7 @@ void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP, Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString); } -/// \brief Handle the microsoft \#pragma comment extension. +/// Handle the microsoft \#pragma comment extension. /// /// The syntax is: /// \code @@ -2393,6 +2474,12 @@ void PragmaCommentHandler::HandlePragma(Preprocessor &PP, return; } + if (PP.getTargetInfo().getTriple().isOSBinFormatELF() && Kind != PCK_Lib) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored) + << II->getName(); + return; + } + // On PS4, issue a warning about any pragma comments other than // #pragma comment lib. if (PP.getTargetInfo().getTriple().isPS4() && Kind != PCK_Lib) { @@ -2595,7 +2682,7 @@ void Parser::HandlePragmaFP() { ConsumeAnnotationToken(); } -/// \brief Parses loop or unroll pragma hint value and fills in Info. +/// Parses loop or unroll pragma hint value and fills in Info. static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName, Token Option, bool ValueInParens, PragmaLoopHintInfo &Info) { @@ -2637,7 +2724,7 @@ static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName, return false; } -/// \brief Handle the \#pragma clang loop directive. +/// Handle the \#pragma clang loop directive. /// #pragma clang 'loop' loop-hints /// /// loop-hints: @@ -2752,7 +2839,7 @@ void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP, /*DisableMacroExpansion=*/false); } -/// \brief Handle the loop unroll optimization pragmas. +/// Handle the loop unroll optimization pragmas. /// #pragma unroll /// #pragma unroll unroll-hint-value /// #pragma unroll '(' unroll-hint-value ')' @@ -2822,7 +2909,7 @@ void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP, /*DisableMacroExpansion=*/false); } -/// \brief Handle the Microsoft \#pragma intrinsic extension. +/// Handle the Microsoft \#pragma intrinsic extension. /// /// The syntax is: /// \code @@ -2871,6 +2958,61 @@ void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP, PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "intrinsic"; } + +// #pragma optimize("gsty", on|off) +void PragmaMSOptimizeHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &Tok) { + SourceLocation StartLoc = Tok.getLocation(); + PP.Lex(Tok); + + if (Tok.isNot(tok::l_paren)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "optimize"; + return; + } + PP.Lex(Tok); + + if (Tok.isNot(tok::string_literal)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_string) << "optimize"; + return; + } + // We could syntax check the string but it's probably not worth the effort. + PP.Lex(Tok); + + if (Tok.isNot(tok::comma)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_comma) << "optimize"; + return; + } + PP.Lex(Tok); + + if (Tok.is(tok::eod) || Tok.is(tok::r_paren)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_missing_argument) + << "optimize" << /*Expected=*/true << "'on' or 'off'"; + return; + } + IdentifierInfo *II = Tok.getIdentifierInfo(); + if (!II || (!II->isStr("on") && !II->isStr("off"))) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument) + << PP.getSpelling(Tok) << "optimize" << /*Expected=*/true + << "'on' or 'off'"; + return; + } + PP.Lex(Tok); + + if (Tok.isNot(tok::r_paren)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "optimize"; + return; + } + PP.Lex(Tok); + + if (Tok.isNot(tok::eod)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) + << "optimize"; + return; + } + PP.Diag(StartLoc, diag::warn_pragma_optimize); +} + void PragmaForceCUDAHostDeviceHandler::HandlePragma( Preprocessor &PP, PragmaIntroducerKind Introducer, Token &Tok) { Token FirstTok = Tok; @@ -2895,7 +3037,7 @@ void PragmaForceCUDAHostDeviceHandler::HandlePragma( diag::warn_pragma_force_cuda_host_device_bad_arg); } -/// \brief Handle the #pragma clang attribute directive. +/// Handle the #pragma clang attribute directive. /// /// The syntax is: /// \code |