From e12f6121b90f4f25b778c2ffdd8085e53b6d2c27 Mon Sep 17 00:00:00 2001 From: Eric Schweitz Date: Thu, 6 Sep 2018 15:32:33 -0700 Subject: [PATCH] [flang] Remove the strict F18 checking flag. Always check that program is strictly conforming to F18, but demote errors to warnings when the Fortran is legal under pre-F18 standards. If the Fortran is illegal under F18 _and_ previous standards, then emit an error. Original-commit: flang-compiler/f18@6d1f37683a4409a609af49c4a623007950c868fc Reviewed-on: https://github.com/flang-compiler/f18/pull/170 Tree-same-pre-rewrite: false --- flang/lib/semantics/resolve-labels.cc | 129 ++++++++++++++------------ 1 file changed, 68 insertions(+), 61 deletions(-) diff --git a/flang/lib/semantics/resolve-labels.cc b/flang/lib/semantics/resolve-labels.cc index 7cf08daf92a0..94fdad46476b 100644 --- a/flang/lib/semantics/resolve-labels.cc +++ b/flang/lib/semantics/resolve-labels.cc @@ -24,7 +24,8 @@ namespace Fortran::semantics { using namespace parser::literals; -ENUM_CLASS(TargetStatementEnum, Do, Branch, Format) +ENUM_CLASS( + TargetStatementEnum, Do, Branch, Format, CompatibleDo, CompatibleBranch) using LabeledStmtClassificationSet = common::EnumSet; @@ -54,39 +55,43 @@ struct SourceStatementInfoTuplePOD { parser::CharBlock parserCharBlock; }; using SourceStmtList = std::vector; - -const bool isStrictF18{false}; // FIXME - make a command-line option +enum Legality { neverLegal, alwaysLegal, backwardsCompatible }; bool HasScope(ProxyForScope scope) { return scope != ProxyForScope{0u}; } // F18:R1131 template -constexpr bool IsLegalDoTerm(const parser::Statement &) { - return std::is_same_v> || - std::is_same_v; +constexpr Legality IsLegalDoTerm(const parser::Statement &) { + if (std::is_same_v> || + std::is_same_v) { + return alwaysLegal; + } else { + return neverLegal; + } } template<> -constexpr bool IsLegalDoTerm( +constexpr Legality IsLegalDoTerm( const parser::Statement &actionStmt) { if (std::holds_alternative(actionStmt.statement.u)) { // See F08:C816 - return true; - } else if (isStrictF18) { - return false; + return alwaysLegal; + } else if (!(std::holds_alternative< + common::Indirection>( + actionStmt.statement.u) || + std::holds_alternative>( + actionStmt.statement.u) || + std::holds_alternative>( + actionStmt.statement.u) || + std::holds_alternative>( + actionStmt.statement.u) || + std::holds_alternative>( + actionStmt.statement.u) || + std::holds_alternative< + common::Indirection>( + actionStmt.statement.u))) { + return backwardsCompatible; } else { - return !( - std::holds_alternative>( - actionStmt.statement.u) || - std::holds_alternative>( - actionStmt.statement.u) || - std::holds_alternative>( - actionStmt.statement.u) || - std::holds_alternative>( - actionStmt.statement.u) || - std::holds_alternative>( - actionStmt.statement.u) || - std::holds_alternative>( - actionStmt.statement.u)); + return neverLegal; } } @@ -95,8 +100,8 @@ template constexpr bool IsFormat(const parser::Statement &) { } template -constexpr bool IsLegalBranchTarget(const parser::Statement &) { - return std::is_same_v || +constexpr Legality IsLegalBranchTarget(const parser::Statement &) { + if (std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || @@ -118,23 +123,26 @@ constexpr bool IsLegalBranchTarget(const parser::Statement &) { std::is_same_v || std::is_same_v || std::is_same_v || - std::is_same_v; + std::is_same_v) { + return alwaysLegal; + } else { + return neverLegal; + } } template<> -constexpr bool IsLegalBranchTarget( +constexpr Legality IsLegalBranchTarget( const parser::Statement &actionStmt) { - if (!isStrictF18) { - return true; + if (!(std::holds_alternative>( + actionStmt.statement.u) || + std::holds_alternative>( + actionStmt.statement.u) || + std::holds_alternative>( + actionStmt.statement.u) || + std::holds_alternative>( + actionStmt.statement.u))) { + return alwaysLegal; } else { - return !( - std::holds_alternative>( - actionStmt.statement.u) || - std::holds_alternative>( - actionStmt.statement.u) || - std::holds_alternative>( - actionStmt.statement.u) || - std::holds_alternative>( - actionStmt.statement.u)); + return backwardsCompatible; } } @@ -142,11 +150,15 @@ template constexpr LabeledStmtClassificationSet constructBranchTargetFlags( const parser::Statement &statement) { LabeledStmtClassificationSet labeledStmtClassificationSet{}; - if (IsLegalDoTerm(statement)) { + if (IsLegalDoTerm(statement) == alwaysLegal) { labeledStmtClassificationSet.set(TargetStatementEnum::Do); + } else if (IsLegalDoTerm(statement) == backwardsCompatible) { + labeledStmtClassificationSet.set(TargetStatementEnum::CompatibleDo); } - if (IsLegalBranchTarget(statement)) { + if (IsLegalBranchTarget(statement) == alwaysLegal) { labeledStmtClassificationSet.set(TargetStatementEnum::Branch); + } else if (IsLegalBranchTarget(statement) == backwardsCompatible) { + labeledStmtClassificationSet.set(TargetStatementEnum::CompatibleBranch); } if (IsFormat(statement)) { labeledStmtClassificationSet.set(TargetStatementEnum::Format); @@ -719,17 +731,10 @@ void CheckBranchesIntoDoBody(const SourceStmtList &branches, const auto &toPosition{branchTarget.parserCharBlock}; for (const auto body : loopBodies) { if (!InBody(fromPosition, body) && InBody(toPosition, body)) { - if (isStrictF18) { - errorHandler.Say(fromPosition, - parser::MessageFormattedText{ - "branch into '%s' from another scope"_err_en_US, - body.first.ToString().c_str()}); - } else { errorHandler.Say(fromPosition, parser::MessageFormattedText{ "branch into '%s' from another scope"_en_US, body.first.ToString().c_str()}); - } } } } @@ -787,20 +792,21 @@ void CheckLabelDoConstraints(const SourceStmtList &dos, label}); } else if (!InInclusiveScope(scopes, scope, doTarget.proxyForScope)) { // C1133 - if (isStrictF18) { - errorHandler.Say(position, - parser::MessageFormattedText{ - "label '%" PRIu64 "' is not in scope"_err_en_US, label}); - } else { errorHandler.Say(position, parser::MessageFormattedText{ "label '%" PRIu64 "' is not in scope"_en_US, label}); - } + } else if (!doTarget.labeledStmtClassificationSet.test( + TargetStatementEnum::Do) && + !doTarget.labeledStmtClassificationSet.test( + TargetStatementEnum::CompatibleDo)) { + errorHandler.Say(doTarget.parserCharBlock, + parser::MessageFormattedText{ + "'%" PRIu64 "' invalid DO terminal statement"_err_en_US, label}); } else if (!doTarget.labeledStmtClassificationSet.test( TargetStatementEnum::Do)) { errorHandler.Say(doTarget.parserCharBlock, parser::MessageFormattedText{ - "'%" PRIu64 "' invalid DO terminal statement"_err_en_US, label}); + "'%" PRIu64 "' invalid DO terminal statement"_en_US, label}); } else { loopBodies.emplace_back(SkipLabel(position), doTarget.parserCharBlock); } @@ -824,15 +830,9 @@ void CheckScopeConstraints(const SourceStmtList &stmts, parser::MessageFormattedText{ "label '%" PRIu64 "' was not found"_err_en_US, label}); } else if (!InInclusiveScope(scopes, scope, target.proxyForScope)) { - if (isStrictF18) { - errorHandler.Say(position, - parser::MessageFormattedText{ - "label '%" PRIu64 "' is not in scope"_err_en_US, label}); - } else { errorHandler.Say(position, parser::MessageFormattedText{ "label '%" PRIu64 "' is not in scope"_en_US, label}); - } } } } @@ -844,10 +844,17 @@ void CheckBranchTargetConstraints(const SourceStmtList &stmts, auto branchTarget{GetLabel(labels, label)}; if (HasScope(branchTarget.proxyForScope)) { if (!branchTarget.labeledStmtClassificationSet.test( - TargetStatementEnum::Branch)) { + TargetStatementEnum::Branch) && + !branchTarget.labeledStmtClassificationSet.test( + TargetStatementEnum::CompatibleBranch)) { errorHandler.Say(branchTarget.parserCharBlock, parser::MessageFormattedText{ "'%" PRIu64 "' not a branch target"_err_en_US, label}); + } else if (!branchTarget.labeledStmtClassificationSet.test( + TargetStatementEnum::Branch)) { + errorHandler.Say(branchTarget.parserCharBlock, + parser::MessageFormattedText{ + "'%" PRIu64 "' not a branch target"_en_US, label}); } } }