{"action":"created","comment":{"url":"https://api.github.com/repos/flang-compiler/f18/pulls/comments/216011819","pull_request_review_id":153409514,"id":216011819,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIxNjAxMTgxOQ==","diff_hunk":"@@ -0,0 +1,918 @@\n+// Copyright (c) 2018, NVIDIA CORPORATION.  All rights reserved.\n+//\n+// Licensed under the Apache License, Version 2.0 (the \"License\");\n+// you may not use this file except in compliance with the License.\n+// You may obtain a copy of the License at\n+//\n+//     http://www.apache.org/licenses/LICENSE-2.0\n+//\n+// Unless required by applicable law or agreed to in writing, software\n+// distributed under the License is distributed on an \"AS IS\" BASIS,\n+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+// See the License for the specific language governing permissions and\n+// limitations under the License.\n+\n+#include \"resolve-labels.h\"\n+#include \"../common/enum-set.h\"\n+#include \"../parser/message.h\"\n+#include \"../parser/parse-tree-visitor.h\"\n+#include <cctype>\n+#include <cstdarg>\n+#include <iostream>\n+\n+namespace Fortran::semantics {\n+\n+using namespace parser::literals;\n+\n+ENUM_CLASS(TargetStatementEnum, Do, Branch, Format)\n+using LabeledStmtClassificationSet =\n+    common::EnumSet<TargetStatementEnum, TargetStatementEnum_enumSize>;\n+\n+using IndexList = std::vector<std::pair<parser::CharBlock, parser::CharBlock>>;\n+// A ProxyForScope is an integral proxy for a Fortran scope. This is required\n+// because the parse tree does not actually have the scopes required.\n+using ProxyForScope = unsigned;\n+struct LabeledStatementInfoTuplePOD {\n+  LabeledStatementInfoTuplePOD(const ProxyForScope &_proxyForScope,\n+      const parser::CharBlock &_parserCharBlock,\n+      const LabeledStmtClassificationSet &_labeledStmtClassificationSet)\n+    : proxyForScope{_proxyForScope}, parserCharBlock{_parserCharBlock},\n+      labeledStmtClassificationSet{_labeledStmtClassificationSet} {}\n+  ProxyForScope proxyForScope;\n+  parser::CharBlock parserCharBlock;\n+  LabeledStmtClassificationSet labeledStmtClassificationSet;\n+};\n+using TargetStmtMap = std::map<parser::Label, LabeledStatementInfoTuplePOD>;\n+struct SourceStatementInfoTuplePOD {\n+  SourceStatementInfoTuplePOD(const parser::Label &_parserLabel,\n+      const ProxyForScope &_proxyForScope,\n+      const parser::CharBlock &_parserCharBlock)\n+    : parserLabel{_parserLabel}, proxyForScope{_proxyForScope},\n+      parserCharBlock{_parserCharBlock} {}\n+  parser::Label parserLabel;\n+  ProxyForScope proxyForScope;\n+  parser::CharBlock parserCharBlock;\n+};\n+using SourceStmtList = std::vector<SourceStatementInfoTuplePOD>;\n+\n+const bool isStrictF18{false};  // FIXME - make a command-line option\n+\n+bool HasScope(ProxyForScope scope) { return scope != ProxyForScope{0u}; }\n+\n+// F18:R1131\n+template<typename A>\n+constexpr bool IsLegalDoTerm(const parser::Statement<A> &) {\n+  return std::is_same_v<A, common::Indirection<parser::EndDoStmt>> ||\n+      std::is_same_v<A, parser::EndDoStmt>;\n+}\n+template<>\n+constexpr bool IsLegalDoTerm(\n+    const parser::Statement<parser::ActionStmt> &actionStmt) {\n+  if (std::holds_alternative<parser::ContinueStmt>(actionStmt.statement.u)) {\n+    // See F08:C816\n+    return true;\n+  } else if (isStrictF18) {\n+    return false;\n+  } else {\n+    return !(\n+        std::holds_alternative<common::Indirection<parser::ArithmeticIfStmt>>(\n+            actionStmt.statement.u) ||\n+        std::holds_alternative<common::Indirection<parser::CycleStmt>>(\n+            actionStmt.statement.u) ||\n+        std::holds_alternative<common::Indirection<parser::ExitStmt>>(\n+            actionStmt.statement.u) ||\n+        std::holds_alternative<common::Indirection<parser::StopStmt>>(\n+            actionStmt.statement.u) ||\n+        std::holds_alternative<common::Indirection<parser::GotoStmt>>(\n+            actionStmt.statement.u) ||\n+        std::holds_alternative<common::Indirection<parser::ReturnStmt>>(\n+            actionStmt.statement.u));\n+  }\n+}\n+\n+template<typename A> constexpr bool IsFormat(const parser::Statement<A> &) {\n+  return std::is_same_v<A, common::Indirection<parser::FormatStmt>>;\n+}\n+\n+template<typename A>\n+constexpr bool IsLegalBranchTarget(const parser::Statement<A> &) {\n+  return std::is_same_v<A, parser::AssociateStmt> ||\n+      std::is_same_v<A, parser::EndAssociateStmt> ||\n+      std::is_same_v<A, parser::IfThenStmt> ||\n+      std::is_same_v<A, parser::EndIfStmt> ||\n+      std::is_same_v<A, parser::SelectCaseStmt> ||\n+      std::is_same_v<A, parser::EndSelectStmt> ||\n+      std::is_same_v<A, parser::SelectRankStmt> ||\n+      std::is_same_v<A, parser::SelectTypeStmt> ||\n+      std::is_same_v<A, common::Indirection<parser::LabelDoStmt>> ||\n+      std::is_same_v<A, parser::NonLabelDoStmt> ||\n+      std::is_same_v<A, parser::EndDoStmt> ||\n+      std::is_same_v<A, common::Indirection<parser::EndDoStmt>> ||\n+      std::is_same_v<A, parser::BlockStmt> ||\n+      std::is_same_v<A, parser::EndBlockStmt> ||\n+      std::is_same_v<A, parser::CriticalStmt> ||\n+      std::is_same_v<A, parser::EndCriticalStmt> ||\n+      std::is_same_v<A, parser::ForallConstructStmt> ||\n+      std::is_same_v<A, parser::ForallStmt> ||\n+      std::is_same_v<A, parser::WhereConstructStmt> ||\n+      std::is_same_v<A, parser::EndFunctionStmt> ||\n+      std::is_same_v<A, parser::EndMpSubprogramStmt> ||\n+      std::is_same_v<A, parser::EndProgramStmt> ||\n+      std::is_same_v<A, parser::EndSubroutineStmt>;\n+}\n+template<>\n+constexpr bool IsLegalBranchTarget(\n+    const parser::Statement<parser::ActionStmt> &actionStmt) {\n+  if (!isStrictF18) {\n+    return true;\n+  } else {\n+    return !(\n+        std::holds_alternative<common::Indirection<parser::ArithmeticIfStmt>>(\n+            actionStmt.statement.u) ||\n+        std::holds_alternative<common::Indirection<parser::AssignStmt>>(\n+            actionStmt.statement.u) ||\n+        std::holds_alternative<common::Indirection<parser::AssignedGotoStmt>>(\n+            actionStmt.statement.u) ||\n+        std::holds_alternative<common::Indirection<parser::PauseStmt>>(\n+            actionStmt.statement.u));\n+  }\n+}\n+\n+template<typename A>\n+constexpr LabeledStmtClassificationSet constructBranchTargetFlags(\n+    const parser::Statement<A> &statement) {\n+  LabeledStmtClassificationSet labeledStmtClassificationSet{};\n+  if (IsLegalDoTerm(statement)) {\n+    labeledStmtClassificationSet.set(TargetStatementEnum::Do);\n+  }\n+  if (IsLegalBranchTarget(statement)) {\n+    labeledStmtClassificationSet.set(TargetStatementEnum::Branch);\n+  }\n+  if (IsFormat(statement)) {\n+    labeledStmtClassificationSet.set(TargetStatementEnum::Format);\n+  }\n+  return labeledStmtClassificationSet;\n+}\n+\n+bool BothEqOrNone(const std::optional<parser::Name> &name_a,\n+    const std::optional<parser::Name> &name_b) {\n+  if (name_a.has_value()) {\n+    if (name_b.has_value()) {\n+      return name_a->ToString() == name_b->ToString();\n+    } else {\n+      return false;\n+    }\n+  } else {\n+    return !name_b.has_value();\n+  }\n+}\n+\n+bool PresentAndEq(const std::optional<parser::Name> &name_a,\n+    const std::optional<parser::Name> &name_b) {\n+  if (!name_a.has_value()) {\n+    return true;\n+  } else if (name_b.has_value()) {\n+    return name_a->ToString() == name_b->ToString();\n+  } else {\n+    return false;\n+  }\n+}\n+\n+struct UnitAnalysis {\n+  UnitAnalysis() { scopeModel.push_back(0); }\n+  UnitAnalysis(UnitAnalysis &&that)\n+    : doStmtSources{std::move(that.doStmtSources)},\n+      formatStmtSources{std::move(that.formatStmtSources)},\n+      otherStmtSources{std::move(that.otherStmtSources)},\n+      targetStmts{std::move(that.targetStmts)}, scopeModel{std::move(\n+                                                    that.scopeModel)} {}\n+\n+  SourceStmtList doStmtSources;\n+  SourceStmtList formatStmtSources;\n+  SourceStmtList otherStmtSources;\n+  TargetStmtMap targetStmts;\n+  std::vector<ProxyForScope> scopeModel;\n+};\n+\n+class ParseTreeAnalyzer {\n+public:\n+  ParseTreeAnalyzer() {}\n+  ParseTreeAnalyzer(ParseTreeAnalyzer &&that)\n+    : programUnits_{std::move(that.programUnits_)},\n+      errorHandler_{std::move(that.errorHandler_)}, currentPosition_{std::move(\n+                                                        that.currentPosition_)},\n+      constructNames_{std::move(that.constructNames_)} {}\n+\n+  template<typename A> constexpr bool Pre(const A &) { return true; }\n+  template<typename A> constexpr void Post(const A &) {}\n+\n+  template<typename A> bool Pre(const parser::Statement<A> &statement) {\n+    currentPosition_ = statement.source;\n+    if (statement.label.has_value())\n+      addTargetLabelDefinition(\n+          statement.label.value(), constructBranchTargetFlags(statement));\n+    return true;\n+  }\n+\n+  // see 11.1.1\n+  bool Pre(const parser::ProgramUnit &) { return PushNewScope(); }\n+  bool Pre(const parser::AssociateConstruct &associateConstruct) {\n+    return pushConstructName(associateConstruct);\n+  }\n+  bool Pre(const parser::BlockConstruct &blockConstruct) {\n+    return pushConstructName(blockConstruct);\n+  }\n+  bool Pre(const parser::ChangeTeamConstruct &changeTeamConstruct) {\n+    return pushConstructName(changeTeamConstruct);\n+  }\n+  bool Pre(const parser::CriticalConstruct &criticalConstruct) {\n+    return pushConstructName(criticalConstruct);\n+  }\n+  bool Pre(const parser::DoConstruct &doConstruct) {\n+    return pushConstructName(doConstruct);\n+  }\n+  bool Pre(const parser::IfConstruct &ifConstruct) {\n+    return pushConstructName(ifConstruct);\n+  }\n+  bool Pre(const parser::IfConstruct::ElseIfBlock &) {\n+    return switchToNewScope();\n+  }\n+  bool Pre(const parser::IfConstruct::ElseBlock &) {\n+    return switchToNewScope();\n+  }\n+  bool Pre(const parser::CaseConstruct &caseConstruct) {\n+    return pushConstructName(caseConstruct);\n+  }\n+  bool Pre(const parser::CaseConstruct::Case &) { return switchToNewScope(); }\n+  bool Pre(const parser::SelectRankConstruct &selectRankConstruct) {\n+    return pushConstructName(selectRankConstruct);\n+  }\n+  bool Pre(const parser::SelectRankConstruct::RankCase &) {\n+    return switchToNewScope();\n+  }\n+  bool Pre(const parser::SelectTypeConstruct &selectTypeConstruct) {\n+    return pushConstructName(selectTypeConstruct);\n+  }\n+  bool Pre(const parser::SelectTypeConstruct::TypeCase &) {\n+    return switchToNewScope();\n+  }\n+  bool Pre(const parser::WhereConstruct &whereConstruct) {\n+    return pushConstructNameWithoutBlock(whereConstruct);\n+  }\n+  bool Pre(const parser::ForallConstruct &forallConstruct) {\n+    return pushConstructNameWithoutBlock(forallConstruct);\n+  }\n+\n+  void Post(const parser::ProgramUnit &) { PopScope(); }\n+  void Post(const parser::AssociateConstruct &associateConstruct) {\n+    popConstructName(associateConstruct);\n+  }\n+  void Post(const parser::BlockConstruct &blockConstruct) {\n+    popConstructName(blockConstruct);\n+  }\n+  void Post(const parser::ChangeTeamConstruct &changeTeamConstruct) {\n+    popConstructName(changeTeamConstruct);\n+  }\n+  void Post(const parser::CriticalConstruct &criticalConstruct) {\n+    popConstructName(criticalConstruct);\n+  }\n+  void Post(const parser::DoConstruct &doConstruct) {\n+    popConstructName(doConstruct);\n+  }\n+  void Post(const parser::IfConstruct &ifConstruct) {\n+    popConstructName(ifConstruct);\n+  }\n+  void Post(const parser::CaseConstruct &caseConstruct) {\n+    popConstructName(caseConstruct);\n+  }\n+  void Post(const parser::SelectRankConstruct &selectRankConstruct) {\n+    popConstructName(selectRankConstruct);\n+  }\n+  void Post(const parser::SelectTypeConstruct &selectTypeConstruct) {\n+    popConstructName(selectTypeConstruct);\n+  }\n+\n+  void Post(const parser::WhereConstruct &whereConstruct) {\n+    popConstructNameWithoutBlock(whereConstruct);\n+  }\n+  void Post(const parser::ForallConstruct &forallConstruct) {\n+    popConstructNameWithoutBlock(forallConstruct);\n+  }\n+\n+  void Post(const parser::LabelDoStmt &labelDoStmt) {\n+    addLabelReferenceFromDoStmt(std::get<parser::Label>(labelDoStmt.t));\n+  }\n+  void Post(const parser::GotoStmt &gotoStmt) { addLabelReference(gotoStmt.v); }\n+  void Post(const parser::ComputedGotoStmt &computedGotoStmt) {\n+    addLabelReference(std::get<std::list<parser::Label>>(computedGotoStmt.t));\n+  }\n+  void Post(const parser::ArithmeticIfStmt &arithmeticIfStmt) {\n+    addLabelReference(std::get<1>(arithmeticIfStmt.t));\n+    addLabelReference(std::get<2>(arithmeticIfStmt.t));\n+    addLabelReference(std::get<3>(arithmeticIfStmt.t));\n+  }\n+  void Post(const parser::AssignStmt &assignStmt) {\n+    addLabelReference(std::get<parser::Label>(assignStmt.t));\n+  }\n+  void Post(const parser::AssignedGotoStmt &assignedGotoStmt) {\n+    addLabelReference(std::get<std::list<parser::Label>>(assignedGotoStmt.t));\n+  }\n+  void Post(const parser::AltReturnSpec &altReturnSpec) {\n+    addLabelReference(altReturnSpec.v);\n+  }\n+\n+  void Post(const parser::ErrLabel &errLabel) { addLabelReference(errLabel.v); }\n+  void Post(const parser::EndLabel &endLabel) { addLabelReference(endLabel.v); }\n+  void Post(const parser::EorLabel &eorLabel) { addLabelReference(eorLabel.v); }\n+  void Post(const parser::Format &format) {\n+    // BUG: the label is saved as an IntLiteralConstant rather than a Label\n+#if 0\n+    if (const auto *P{std::get_if<parser::Label>(&format.u)}) {\n+      addLabelReferenceFromFormatStmt(*P);\n+    }\n+#else\n+    if (const auto *P{std::get_if<0>(&format.u)}) {\n+      addLabelReferenceFromFormatStmt(\n+          parser::Label{std::get<0>(std::get<parser::IntLiteralConstant>(\n+              std::get<parser::LiteralConstant>((*P->thing).u).u)\n+                                        .t)});\n+    }\n+#endif\n+  }\n+  void Post(const parser::CycleStmt &cycleStmt) {\n+    if (cycleStmt.v.has_value()) {\n+      CheckLabelContext(\"CYCLE\", cycleStmt.v->ToString());\n+    }\n+  }\n+  void Post(const parser::ExitStmt &exitStmt) {\n+    if (exitStmt.v.has_value()) {\n+      CheckLabelContext(\"EXIT\", exitStmt.v->ToString());\n+    }\n+  }\n+\n+  const std::vector<UnitAnalysis> &programUnits() const {\n+    return programUnits_;\n+  }\n+  parser::Messages &errorHandler() { return errorHandler_; }\n+\n+private:\n+  bool pushSubscope() {\n+    programUnits_.back().scopeModel.push_back(currentScope_);\n+    currentScope_ = programUnits_.back().scopeModel.size() - 1;\n+    return true;\n+  }\n+  bool PushNewScope() {\n+    programUnits_.emplace_back(UnitAnalysis{});\n+    return pushSubscope();\n+  }\n+  void PopScope() {\n+    currentScope_ = programUnits_.back().scopeModel[currentScope_];\n+  }\n+  bool switchToNewScope() {\n+    PopScope();\n+    return pushSubscope();\n+  }\n+\n+  template<typename A> bool pushConstructName(const A &a) {\n+    const auto &optionalName{std::get<0>(std::get<0>(a.t).statement.t)};\n+    if (optionalName.has_value()) {\n+      constructNames_.emplace_back(optionalName->ToString());\n+    }\n+    return pushSubscope();\n+  }\n+  bool pushConstructName(const parser::BlockConstruct &blockConstruct) {\n+    const auto &optionalName{\n+        std::get<parser::Statement<parser::BlockStmt>>(blockConstruct.t)\n+            .statement.v};\n+    if (optionalName.has_value()) {\n+      constructNames_.emplace_back(optionalName->ToString());\n+    }\n+    return pushSubscope();\n+  }\n+  template<typename A> bool pushConstructNameWithoutBlock(const A &a) {\n+    const auto &optionalName{std::get<0>(std::get<0>(a.t).statement.t)};\n+    if (optionalName.has_value()) {\n+      constructNames_.emplace_back(optionalName->ToString());\n+    }\n+    return true;\n+  }\n+\n+  template<typename A> void popConstructNameWithoutBlock(const A &a) {\n+    CheckName(a);\n+    popConstructNameIfPresent(a);\n+  }\n+\n+  template<typename A> void popConstructNameIfPresent(const A &a) {\n+    const auto &optionalName{std::get<0>(std::get<0>(a.t).statement.t)};\n+    if (optionalName.has_value()) {\n+      constructNames_.pop_back();\n+    }\n+  }\n+\n+  void popConstructNameIfPresent(const parser::BlockConstruct &blockConstruct) {\n+    const auto &optionalName{\n+        std::get<parser::Statement<parser::BlockStmt>>(blockConstruct.t)\n+            .statement.v};\n+    if (optionalName.has_value()) {\n+      constructNames_.pop_back();\n+    }\n+  }\n+\n+  template<typename A> void popConstructName(const A &a) {\n+    CheckName(a);\n+    PopScope();\n+    popConstructNameIfPresent(a);\n+  }\n+\n+  // C1144\n+  void popConstructName(const parser::CaseConstruct &caseConstruct) {\n+    CheckName(caseConstruct, \"CASE\");\n+    PopScope();\n+    popConstructNameIfPresent(caseConstruct);\n+  }\n+\n+  // C1154, C1156\n+  void popConstructName(\n+      const parser::SelectRankConstruct &selectRankConstruct) {\n+    CheckName(selectRankConstruct, \"RANK\", \"RANK \");\n+    PopScope();\n+    popConstructNameIfPresent(selectRankConstruct);\n+  }\n+\n+  // C1165\n+  void popConstructName(\n+      const parser::SelectTypeConstruct &selectTypeConstruct) {\n+    CheckName(selectTypeConstruct, \"TYPE\", \"TYPE \");\n+    PopScope();\n+    popConstructNameIfPresent(selectTypeConstruct);\n+  }\n+\n+  // C1106\n+  void CheckName(const parser::AssociateConstruct &associateConstruct) {\n+    CheckName(\"ASSOCIATE\", associateConstruct);\n+  }\n+  // C1117\n+  void CheckName(const parser::CriticalConstruct &criticalConstruct) {\n+    CheckName(\"CRITICAL\", criticalConstruct);\n+  }\n+  // C1131\n+  void CheckName(const parser::DoConstruct &doConstruct) {\n+    CheckName(\"DO\", doConstruct);\n+  }\n+  // C1035\n+  void CheckName(const parser::ForallConstruct &forallConstruct) {\n+    CheckName(\"FORALL\", forallConstruct);\n+  }\n+\n+  template<typename A>\n+  void CheckName(const char *const constructTag, const A &a) {\n+    if (!BothEqOrNone(\n+            std::get<std::optional<parser::Name>>(std::get<0>(a.t).statement.t),\n+            std::get<2>(a.t).statement.v)) {\n+      errorHandler_.Say(currentPosition_,\n+          parser::MessageFormattedText{\n+              \"%s construct name mismatch\"_err_en_US, constructTag});\n+    }\n+  }\n+\n+  // C1109\n+  void CheckName(const parser::BlockConstruct &blockConstruct) {\n+    if (!BothEqOrNone(\n+            std::get<parser::Statement<parser::BlockStmt>>(blockConstruct.t)\n+                .statement.v,\n+            std::get<parser::Statement<parser::EndBlockStmt>>(blockConstruct.t)\n+                .statement.v)) {\n+      errorHandler_.Say(currentPosition_,\n+          parser::MessageFormattedText{\n+              \"BLOCK construct name mismatch\"_err_en_US});\n+    }\n+  }\n+  // C1112\n+  void CheckName(const parser::ChangeTeamConstruct &changeTeamConstruct) {\n+    if (!BothEqOrNone(std::get<std::optional<parser::Name>>(\n+                          std::get<parser::Statement<parser::ChangeTeamStmt>>(\n+                              changeTeamConstruct.t)\n+                              .statement.t),\n+            std::get<std::optional<parser::Name>>(\n+                std::get<parser::Statement<parser::EndChangeTeamStmt>>(\n+                    changeTeamConstruct.t)\n+                    .statement.t))) {\n+      errorHandler_.Say(currentPosition_,\n+          parser::MessageFormattedText{\n+              \"CHANGE TEAM construct name mismatch\"_err_en_US});\n+    }\n+  }\n+\n+  // C1142\n+  void CheckName(const parser::IfConstruct &ifConstruct) {\n+    const auto &constructName{std::get<std::optional<parser::Name>>(\n+        std::get<parser::Statement<parser::IfThenStmt>>(ifConstruct.t)\n+            .statement.t)};\n+    if (!BothEqOrNone(constructName,\n+            std::get<parser::Statement<parser::EndIfStmt>>(ifConstruct.t)\n+                .statement.v)) {\n+      errorHandler_.Say(currentPosition_,\n+          parser::MessageFormattedText{\"IF construct name mismatch\"_err_en_US});\n+    }\n+    for (const auto &elseIfBlock :\n+        std::get<std::list<parser::IfConstruct::ElseIfBlock>>(ifConstruct.t)) {\n+      if (!PresentAndEq(\n+              std::get<std::optional<parser::Name>>(\n+                  std::get<parser::Statement<parser::ElseIfStmt>>(elseIfBlock.t)\n+                      .statement.t),\n+              constructName)) {\n+        errorHandler_.Say(currentPosition_,\n+            parser::MessageFormattedText{\n+                \"ELSE IF statement name mismatch\"_err_en_US});\n+      }\n+    }\n+    if (std::get<std::optional<parser::IfConstruct::ElseBlock>>(ifConstruct.t)\n+            .has_value()) {\n+      if (!PresentAndEq(\n+              std::get<parser::Statement<parser::ElseStmt>>(\n+                  std::get<std::optional<parser::IfConstruct::ElseBlock>>(\n+                      ifConstruct.t)\n+                      ->t\n+\n+                  )\n+                  .statement.v,\n+              constructName)) {\n+        errorHandler_.Say(currentPosition_,\n+            parser::MessageFormattedText{\n+                \"ELSE statement name mismatch\"_err_en_US});\n+      }\n+    }\n+  }\n+\n+  template<typename A>\n+  void CheckName(const A &a, const char *const selectTag,\n+      const char *const selectSubTag = \"\") {\n+    const auto &constructName{std::get<0>(std::get<0>(a.t).statement.t)};\n+    if (!BothEqOrNone(constructName, std::get<2>(a.t).statement.v)) {\n+      errorHandler_.Say(currentPosition_,\n+          parser::MessageFormattedText{\n+              \"SELECT %s construct name mismatch\"_err_en_US, selectTag});\n+    }\n+    for (const auto &subpart : std::get<1>(a.t)) {\n+      if (!PresentAndEq(std::get<std::optional<parser::Name>>(\n+                            std::get<0>(subpart.t).statement.t),\n+              constructName)) {\n+        errorHandler_.Say(currentPosition_,\n+            parser::MessageFormattedText{\n+                \"%sCASE statement name mismatch\"_err_en_US, selectSubTag});\n+      }\n+    }\n+  }\n+\n+  // C1033\n+  void CheckName(const parser::WhereConstruct &whereConstruct) {\n+    const auto &constructName{std::get<std::optional<parser::Name>>(\n+        std::get<parser::Statement<parser::WhereConstructStmt>>(\n+            whereConstruct.t)\n+            .statement.t)};\n+    if (!BothEqOrNone(constructName,\n+            std::get<parser::Statement<parser::EndWhereStmt>>(whereConstruct.t)\n+                .statement.v)) {\n+      errorHandler_.Say(currentPosition_,\n+          parser::MessageFormattedText{\n+              \"WHERE construct name mismatch\"_err_en_US});\n+    }\n+    for (const auto &maskedElsewhere :\n+        std::get<std::list<parser::WhereConstruct::MaskedElsewhere>>(\n+            whereConstruct.t)) {\n+      if (!PresentAndEq(\n+              std::get<std::optional<parser::Name>>(\n+                  std::get<parser::Statement<parser::MaskedElsewhereStmt>>(\n+                      maskedElsewhere.t)\n+                      .statement.t),\n+              constructName)) {\n+        errorHandler_.Say(currentPosition_,\n+            parser::MessageFormattedText{\n+                \"ELSEWHERE (<mask>) statement name mismatch\"_err_en_US});\n+      }\n+    }\n+    if (std::get<std::optional<parser::WhereConstruct::Elsewhere>>(\n+            whereConstruct.t)\n+            .has_value()) {\n+      if (!PresentAndEq(\n+              std::get<parser::Statement<parser::ElsewhereStmt>>(\n+                  std::get<std::optional<parser::WhereConstruct::Elsewhere>>(\n+                      whereConstruct.t)\n+                      ->t)\n+                  .statement.v,\n+              constructName)) {\n+        errorHandler_.Say(currentPosition_,\n+            parser::MessageFormattedText{\n+                \"ELSEWHERE statement name mismatch\"_err_en_US});\n+      }\n+    }\n+  }\n+\n+  // C1134, C1166\n+  template<typename A>\n+  void CheckLabelContext(const char *const stmtString, const A &constructName) {\n+    const auto I{std::find(\n+        constructNames_.crbegin(), constructNames_.crend(), constructName)};\n+    if (I == constructNames_.crend()) {\n+      errorHandler_.Say(currentPosition_,\n+          parser::MessageFormattedText{\n+              \"%s construct-name '%s' is not in scope\"_err_en_US, stmtString,\n+              constructName.c_str()});\n+    }\n+  }\n+\n+  // 6.2.5, paragraph 2\n+  void CheckLabelInRange(parser::Label label) {\n+    if (label < 1 || label > 99999) {\n+      errorHandler_.Say(currentPosition_,\n+          parser::MessageFormattedText{\n+              \"label '%\" PRIu64 \"' is out of range\"_err_en_US, label});\n+    }\n+  }\n+\n+  // 6.2.5., paragraph 2\n+  void addTargetLabelDefinition(parser::Label label,\n+      LabeledStmtClassificationSet labeledStmtClassificationSet) {\n+    CheckLabelInRange(label);\n+    const auto pair{\n+        programUnits_.back().targetStmts.emplace(std::make_pair(label,","path":"lib/semantics/resolve-labels.cc","position":null,"original_position":638,"commit_id":"7c80648f27a66cb8b75e135be219f6589b227e75","original_commit_id":"55b7e18763de2cb786ea03b4813aabd45a507337","user":{"login":"klausler","id":35819229,"node_id":"MDQ6VXNlcjM1ODE5MjI5","avatar_url":"https://avatars1.githubusercontent.com/u/35819229?v=4","gravatar_id":"","url":"https://api.github.com/users/klausler","html_url":"https://github.com/klausler","followers_url":"https://api.github.com/users/klausler/followers","following_url":"https://api.github.com/users/klausler/following{/other_user}","gists_url":"https://api.github.com/users/klausler/gists{/gist_id}","starred_url":"https://api.github.com/users/klausler/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/klausler/subscriptions","organizations_url":"https://api.github.com/users/klausler/orgs","repos_url":"https://api.github.com/users/klausler/repos","events_url":"https://api.github.com/users/klausler/events{/privacy}","received_events_url":"https://api.github.com/users/klausler/received_events","type":"User","site_admin":false},"body":"The arguments to `emplace` (and related STL member functions) are forwarded to the constructor of the new element.  If one uses `emplace` with a already-constructed temporary object, the new element's move constructor will be used, assuming that it has one.  The whole point of `emplace` is that it omits the use of an intermediate temporary object.  The runtime savings is probably not going to affect the compiler's performance significantly, but `emplace` should be used anyway when constructing a new object in a container that provides the interface.","created_at":"2018-09-07T16:13:18Z","updated_at":"2018-09-07T16:13:18Z","html_url":"https://github.com/flang-compiler/f18/pull/170#discussion_r216011819","pull_request_url":"https://api.github.com/repos/flang-compiler/f18/pulls/170","author_association":"COLLABORATOR","_links":{"self":{"href":"https://api.github.com/repos/flang-compiler/f18/pulls/comments/216011819"},"html":{"href":"https://github.com/flang-compiler/f18/pull/170#discussion_r216011819"},"pull_request":{"href":"https://api.github.com/repos/flang-compiler/f18/pulls/170"}},"in_reply_to_id":215755657},"pull_request":{"url":"https://api.github.com/repos/flang-compiler/f18/pulls/170","id":211230136,"node_id":"MDExOlB1bGxSZXF1ZXN0MjExMjMwMTM2","html_url":"https://github.com/flang-compiler/f18/pull/170","diff_url":"https://github.com/flang-compiler/f18/pull/170.diff","patch_url":"https://github.com/flang-compiler/f18/pull/170.patch","issue_url":"https://api.github.com/repos/flang-compiler/f18/issues/170","number":170,"state":"open","locked":false,"title":"Add label resolution initial pass implementation and tests","user":{"login":"schweitzpgi","id":22080509,"node_id":"MDQ6VXNlcjIyMDgwNTA5","avatar_url":"https://avatars0.githubusercontent.com/u/22080509?v=4","gravatar_id":"","url":"https://api.github.com/users/schweitzpgi","html_url":"https://github.com/schweitzpgi","followers_url":"https://api.github.com/users/schweitzpgi/followers","following_url":"https://api.github.com/users/schweitzpgi/following{/other_user}","gists_url":"https://api.github.com/users/schweitzpgi/gists{/gist_id}","starred_url":"https://api.github.com/users/schweitzpgi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/schweitzpgi/subscriptions","organizations_url":"https://api.github.com/users/schweitzpgi/orgs","repos_url":"https://api.github.com/users/schweitzpgi/repos","events_url":"https://api.github.com/users/schweitzpgi/events{/privacy}","received_events_url":"https://api.github.com/users/schweitzpgi/received_events","type":"User","site_admin":false},"body":"","created_at":"2018-08-27T21:00:52Z","updated_at":"2018-09-07T16:13:18Z","closed_at":null,"merged_at":null,"merge_commit_sha":"55dfc555aaec2174ad5cc8639cb34b288d437c82","assignee":null,"assignees":[],"requested_reviewers":[{"login":"sscalpone","id":504306,"node_id":"MDQ6VXNlcjUwNDMwNg==","avatar_url":"https://avatars0.githubusercontent.com/u/504306?v=4","gravatar_id":"","url":"https://api.github.com/users/sscalpone","html_url":"https://github.com/sscalpone","followers_url":"https://api.github.com/users/sscalpone/followers","following_url":"https://api.github.com/users/sscalpone/following{/other_user}","gists_url":"https://api.github.com/users/sscalpone/gists{/gist_id}","starred_url":"https://api.github.com/users/sscalpone/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sscalpone/subscriptions","organizations_url":"https://api.github.com/users/sscalpone/orgs","repos_url":"https://api.github.com/users/sscalpone/repos","events_url":"https://api.github.com/users/sscalpone/events{/privacy}","received_events_url":"https://api.github.com/users/sscalpone/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/flang-compiler/f18/pulls/170/commits","review_comments_url":"https://api.github.com/repos/flang-compiler/f18/pulls/170/comments","review_comment_url":"https://api.github.com/repos/flang-compiler/f18/pulls/comments{/number}","comments_url":"https://api.github.com/repos/flang-compiler/f18/issues/170/comments","statuses_url":"https://api.github.com/repos/flang-compiler/f18/statuses/7c80648f27a66cb8b75e135be219f6589b227e75","head":{"label":"flang-compiler:easddd","ref":"easddd","sha":"7c80648f27a66cb8b75e135be219f6589b227e75","user":{"login":"flang-compiler","id":27519978,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI3NTE5OTc4","avatar_url":"https://avatars2.githubusercontent.com/u/27519978?v=4","gravatar_id":"","url":"https://api.github.com/users/flang-compiler","html_url":"https://github.com/flang-compiler","followers_url":"https://api.github.com/users/flang-compiler/followers","following_url":"https://api.github.com/users/flang-compiler/following{/other_user}","gists_url":"https://api.github.com/users/flang-compiler/gists{/gist_id}","starred_url":"https://api.github.com/users/flang-compiler/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/flang-compiler/subscriptions","organizations_url":"https://api.github.com/users/flang-compiler/orgs","repos_url":"https://api.github.com/users/flang-compiler/repos","events_url":"https://api.github.com/users/flang-compiler/events{/privacy}","received_events_url":"https://api.github.com/users/flang-compiler/received_events","type":"Organization","site_admin":false},"repo":{"id":118970343,"node_id":"MDEwOlJlcG9zaXRvcnkxMTg5NzAzNDM=","name":"f18","full_name":"flang-compiler/f18","owner":{"login":"flang-compiler","id":27519978,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI3NTE5OTc4","avatar_url":"https://avatars2.githubusercontent.com/u/27519978?v=4","gravatar_id":"","url":"https://api.github.com/users/flang-compiler","html_url":"https://github.com/flang-compiler","followers_url":"https://api.github.com/users/flang-compiler/followers","following_url":"https://api.github.com/users/flang-compiler/following{/other_user}","gists_url":"https://api.github.com/users/flang-compiler/gists{/gist_id}","starred_url":"https://api.github.com/users/flang-compiler/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/flang-compiler/subscriptions","organizations_url":"https://api.github.com/users/flang-compiler/orgs","repos_url":"https://api.github.com/users/flang-compiler/repos","events_url":"https://api.github.com/users/flang-compiler/events{/privacy}","received_events_url":"https://api.github.com/users/flang-compiler/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/flang-compiler/f18","description":"F18 is a front-end for Fortran intended to replace the existing front-end in the Flang compiler","fork":false,"url":"https://api.github.com/repos/flang-compiler/f18","forks_url":"https://api.github.com/repos/flang-compiler/f18/forks","keys_url":"https://api.github.com/repos/flang-compiler/f18/keys{/key_id}","collaborators_url":"https://api.github.com/repos/flang-compiler/f18/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/flang-compiler/f18/teams","hooks_url":"https://api.github.com/repos/flang-compiler/f18/hooks","issue_events_url":"https://api.github.com/repos/flang-compiler/f18/issues/events{/number}","events_url":"https://api.github.com/repos/flang-compiler/f18/events","assignees_url":"https://api.github.com/repos/flang-compiler/f18/assignees{/user}","branches_url":"https://api.github.com/repos/flang-compiler/f18/branches{/branch}","tags_url":"https://api.github.com/repos/flang-compiler/f18/tags","blobs_url":"https://api.github.com/repos/flang-compiler/f18/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/flang-compiler/f18/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/flang-compiler/f18/git/refs{/sha}","trees_url":"https://api.github.com/repos/flang-compiler/f18/git/trees{/sha}","statuses_url":"https://api.github.com/repos/flang-compiler/f18/statuses/{sha}","languages_url":"https://api.github.com/repos/flang-compiler/f18/languages","stargazers_url":"https://api.github.com/repos/flang-compiler/f18/stargazers","contributors_url":"https://api.github.com/repos/flang-compiler/f18/contributors","subscribers_url":"https://api.github.com/repos/flang-compiler/f18/subscribers","subscription_url":"https://api.github.com/repos/flang-compiler/f18/subscription","commits_url":"https://api.github.com/repos/flang-compiler/f18/commits{/sha}","git_commits_url":"https://api.github.com/repos/flang-compiler/f18/git/commits{/sha}","comments_url":"https://api.github.com/repos/flang-compiler/f18/comments{/number}","issue_comment_url":"https://api.github.com/repos/flang-compiler/f18/issues/comments{/number}","contents_url":"https://api.github.com/repos/flang-compiler/f18/contents/{+path}","compare_url":"https://api.github.com/repos/flang-compiler/f18/compare/{base}...{head}","merges_url":"https://api.github.com/repos/flang-compiler/f18/merges","archive_url":"https://api.github.com/repos/flang-compiler/f18/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/flang-compiler/f18/downloads","issues_url":"https://api.github.com/repos/flang-compiler/f18/issues{/number}","pulls_url":"https://api.github.com/repos/flang-compiler/f18/pulls{/number}","milestones_url":"https://api.github.com/repos/flang-compiler/f18/milestones{/number}","notifications_url":"https://api.github.com/repos/flang-compiler/f18/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/flang-compiler/f18/labels{/name}","releases_url":"https://api.github.com/repos/flang-compiler/f18/releases{/id}","deployments_url":"https://api.github.com/repos/flang-compiler/f18/deployments","created_at":"2018-01-25T21:34:19Z","updated_at":"2018-09-07T16:08:08Z","pushed_at":"2018-09-07T16:08:06Z","git_url":"git://github.com/flang-compiler/f18.git","ssh_url":"git@github.com:flang-compiler/f18.git","clone_url":"https://github.com/flang-compiler/f18.git","svn_url":"https://github.com/flang-compiler/f18","homepage":"","size":2361,"stargazers_count":42,"watchers_count":42,"language":"C++","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":3,"mirror_url":null,"archived":false,"open_issues_count":7,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":3,"open_issues":7,"watchers":42,"default_branch":"master"}},"base":{"label":"flang-compiler:master","ref":"master","sha":"e9abdbc993482ceab2cc2831d65f5275bdee264b","user":{"login":"flang-compiler","id":27519978,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI3NTE5OTc4","avatar_url":"https://avatars2.githubusercontent.com/u/27519978?v=4","gravatar_id":"","url":"https://api.github.com/users/flang-compiler","html_url":"https://github.com/flang-compiler","followers_url":"https://api.github.com/users/flang-compiler/followers","following_url":"https://api.github.com/users/flang-compiler/following{/other_user}","gists_url":"https://api.github.com/users/flang-compiler/gists{/gist_id}","starred_url":"https://api.github.com/users/flang-compiler/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/flang-compiler/subscriptions","organizations_url":"https://api.github.com/users/flang-compiler/orgs","repos_url":"https://api.github.com/users/flang-compiler/repos","events_url":"https://api.github.com/users/flang-compiler/events{/privacy}","received_events_url":"https://api.github.com/users/flang-compiler/received_events","type":"Organization","site_admin":false},"repo":{"id":118970343,"node_id":"MDEwOlJlcG9zaXRvcnkxMTg5NzAzNDM=","name":"f18","full_name":"flang-compiler/f18","owner":{"login":"flang-compiler","id":27519978,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI3NTE5OTc4","avatar_url":"https://avatars2.githubusercontent.com/u/27519978?v=4","gravatar_id":"","url":"https://api.github.com/users/flang-compiler","html_url":"https://github.com/flang-compiler","followers_url":"https://api.github.com/users/flang-compiler/followers","following_url":"https://api.github.com/users/flang-compiler/following{/other_user}","gists_url":"https://api.github.com/users/flang-compiler/gists{/gist_id}","starred_url":"https://api.github.com/users/flang-compiler/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/flang-compiler/subscriptions","organizations_url":"https://api.github.com/users/flang-compiler/orgs","repos_url":"https://api.github.com/users/flang-compiler/repos","events_url":"https://api.github.com/users/flang-compiler/events{/privacy}","received_events_url":"https://api.github.com/users/flang-compiler/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/flang-compiler/f18","description":"F18 is a front-end for Fortran intended to replace the existing front-end in the Flang compiler","fork":false,"url":"https://api.github.com/repos/flang-compiler/f18","forks_url":"https://api.github.com/repos/flang-compiler/f18/forks","keys_url":"https://api.github.com/repos/flang-compiler/f18/keys{/key_id}","collaborators_url":"https://api.github.com/repos/flang-compiler/f18/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/flang-compiler/f18/teams","hooks_url":"https://api.github.com/repos/flang-compiler/f18/hooks","issue_events_url":"https://api.github.com/repos/flang-compiler/f18/issues/events{/number}","events_url":"https://api.github.com/repos/flang-compiler/f18/events","assignees_url":"https://api.github.com/repos/flang-compiler/f18/assignees{/user}","branches_url":"https://api.github.com/repos/flang-compiler/f18/branches{/branch}","tags_url":"https://api.github.com/repos/flang-compiler/f18/tags","blobs_url":"https://api.github.com/repos/flang-compiler/f18/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/flang-compiler/f18/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/flang-compiler/f18/git/refs{/sha}","trees_url":"https://api.github.com/repos/flang-compiler/f18/git/trees{/sha}","statuses_url":"https://api.github.com/repos/flang-compiler/f18/statuses/{sha}","languages_url":"https://api.github.com/repos/flang-compiler/f18/languages","stargazers_url":"https://api.github.com/repos/flang-compiler/f18/stargazers","contributors_url":"https://api.github.com/repos/flang-compiler/f18/contributors","subscribers_url":"https://api.github.com/repos/flang-compiler/f18/subscribers","subscription_url":"https://api.github.com/repos/flang-compiler/f18/subscription","commits_url":"https://api.github.com/repos/flang-compiler/f18/commits{/sha}","git_commits_url":"https://api.github.com/repos/flang-compiler/f18/git/commits{/sha}","comments_url":"https://api.github.com/repos/flang-compiler/f18/comments{/number}","issue_comment_url":"https://api.github.com/repos/flang-compiler/f18/issues/comments{/number}","contents_url":"https://api.github.com/repos/flang-compiler/f18/contents/{+path}","compare_url":"https://api.github.com/repos/flang-compiler/f18/compare/{base}...{head}","merges_url":"https://api.github.com/repos/flang-compiler/f18/merges","archive_url":"https://api.github.com/repos/flang-compiler/f18/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/flang-compiler/f18/downloads","issues_url":"https://api.github.com/repos/flang-compiler/f18/issues{/number}","pulls_url":"https://api.github.com/repos/flang-compiler/f18/pulls{/number}","milestones_url":"https://api.github.com/repos/flang-compiler/f18/milestones{/number}","notifications_url":"https://api.github.com/repos/flang-compiler/f18/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/flang-compiler/f18/labels{/name}","releases_url":"https://api.github.com/repos/flang-compiler/f18/releases{/id}","deployments_url":"https://api.github.com/repos/flang-compiler/f18/deployments","created_at":"2018-01-25T21:34:19Z","updated_at":"2018-09-07T16:08:08Z","pushed_at":"2018-09-07T16:08:06Z","git_url":"git://github.com/flang-compiler/f18.git","ssh_url":"git@github.com:flang-compiler/f18.git","clone_url":"https://github.com/flang-compiler/f18.git","svn_url":"https://github.com/flang-compiler/f18","homepage":"","size":2361,"stargazers_count":42,"watchers_count":42,"language":"C++","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":3,"mirror_url":null,"archived":false,"open_issues_count":7,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":3,"open_issues":7,"watchers":42,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/flang-compiler/f18/pulls/170"},"html":{"href":"https://github.com/flang-compiler/f18/pull/170"},"issue":{"href":"https://api.github.com/repos/flang-compiler/f18/issues/170"},"comments":{"href":"https://api.github.com/repos/flang-compiler/f18/issues/170/comments"},"review_comments":{"href":"https://api.github.com/repos/flang-compiler/f18/pulls/170/comments"},"review_comment":{"href":"https://api.github.com/repos/flang-compiler/f18/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/flang-compiler/f18/pulls/170/commits"},"statuses":{"href":"https://api.github.com/repos/flang-compiler/f18/statuses/7c80648f27a66cb8b75e135be219f6589b227e75"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"klausler"}}