164ab3302SCarolineConcatto //===-- lib/Semantics/semantics.cpp ---------------------------------------===// 264ab3302SCarolineConcatto // 364ab3302SCarolineConcatto // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 464ab3302SCarolineConcatto // See https://llvm.org/LICENSE.txt for license information. 564ab3302SCarolineConcatto // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 664ab3302SCarolineConcatto // 764ab3302SCarolineConcatto //===----------------------------------------------------------------------===// 864ab3302SCarolineConcatto 964ab3302SCarolineConcatto #include "flang/Semantics/semantics.h" 1064ab3302SCarolineConcatto #include "assignment.h" 119aa3dca8SValentin Clement #include "canonicalize-acc.h" 12c6b6e18cSDavid Truby #include "canonicalize-directives.h" 1364ab3302SCarolineConcatto #include "canonicalize-do.h" 1464ab3302SCarolineConcatto #include "canonicalize-omp.h" 159aa3dca8SValentin Clement #include "check-acc-structure.h" 1664ab3302SCarolineConcatto #include "check-allocate.h" 1764ab3302SCarolineConcatto #include "check-arithmeticif.h" 187a77c20dSpeter klausler #include "check-case.h" 1964ab3302SCarolineConcatto #include "check-coarray.h" 20f674ddc1SPeter Klausler #include "check-cuda.h" 2164ab3302SCarolineConcatto #include "check-data.h" 2264ab3302SCarolineConcatto #include "check-deallocate.h" 2364ab3302SCarolineConcatto #include "check-declarations.h" 2464ab3302SCarolineConcatto #include "check-do-forall.h" 2564ab3302SCarolineConcatto #include "check-if-stmt.h" 2664ab3302SCarolineConcatto #include "check-io.h" 2792c1f6bbSVarun Jayathirtha #include "check-namelist.h" 2864ab3302SCarolineConcatto #include "check-nullify.h" 2964ab3302SCarolineConcatto #include "check-omp-structure.h" 3064ab3302SCarolineConcatto #include "check-purity.h" 3164ab3302SCarolineConcatto #include "check-return.h" 32332e6aeaSsameeran joshi #include "check-select-rank.h" 3370ad73b6Ssameeran joshi #include "check-select-type.h" 3464ab3302SCarolineConcatto #include "check-stop.h" 35c353ebbfSTim Keith #include "compute-offsets.h" 3664ab3302SCarolineConcatto #include "mod-file.h" 3764ab3302SCarolineConcatto #include "resolve-labels.h" 3864ab3302SCarolineConcatto #include "resolve-names.h" 3964ab3302SCarolineConcatto #include "rewrite-parse-tree.h" 4064ab3302SCarolineConcatto #include "flang/Common/default-kinds.h" 4164ab3302SCarolineConcatto #include "flang/Parser/parse-tree-visitor.h" 4264ab3302SCarolineConcatto #include "flang/Parser/tools.h" 4364ab3302SCarolineConcatto #include "flang/Semantics/expression.h" 4464ab3302SCarolineConcatto #include "flang/Semantics/scope.h" 4564ab3302SCarolineConcatto #include "flang/Semantics/symbol.h" 468670e499SCaroline Concatto #include "llvm/Support/raw_ostream.h" 47838a4d34SKelvin Li #include "llvm/TargetParser/Host.h" 48838a4d34SKelvin Li #include "llvm/TargetParser/Triple.h" 4964ab3302SCarolineConcatto 5064ab3302SCarolineConcatto namespace Fortran::semantics { 5164ab3302SCarolineConcatto 52f80866bdSpeter klausler using NameToSymbolMap = std::multimap<parser::CharBlock, SymbolRef>; 538670e499SCaroline Concatto static void DoDumpSymbols(llvm::raw_ostream &, const Scope &, int indent = 0); 548670e499SCaroline Concatto static void PutIndent(llvm::raw_ostream &, int indent); 5564ab3302SCarolineConcatto 5664ab3302SCarolineConcatto static void GetSymbolNames(const Scope &scope, NameToSymbolMap &symbols) { 5764ab3302SCarolineConcatto // Finds all symbol names in the scope without collecting duplicates. 5864ab3302SCarolineConcatto for (const auto &pair : scope) { 59f80866bdSpeter klausler symbols.emplace(pair.second->name(), *pair.second); 6064ab3302SCarolineConcatto } 6164ab3302SCarolineConcatto for (const auto &pair : scope.commonBlocks()) { 62f80866bdSpeter klausler symbols.emplace(pair.second->name(), *pair.second); 6364ab3302SCarolineConcatto } 6464ab3302SCarolineConcatto for (const auto &child : scope.children()) { 6564ab3302SCarolineConcatto GetSymbolNames(child, symbols); 6664ab3302SCarolineConcatto } 6764ab3302SCarolineConcatto } 6864ab3302SCarolineConcatto 6964ab3302SCarolineConcatto // A parse tree visitor that calls Enter/Leave functions from each checker 7064ab3302SCarolineConcatto // class C supplied as template parameters. Enter is called before the node's 7164ab3302SCarolineConcatto // children are visited, Leave is called after. No two checkers may have the 7264ab3302SCarolineConcatto // same Enter or Leave function. Each checker must be constructible from 7364ab3302SCarolineConcatto // SemanticsContext and have BaseChecker as a virtual base class. 74f674ddc1SPeter Klausler template <typename... C> 75f674ddc1SPeter Klausler class SemanticsVisitor : public virtual BaseChecker, public virtual C... { 7664ab3302SCarolineConcatto public: 7764ab3302SCarolineConcatto using BaseChecker::Enter; 7864ab3302SCarolineConcatto using BaseChecker::Leave; 79f674ddc1SPeter Klausler using C::Enter...; 80f674ddc1SPeter Klausler using C::Leave...; 8164ab3302SCarolineConcatto SemanticsVisitor(SemanticsContext &context) 8264ab3302SCarolineConcatto : C{context}..., context_{context} {} 8364ab3302SCarolineConcatto 8464ab3302SCarolineConcatto template <typename N> bool Pre(const N &node) { 8564ab3302SCarolineConcatto if constexpr (common::HasMember<const N *, ConstructNode>) { 8664ab3302SCarolineConcatto context_.PushConstruct(node); 8764ab3302SCarolineConcatto } 8864ab3302SCarolineConcatto Enter(node); 8964ab3302SCarolineConcatto return true; 9064ab3302SCarolineConcatto } 9164ab3302SCarolineConcatto template <typename N> void Post(const N &node) { 9264ab3302SCarolineConcatto Leave(node); 9364ab3302SCarolineConcatto if constexpr (common::HasMember<const N *, ConstructNode>) { 9464ab3302SCarolineConcatto context_.PopConstruct(); 9564ab3302SCarolineConcatto } 9664ab3302SCarolineConcatto } 9764ab3302SCarolineConcatto 9864ab3302SCarolineConcatto template <typename T> bool Pre(const parser::Statement<T> &node) { 9964ab3302SCarolineConcatto context_.set_location(node.source); 10064ab3302SCarolineConcatto Enter(node); 10164ab3302SCarolineConcatto return true; 10264ab3302SCarolineConcatto } 10364ab3302SCarolineConcatto template <typename T> bool Pre(const parser::UnlabeledStatement<T> &node) { 10464ab3302SCarolineConcatto context_.set_location(node.source); 10564ab3302SCarolineConcatto Enter(node); 10664ab3302SCarolineConcatto return true; 10764ab3302SCarolineConcatto } 10864ab3302SCarolineConcatto template <typename T> void Post(const parser::Statement<T> &node) { 10964ab3302SCarolineConcatto Leave(node); 11064ab3302SCarolineConcatto context_.set_location(std::nullopt); 11164ab3302SCarolineConcatto } 11264ab3302SCarolineConcatto template <typename T> void Post(const parser::UnlabeledStatement<T> &node) { 11364ab3302SCarolineConcatto Leave(node); 11464ab3302SCarolineConcatto context_.set_location(std::nullopt); 11564ab3302SCarolineConcatto } 11664ab3302SCarolineConcatto 11764ab3302SCarolineConcatto bool Walk(const parser::Program &program) { 11864ab3302SCarolineConcatto parser::Walk(program, *this); 11964ab3302SCarolineConcatto return !context_.AnyFatalError(); 12064ab3302SCarolineConcatto } 12164ab3302SCarolineConcatto 12264ab3302SCarolineConcatto private: 12364ab3302SCarolineConcatto SemanticsContext &context_; 12464ab3302SCarolineConcatto }; 12564ab3302SCarolineConcatto 126455ed8deSpeter klausler class MiscChecker : public virtual BaseChecker { 127c42f6314Speter klausler public: 128455ed8deSpeter klausler explicit MiscChecker(SemanticsContext &context) : context_{context} {} 129c42f6314Speter klausler void Leave(const parser::EntryStmt &) { 130c42f6314Speter klausler if (!context_.constructStack().empty()) { // C1571 131c42f6314Speter klausler context_.Say("ENTRY may not appear in an executable construct"_err_en_US); 132c42f6314Speter klausler } 133c42f6314Speter klausler } 134455ed8deSpeter klausler void Leave(const parser::AssignStmt &stmt) { 135455ed8deSpeter klausler CheckAssignGotoName(std::get<parser::Name>(stmt.t)); 136455ed8deSpeter klausler } 137455ed8deSpeter klausler void Leave(const parser::AssignedGotoStmt &stmt) { 138455ed8deSpeter klausler CheckAssignGotoName(std::get<parser::Name>(stmt.t)); 139455ed8deSpeter klausler } 140c42f6314Speter klausler 141c42f6314Speter klausler private: 142455ed8deSpeter klausler void CheckAssignGotoName(const parser::Name &name) { 143455ed8deSpeter klausler if (context_.HasError(name.symbol)) { 144455ed8deSpeter klausler return; 145455ed8deSpeter klausler } 146455ed8deSpeter klausler const Symbol &symbol{DEREF(name.symbol)}; 147455ed8deSpeter klausler auto type{evaluate::DynamicType::From(symbol)}; 148455ed8deSpeter klausler if (!IsVariableName(symbol) || symbol.Rank() != 0 || !type || 149455ed8deSpeter klausler type->category() != TypeCategory::Integer || 150455ed8deSpeter klausler type->kind() != 151455ed8deSpeter klausler context_.defaultKinds().GetDefaultKind(TypeCategory::Integer)) { 152455ed8deSpeter klausler context_ 153455ed8deSpeter klausler .Say(name.source, 154455ed8deSpeter klausler "'%s' must be a default integer scalar variable"_err_en_US, 155455ed8deSpeter klausler name.source) 156455ed8deSpeter klausler .Attach(symbol.name(), "Declaration of '%s'"_en_US, symbol.name()); 157455ed8deSpeter klausler } 158455ed8deSpeter klausler } 159455ed8deSpeter klausler 160c42f6314Speter klausler SemanticsContext &context_; 161c42f6314Speter klausler }; 162c42f6314Speter klausler 16333c27f28SPeter Klausler static void WarnUndefinedFunctionResult( 16433c27f28SPeter Klausler SemanticsContext &context, const Scope &scope) { 16533c27f28SPeter Klausler auto WasDefined{[&context](const Symbol &symbol) { 16633c27f28SPeter Klausler return context.IsSymbolDefined(symbol) || 16733c27f28SPeter Klausler IsInitialized(symbol, /*ignoreDataStatements=*/true, 16833c27f28SPeter Klausler /*ignoreAllocatable=*/true, /*ignorePointer=*/true); 16933c27f28SPeter Klausler }}; 17033c27f28SPeter Klausler if (const Symbol * symbol{scope.symbol()}) { 17133c27f28SPeter Klausler if (const auto *subp{symbol->detailsIf<SubprogramDetails>()}) { 17233c27f28SPeter Klausler if (subp->isFunction() && !subp->isInterface() && !subp->stmtFunction()) { 17333c27f28SPeter Klausler bool wasDefined{WasDefined(subp->result())}; 17433c27f28SPeter Klausler if (!wasDefined) { 17533c27f28SPeter Klausler // Definitions of ENTRY result variables also count. 17633c27f28SPeter Klausler for (const auto &pair : scope) { 17733c27f28SPeter Klausler const Symbol &local{*pair.second}; 17833c27f28SPeter Klausler if (IsFunctionResult(local) && WasDefined(local)) { 17933c27f28SPeter Klausler wasDefined = true; 18033c27f28SPeter Klausler break; 18133c27f28SPeter Klausler } 18233c27f28SPeter Klausler } 18333c27f28SPeter Klausler if (!wasDefined) { 1840f973ac7SPeter Klausler context.Warn(common::UsageWarning::UndefinedFunctionResult, 18533c27f28SPeter Klausler symbol->name(), "Function result is never defined"_warn_en_US); 18633c27f28SPeter Klausler } 18733c27f28SPeter Klausler } 18833c27f28SPeter Klausler } 18933c27f28SPeter Klausler } 19033c27f28SPeter Klausler } 19133c27f28SPeter Klausler if (!scope.IsModuleFile()) { 19233c27f28SPeter Klausler for (const Scope &child : scope.children()) { 19333c27f28SPeter Klausler WarnUndefinedFunctionResult(context, child); 19433c27f28SPeter Klausler } 19533c27f28SPeter Klausler } 19633c27f28SPeter Klausler } 19733c27f28SPeter Klausler 19864ab3302SCarolineConcatto using StatementSemanticsPass1 = ExprChecker; 199f674ddc1SPeter Klausler using StatementSemanticsPass2 = SemanticsVisitor<AllocateChecker, 200f674ddc1SPeter Klausler ArithmeticIfStmtChecker, AssignmentChecker, CaseChecker, CoarrayChecker, 201f674ddc1SPeter Klausler DataChecker, DeallocateChecker, DoForallChecker, IfStmtChecker, IoChecker, 202f674ddc1SPeter Klausler MiscChecker, NamelistChecker, NullifyChecker, PurityChecker, 203f674ddc1SPeter Klausler ReturnStmtChecker, SelectRankConstructChecker, SelectTypeChecker, 204f674ddc1SPeter Klausler StopChecker>; 20564ab3302SCarolineConcatto 20664ab3302SCarolineConcatto static bool PerformStatementSemantics( 20764ab3302SCarolineConcatto SemanticsContext &context, parser::Program &program) { 20852a1346bSPeter Klausler ResolveNames(context, program, context.globalScope()); 20964ab3302SCarolineConcatto RewriteParseTree(context, program); 2106aa3591eSpeter klausler ComputeOffsets(context, context.globalScope()); 21164ab3302SCarolineConcatto CheckDeclarations(context); 21264ab3302SCarolineConcatto StatementSemanticsPass1{context}.Walk(program); 213a20d48d7Speter klausler StatementSemanticsPass2 pass2{context}; 214a20d48d7Speter klausler pass2.Walk(program); 215c988e78fSValentin Clement if (context.languageFeatures().IsEnabled(common::LanguageFeature::OpenACC)) { 216c988e78fSValentin Clement SemanticsVisitor<AccStructureChecker>{context}.Walk(program); 217c988e78fSValentin Clement } 218c988e78fSValentin Clement if (context.languageFeatures().IsEnabled(common::LanguageFeature::OpenMP)) { 219c988e78fSValentin Clement SemanticsVisitor<OmpStructureChecker>{context}.Walk(program); 220c988e78fSValentin Clement } 221c988e78fSValentin Clement if (context.languageFeatures().IsEnabled(common::LanguageFeature::CUDA)) { 222c988e78fSValentin Clement SemanticsVisitor<CUDAChecker>{context}.Walk(program); 223f674ddc1SPeter Klausler } 224b949a6f5SPeter Klausler if (!context.messages().AnyFatalError()) { 22533c27f28SPeter Klausler WarnUndefinedFunctionResult(context, context.globalScope()); 22633c27f28SPeter Klausler } 227b949a6f5SPeter Klausler if (!context.AnyFatalError()) { 228a20d48d7Speter klausler pass2.CompileDataInitializationsIntoInitializers(); 229a20d48d7Speter klausler } 23064ab3302SCarolineConcatto return !context.AnyFatalError(); 23164ab3302SCarolineConcatto } 23264ab3302SCarolineConcatto 2332c8cb9acSJean Perier /// This class keeps track of the common block appearances with the biggest size 2342c8cb9acSJean Perier /// and with an initial value (if any) in a program. This allows reporting 2352c8cb9acSJean Perier /// conflicting initialization and warning about appearances of a same 2362c8cb9acSJean Perier /// named common block with different sizes. The biggest common block size and 2372c8cb9acSJean Perier /// initialization (if any) can later be provided so that lowering can generate 2382c8cb9acSJean Perier /// the correct symbol size and initial values, even when named common blocks 2392c8cb9acSJean Perier /// appears with different sizes and are initialized outside of block data. 2402c8cb9acSJean Perier class CommonBlockMap { 2412c8cb9acSJean Perier private: 2422c8cb9acSJean Perier struct CommonBlockInfo { 2432c8cb9acSJean Perier // Common block symbol for the appearance with the biggest size. 2442c8cb9acSJean Perier SymbolRef biggestSize; 2452c8cb9acSJean Perier // Common block symbol for the appearance with the initialized members (if 2462c8cb9acSJean Perier // any). 2472c8cb9acSJean Perier std::optional<SymbolRef> initialization; 2482c8cb9acSJean Perier }; 2492c8cb9acSJean Perier 2502c8cb9acSJean Perier public: 2512c8cb9acSJean Perier void MapCommonBlockAndCheckConflicts( 2522c8cb9acSJean Perier SemanticsContext &context, const Symbol &common) { 2532c8cb9acSJean Perier const Symbol *isInitialized{CommonBlockIsInitialized(common)}; 2546ffea74fSjeanPerier // Merge common according to the name they will have in the object files. 2556ffea74fSjeanPerier // This allows merging BIND(C) and non BIND(C) common block instead of 2566ffea74fSjeanPerier // later crashing. This "merge" matches what ifort/gfortran/nvfortran are 2576ffea74fSjeanPerier // doing and what a linker would do if the definition were in distinct 2586ffea74fSjeanPerier // files. 2596ffea74fSjeanPerier std::string commonName{ 2606ffea74fSjeanPerier GetCommonBlockObjectName(common, context.underscoring())}; 2616ffea74fSjeanPerier auto [it, firstAppearance] = commonBlocks_.insert({commonName, 2622c8cb9acSJean Perier isInitialized ? CommonBlockInfo{common, common} 2632c8cb9acSJean Perier : CommonBlockInfo{common, std::nullopt}}); 2642c8cb9acSJean Perier if (!firstAppearance) { 2652c8cb9acSJean Perier CommonBlockInfo &info{it->second}; 2662c8cb9acSJean Perier if (isInitialized) { 2672c8cb9acSJean Perier if (info.initialization.has_value() && 2682c8cb9acSJean Perier &**info.initialization != &common) { 2692c8cb9acSJean Perier // Use the location of the initialization in the error message because 2702c8cb9acSJean Perier // common block symbols may have no location if they are blank 2712c8cb9acSJean Perier // commons. 2722c8cb9acSJean Perier const Symbol &previousInit{ 2732c8cb9acSJean Perier DEREF(CommonBlockIsInitialized(**info.initialization))}; 2742c8cb9acSJean Perier context 2752c8cb9acSJean Perier .Say(isInitialized->name(), 2762c8cb9acSJean Perier "Multiple initialization of COMMON block /%s/"_err_en_US, 2772c8cb9acSJean Perier common.name()) 2782c8cb9acSJean Perier .Attach(previousInit.name(), 2792c8cb9acSJean Perier "Previous initialization of COMMON block /%s/"_en_US, 2802c8cb9acSJean Perier common.name()); 2812c8cb9acSJean Perier } else { 2822c8cb9acSJean Perier info.initialization = common; 2832c8cb9acSJean Perier } 2842c8cb9acSJean Perier } 2850f973ac7SPeter Klausler if (common.size() != info.biggestSize->size() && !common.name().empty()) { 2860f973ac7SPeter Klausler if (auto *msg{context.Warn(common::LanguageFeature::DistinctCommonSizes, 2870f973ac7SPeter Klausler common.name(), 2882c8cb9acSJean Perier "A named COMMON block should have the same size everywhere it appears (%zd bytes here)"_port_en_US, 2890f973ac7SPeter Klausler common.size())}) { 2900f973ac7SPeter Klausler msg->Attach(info.biggestSize->name(), 2912c8cb9acSJean Perier "Previously defined with a size of %zd bytes"_en_US, 2922c8cb9acSJean Perier info.biggestSize->size()); 2932c8cb9acSJean Perier } 2940f973ac7SPeter Klausler } 2952c8cb9acSJean Perier if (common.size() > info.biggestSize->size()) { 2962c8cb9acSJean Perier info.biggestSize = common; 2972c8cb9acSJean Perier } 2982c8cb9acSJean Perier } 2992c8cb9acSJean Perier } 3002c8cb9acSJean Perier 3012c8cb9acSJean Perier CommonBlockList GetCommonBlocks() const { 3022c8cb9acSJean Perier CommonBlockList result; 3032c8cb9acSJean Perier for (const auto &[_, blockInfo] : commonBlocks_) { 3042c8cb9acSJean Perier result.emplace_back( 3052c8cb9acSJean Perier std::make_pair(blockInfo.initialization ? *blockInfo.initialization 3062c8cb9acSJean Perier : blockInfo.biggestSize, 3072c8cb9acSJean Perier blockInfo.biggestSize->size())); 3082c8cb9acSJean Perier } 3092c8cb9acSJean Perier return result; 3102c8cb9acSJean Perier } 3112c8cb9acSJean Perier 3122c8cb9acSJean Perier private: 3132c8cb9acSJean Perier /// Return the symbol of an initialized member if a COMMON block 3142c8cb9acSJean Perier /// is initalized. Otherwise, return nullptr. 3152c8cb9acSJean Perier static Symbol *CommonBlockIsInitialized(const Symbol &common) { 3162c8cb9acSJean Perier const auto &commonDetails = 3172c8cb9acSJean Perier common.get<Fortran::semantics::CommonBlockDetails>(); 3182c8cb9acSJean Perier 3192c8cb9acSJean Perier for (const auto &member : commonDetails.objects()) { 3202c8cb9acSJean Perier if (IsInitialized(*member)) { 3212c8cb9acSJean Perier return &*member; 3222c8cb9acSJean Perier } 3232c8cb9acSJean Perier } 3242c8cb9acSJean Perier 3252c8cb9acSJean Perier // Common block may be initialized via initialized variables that are in an 3262c8cb9acSJean Perier // equivalence with the common block members. 3272c8cb9acSJean Perier for (const Fortran::semantics::EquivalenceSet &set : 3282c8cb9acSJean Perier common.owner().equivalenceSets()) { 3292c8cb9acSJean Perier for (const Fortran::semantics::EquivalenceObject &obj : set) { 3302c8cb9acSJean Perier if (!obj.symbol.test( 3312c8cb9acSJean Perier Fortran::semantics::Symbol::Flag::CompilerCreated)) { 3322c8cb9acSJean Perier if (FindCommonBlockContaining(obj.symbol) == &common && 3332c8cb9acSJean Perier IsInitialized(obj.symbol)) { 3342c8cb9acSJean Perier return &obj.symbol; 3352c8cb9acSJean Perier } 3362c8cb9acSJean Perier } 3372c8cb9acSJean Perier } 3382c8cb9acSJean Perier } 3392c8cb9acSJean Perier return nullptr; 3402c8cb9acSJean Perier } 3416ffea74fSjeanPerier 3426ffea74fSjeanPerier std::map<std::string, CommonBlockInfo> commonBlocks_; 3432c8cb9acSJean Perier }; 3442c8cb9acSJean Perier 34564ab3302SCarolineConcatto SemanticsContext::SemanticsContext( 34664ab3302SCarolineConcatto const common::IntrinsicTypeDefaultKinds &defaultKinds, 34764ab3302SCarolineConcatto const common::LanguageFeatureControl &languageFeatures, 3483b20a833SKrzysztof Parzyszek const common::LangOptions &langOpts, 34992a54197Speter klausler parser::AllCookedSources &allCookedSources) 35064ab3302SCarolineConcatto : defaultKinds_{defaultKinds}, languageFeatures_{languageFeatures}, 3513b20a833SKrzysztof Parzyszek langOpts_{langOpts}, allCookedSources_{allCookedSources}, 35264ab3302SCarolineConcatto intrinsics_{evaluate::IntrinsicProcTable::Configure(defaultKinds_)}, 35352a1346bSPeter Klausler globalScope_{*this}, intrinsicModulesScope_{globalScope_.MakeScope( 35452a1346bSPeter Klausler Scope::Kind::IntrinsicModules, nullptr)}, 35523c2bedfSPeter Klausler foldingContext_{parser::ContextualMessages{&messages_}, defaultKinds_, 356181eab27SjeanPerier intrinsics_, targetCharacteristics_, languageFeatures_, tempNames_} {} 35764ab3302SCarolineConcatto 35864ab3302SCarolineConcatto SemanticsContext::~SemanticsContext() {} 35964ab3302SCarolineConcatto 36064ab3302SCarolineConcatto int SemanticsContext::GetDefaultKind(TypeCategory category) const { 36164ab3302SCarolineConcatto return defaultKinds_.GetDefaultKind(category); 36264ab3302SCarolineConcatto } 36364ab3302SCarolineConcatto 36464ab3302SCarolineConcatto const DeclTypeSpec &SemanticsContext::MakeNumericType( 36564ab3302SCarolineConcatto TypeCategory category, int kind) { 36664ab3302SCarolineConcatto if (kind == 0) { 36764ab3302SCarolineConcatto kind = GetDefaultKind(category); 36864ab3302SCarolineConcatto } 36964ab3302SCarolineConcatto return globalScope_.MakeNumericType(category, KindExpr{kind}); 37064ab3302SCarolineConcatto } 37164ab3302SCarolineConcatto const DeclTypeSpec &SemanticsContext::MakeLogicalType(int kind) { 37264ab3302SCarolineConcatto if (kind == 0) { 37364ab3302SCarolineConcatto kind = GetDefaultKind(TypeCategory::Logical); 37464ab3302SCarolineConcatto } 37564ab3302SCarolineConcatto return globalScope_.MakeLogicalType(KindExpr{kind}); 37664ab3302SCarolineConcatto } 37764ab3302SCarolineConcatto 37864ab3302SCarolineConcatto bool SemanticsContext::AnyFatalError() const { 37964ab3302SCarolineConcatto return !messages_.empty() && 38064ab3302SCarolineConcatto (warningsAreErrors_ || messages_.AnyFatalError()); 38164ab3302SCarolineConcatto } 38264ab3302SCarolineConcatto bool SemanticsContext::HasError(const Symbol &symbol) { 383627e9007STim Keith return errorSymbols_.count(symbol) > 0; 38464ab3302SCarolineConcatto } 38564ab3302SCarolineConcatto bool SemanticsContext::HasError(const Symbol *symbol) { 386627e9007STim Keith return !symbol || HasError(*symbol); 38764ab3302SCarolineConcatto } 38864ab3302SCarolineConcatto bool SemanticsContext::HasError(const parser::Name &name) { 38964ab3302SCarolineConcatto return HasError(name.symbol); 39064ab3302SCarolineConcatto } 391627e9007STim Keith void SemanticsContext::SetError(const Symbol &symbol, bool value) { 39264ab3302SCarolineConcatto if (value) { 393627e9007STim Keith CheckError(symbol); 394627e9007STim Keith errorSymbols_.emplace(symbol); 39564ab3302SCarolineConcatto } 39664ab3302SCarolineConcatto } 397627e9007STim Keith void SemanticsContext::CheckError(const Symbol &symbol) { 398627e9007STim Keith if (!AnyFatalError()) { 399627e9007STim Keith std::string buf; 400627e9007STim Keith llvm::raw_string_ostream ss{buf}; 401627e9007STim Keith ss << symbol; 402627e9007STim Keith common::die( 403627e9007STim Keith "No error was reported but setting error on: %s", ss.str().c_str()); 404627e9007STim Keith } 40564ab3302SCarolineConcatto } 40664ab3302SCarolineConcatto 407e727bda1SPeter Klausler bool SemanticsContext::ScopeIndexComparator::operator()( 408e727bda1SPeter Klausler parser::CharBlock x, parser::CharBlock y) const { 409e727bda1SPeter Klausler return x.begin() < y.begin() || 410e727bda1SPeter Klausler (x.begin() == y.begin() && x.size() > y.size()); 411e727bda1SPeter Klausler } 412e727bda1SPeter Klausler 413e727bda1SPeter Klausler auto SemanticsContext::SearchScopeIndex(parser::CharBlock source) 414e727bda1SPeter Klausler -> ScopeIndex::iterator { 415e727bda1SPeter Klausler if (!scopeIndex_.empty()) { 416e727bda1SPeter Klausler auto iter{scopeIndex_.upper_bound(source)}; 417e727bda1SPeter Klausler auto begin{scopeIndex_.begin()}; 418e727bda1SPeter Klausler do { 419e727bda1SPeter Klausler --iter; 420e727bda1SPeter Klausler if (iter->first.Contains(source)) { 421e727bda1SPeter Klausler return iter; 422e727bda1SPeter Klausler } 423e727bda1SPeter Klausler } while (iter != begin); 424e727bda1SPeter Klausler } 425e727bda1SPeter Klausler return scopeIndex_.end(); 426e727bda1SPeter Klausler } 427e727bda1SPeter Klausler 42864ab3302SCarolineConcatto const Scope &SemanticsContext::FindScope(parser::CharBlock source) const { 42964ab3302SCarolineConcatto return const_cast<SemanticsContext *>(this)->FindScope(source); 43064ab3302SCarolineConcatto } 43164ab3302SCarolineConcatto 43264ab3302SCarolineConcatto Scope &SemanticsContext::FindScope(parser::CharBlock source) { 433e727bda1SPeter Klausler if (auto iter{SearchScopeIndex(source)}; iter != scopeIndex_.end()) { 434e727bda1SPeter Klausler return iter->second; 43564ab3302SCarolineConcatto } else { 43652a1346bSPeter Klausler common::die( 43752a1346bSPeter Klausler "SemanticsContext::FindScope(): invalid source location for '%s'", 43852a1346bSPeter Klausler source.ToString().c_str()); 43964ab3302SCarolineConcatto } 44064ab3302SCarolineConcatto } 44164ab3302SCarolineConcatto 442e727bda1SPeter Klausler void SemanticsContext::UpdateScopeIndex( 443e727bda1SPeter Klausler Scope &scope, parser::CharBlock newSource) { 444e727bda1SPeter Klausler if (scope.sourceRange().empty()) { 445e727bda1SPeter Klausler scopeIndex_.emplace(newSource, scope); 446e727bda1SPeter Klausler } else if (!scope.sourceRange().Contains(newSource)) { 447e727bda1SPeter Klausler auto iter{SearchScopeIndex(scope.sourceRange())}; 448e727bda1SPeter Klausler CHECK(iter != scopeIndex_.end()); 449e727bda1SPeter Klausler while (&iter->second != &scope) { 450e727bda1SPeter Klausler CHECK(iter != scopeIndex_.begin()); 451e727bda1SPeter Klausler --iter; 452e727bda1SPeter Klausler } 453e727bda1SPeter Klausler scopeIndex_.erase(iter); 454e727bda1SPeter Klausler scopeIndex_.emplace(newSource, scope); 455e727bda1SPeter Klausler } 456e727bda1SPeter Klausler } 457e727bda1SPeter Klausler 45873506256SPeter Klausler bool SemanticsContext::IsInModuleFile(parser::CharBlock source) const { 45973506256SPeter Klausler for (const Scope *scope{&FindScope(source)}; !scope->IsGlobal(); 46073506256SPeter Klausler scope = &scope->parent()) { 46173506256SPeter Klausler if (scope->IsModuleFile()) { 46273506256SPeter Klausler return true; 46373506256SPeter Klausler } 46473506256SPeter Klausler } 46573506256SPeter Klausler return false; 46673506256SPeter Klausler } 46773506256SPeter Klausler 46864ab3302SCarolineConcatto void SemanticsContext::PopConstruct() { 46964ab3302SCarolineConcatto CHECK(!constructStack_.empty()); 47064ab3302SCarolineConcatto constructStack_.pop_back(); 47164ab3302SCarolineConcatto } 47264ab3302SCarolineConcatto 4730f973ac7SPeter Klausler parser::Message *SemanticsContext::CheckIndexVarRedefine( 4740f973ac7SPeter Klausler const parser::CharBlock &location, const Symbol &variable, 4750f973ac7SPeter Klausler parser::MessageFixedText &&message) { 476a50bb84eSpeter klausler const Symbol &symbol{ResolveAssociations(variable)}; 477a50bb84eSpeter klausler auto it{activeIndexVars_.find(symbol)}; 47864ab3302SCarolineConcatto if (it != activeIndexVars_.end()) { 47964ab3302SCarolineConcatto std::string kind{EnumToString(it->second.kind)}; 4800f973ac7SPeter Klausler return &Say(location, std::move(message), kind, symbol.name()) 4810f973ac7SPeter Klausler .Attach( 4820f973ac7SPeter Klausler it->second.location, "Enclosing %s construct"_en_US, kind); 4830f973ac7SPeter Klausler } else { 4840f973ac7SPeter Klausler return nullptr; 48564ab3302SCarolineConcatto } 48664ab3302SCarolineConcatto } 48764ab3302SCarolineConcatto 48864ab3302SCarolineConcatto void SemanticsContext::WarnIndexVarRedefine( 48964ab3302SCarolineConcatto const parser::CharBlock &location, const Symbol &variable) { 490505f6da1SPeter Klausler if (ShouldWarn(common::UsageWarning::IndexVarRedefinition)) { 4910f973ac7SPeter Klausler if (auto *msg{CheckIndexVarRedefine(location, variable, 4920f973ac7SPeter Klausler "Possible redefinition of %s variable '%s'"_warn_en_US)}) { 4930f973ac7SPeter Klausler msg->set_usageWarning(common::UsageWarning::IndexVarRedefinition); 4940f973ac7SPeter Klausler } 49564ab3302SCarolineConcatto } 496505f6da1SPeter Klausler } 49764ab3302SCarolineConcatto 49864ab3302SCarolineConcatto void SemanticsContext::CheckIndexVarRedefine( 49964ab3302SCarolineConcatto const parser::CharBlock &location, const Symbol &variable) { 50064ab3302SCarolineConcatto CheckIndexVarRedefine( 50164ab3302SCarolineConcatto location, variable, "Cannot redefine %s variable '%s'"_err_en_US); 50264ab3302SCarolineConcatto } 50364ab3302SCarolineConcatto 50464ab3302SCarolineConcatto void SemanticsContext::CheckIndexVarRedefine(const parser::Variable &variable) { 50564ab3302SCarolineConcatto if (const Symbol * entity{GetLastName(variable).symbol}) { 50664ab3302SCarolineConcatto CheckIndexVarRedefine(variable.GetSource(), *entity); 50764ab3302SCarolineConcatto } 50864ab3302SCarolineConcatto } 50964ab3302SCarolineConcatto 51064ab3302SCarolineConcatto void SemanticsContext::CheckIndexVarRedefine(const parser::Name &name) { 51164ab3302SCarolineConcatto if (const Symbol * entity{name.symbol}) { 51264ab3302SCarolineConcatto CheckIndexVarRedefine(name.source, *entity); 51364ab3302SCarolineConcatto } 51464ab3302SCarolineConcatto } 51564ab3302SCarolineConcatto 51664ab3302SCarolineConcatto void SemanticsContext::ActivateIndexVar( 51764ab3302SCarolineConcatto const parser::Name &name, IndexVarKind kind) { 51864ab3302SCarolineConcatto CheckIndexVarRedefine(name); 51964ab3302SCarolineConcatto if (const Symbol * indexVar{name.symbol}) { 520a50bb84eSpeter klausler activeIndexVars_.emplace( 521a50bb84eSpeter klausler ResolveAssociations(*indexVar), IndexVarInfo{name.source, kind}); 52264ab3302SCarolineConcatto } 52364ab3302SCarolineConcatto } 52464ab3302SCarolineConcatto 52564ab3302SCarolineConcatto void SemanticsContext::DeactivateIndexVar(const parser::Name &name) { 52664ab3302SCarolineConcatto if (Symbol * indexVar{name.symbol}) { 527a50bb84eSpeter klausler auto it{activeIndexVars_.find(ResolveAssociations(*indexVar))}; 52864ab3302SCarolineConcatto if (it != activeIndexVars_.end() && it->second.location == name.source) { 52964ab3302SCarolineConcatto activeIndexVars_.erase(it); 53064ab3302SCarolineConcatto } 53164ab3302SCarolineConcatto } 53264ab3302SCarolineConcatto } 53364ab3302SCarolineConcatto 53464ab3302SCarolineConcatto SymbolVector SemanticsContext::GetIndexVars(IndexVarKind kind) { 53564ab3302SCarolineConcatto SymbolVector result; 53664ab3302SCarolineConcatto for (const auto &[symbol, info] : activeIndexVars_) { 53764ab3302SCarolineConcatto if (info.kind == kind) { 53864ab3302SCarolineConcatto result.push_back(symbol); 53964ab3302SCarolineConcatto } 54064ab3302SCarolineConcatto } 54164ab3302SCarolineConcatto return result; 54264ab3302SCarolineConcatto } 54364ab3302SCarolineConcatto 5441bd083b5Speter klausler SourceName SemanticsContext::SaveTempName(std::string &&name) { 5451bd083b5Speter klausler return {*tempNames_.emplace(std::move(name)).first}; 5461bd083b5Speter klausler } 5471bd083b5Speter klausler 5484ac617f4Speter klausler SourceName SemanticsContext::GetTempName(const Scope &scope) { 5494ac617f4Speter klausler for (const auto &str : tempNames_) { 550c14cf92bSPeter Klausler if (IsTempName(str)) { 5514ac617f4Speter klausler SourceName name{str}; 5524ac617f4Speter klausler if (scope.find(name) == scope.end()) { 5534ac617f4Speter klausler return name; 5544ac617f4Speter klausler } 5554ac617f4Speter klausler } 5561bd083b5Speter klausler } 5571bd083b5Speter klausler return SaveTempName(".F18."s + std::to_string(tempNames_.size())); 5584ac617f4Speter klausler } 5594ac617f4Speter klausler 560c14cf92bSPeter Klausler bool SemanticsContext::IsTempName(const std::string &name) { 561c14cf92bSPeter Klausler return name.size() > 5 && name.substr(0, 5) == ".F18."; 562c14cf92bSPeter Klausler } 563c14cf92bSPeter Klausler 56452711fb8Speter klausler Scope *SemanticsContext::GetBuiltinModule(const char *name) { 56552a1346bSPeter Klausler return ModFileReader{*this}.Read(SourceName{name, std::strlen(name)}, 566f7a15e00SPeter Klausler true /*intrinsic*/, nullptr, /*silent=*/true); 56752711fb8Speter klausler } 56852711fb8Speter klausler 56952711fb8Speter klausler void SemanticsContext::UseFortranBuiltinsModule() { 57052711fb8Speter klausler if (builtinsScope_ == nullptr) { 57152711fb8Speter klausler builtinsScope_ = GetBuiltinModule("__fortran_builtins"); 57252711fb8Speter klausler if (builtinsScope_) { 57352711fb8Speter klausler intrinsics_.SupplyBuiltins(*builtinsScope_); 57452711fb8Speter klausler } 57552711fb8Speter klausler } 57652711fb8Speter klausler } 57752711fb8Speter klausler 5787e82379dSKelvin Li void SemanticsContext::UsePPCBuiltinTypesModule() { 579ef934174SKelvin Li if (ppcBuiltinTypesScope_ == nullptr) { 5807e82379dSKelvin Li ppcBuiltinTypesScope_ = GetBuiltinModule("__ppc_types"); 581ef934174SKelvin Li } 582ef934174SKelvin Li } 583ef934174SKelvin Li 584f674ddc1SPeter Klausler const Scope &SemanticsContext::GetCUDABuiltinsScope() { 585f674ddc1SPeter Klausler if (!cudaBuiltinsScope_) { 586f674ddc1SPeter Klausler cudaBuiltinsScope_ = GetBuiltinModule("__cuda_builtins"); 587f674ddc1SPeter Klausler CHECK(cudaBuiltinsScope_.value() != nullptr); 58827f71807SPeter Klausler } 589f674ddc1SPeter Klausler return **cudaBuiltinsScope_; 59027f71807SPeter Klausler } 59127f71807SPeter Klausler 5926d50a79bSValentin Clement (バレンタイン クレメン) const Scope &SemanticsContext::GetCUDADeviceScope() { 5936d50a79bSValentin Clement (バレンタイン クレメン) if (!cudaDeviceScope_) { 5946d50a79bSValentin Clement (バレンタイン クレメン) cudaDeviceScope_ = GetBuiltinModule("cudadevice"); 5956d50a79bSValentin Clement (バレンタイン クレメン) CHECK(cudaDeviceScope_.value() != nullptr); 5966d50a79bSValentin Clement (バレンタイン クレメン) } 5976d50a79bSValentin Clement (バレンタイン クレメン) return **cudaDeviceScope_; 5986d50a79bSValentin Clement (バレンタイン クレメン) } 5996d50a79bSValentin Clement (バレンタイン クレメン) 6007e82379dSKelvin Li void SemanticsContext::UsePPCBuiltinsModule() { 601838a4d34SKelvin Li if (ppcBuiltinsScope_ == nullptr) { 6027e82379dSKelvin Li ppcBuiltinsScope_ = GetBuiltinModule("__ppc_intrinsics"); 603838a4d34SKelvin Li } 604838a4d34SKelvin Li } 605838a4d34SKelvin Li 606f4bb211aSPeter Klausler parser::Program &SemanticsContext::SaveParseTree(parser::Program &&tree) { 607f4bb211aSPeter Klausler return modFileParseTrees_.emplace_back(std::move(tree)); 608f4bb211aSPeter Klausler } 609f4bb211aSPeter Klausler 61064ab3302SCarolineConcatto bool Semantics::Perform() { 61152711fb8Speter klausler // Implicitly USE the __Fortran_builtins module so that special types 61252711fb8Speter klausler // (e.g., __builtin_team_type) are available to semantics, esp. for 61352711fb8Speter klausler // intrinsic checking. 61452711fb8Speter klausler if (!program_.v.empty()) { 61552711fb8Speter klausler const auto *frontModule{std::get_if<common::Indirection<parser::Module>>( 61652711fb8Speter klausler &program_.v.front().u)}; 61752711fb8Speter klausler if (frontModule && 618838a4d34SKelvin Li (std::get<parser::Statement<parser::ModuleStmt>>(frontModule->value().t) 619838a4d34SKelvin Li .statement.v.source == "__fortran_builtins" || 620838a4d34SKelvin Li std::get<parser::Statement<parser::ModuleStmt>>( 621838a4d34SKelvin Li frontModule->value().t) 6227e82379dSKelvin Li .statement.v.source == "__ppc_types")) { 62352711fb8Speter klausler // Don't try to read the builtins module when we're actually building it. 624a9e1d2e7SKelvin Li } else if (frontModule && 6252c2d427cSKelvin Li (std::get<parser::Statement<parser::ModuleStmt>>(frontModule->value().t) 6262c2d427cSKelvin Li .statement.v.source == "__ppc_intrinsics" || 6272c2d427cSKelvin Li std::get<parser::Statement<parser::ModuleStmt>>( 6282c2d427cSKelvin Li frontModule->value().t) 6292c2d427cSKelvin Li .statement.v.source == "mma")) { 630a9e1d2e7SKelvin Li // The derived type definition for the vectors is needed. 6317e82379dSKelvin Li context_.UsePPCBuiltinTypesModule(); 63252711fb8Speter klausler } else { 63352711fb8Speter klausler context_.UseFortranBuiltinsModule(); 634838a4d34SKelvin Li llvm::Triple targetTriple{llvm::Triple( 635838a4d34SKelvin Li llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple()))}; 6367e82379dSKelvin Li // Only use __ppc_intrinsics module when targetting PowerPC arch 637a9e1d2e7SKelvin Li if (context_.targetCharacteristics().isPPC()) { 6387e82379dSKelvin Li context_.UsePPCBuiltinTypesModule(); 6397e82379dSKelvin Li context_.UsePPCBuiltinsModule(); 640838a4d34SKelvin Li } 64152711fb8Speter klausler } 64252711fb8Speter klausler } 64364ab3302SCarolineConcatto return ValidateLabels(context_, program_) && 64464ab3302SCarolineConcatto parser::CanonicalizeDo(program_) && // force line break 6459aa3dca8SValentin Clement CanonicalizeAcc(context_.messages(), program_) && 64664ab3302SCarolineConcatto CanonicalizeOmp(context_.messages(), program_) && 647f674ddc1SPeter Klausler CanonicalizeCUDA(program_) && 64864ab3302SCarolineConcatto PerformStatementSemantics(context_, program_) && 649c734d77bSTom Eccles CanonicalizeDirectives(context_.messages(), program_) && 65065987954SPeter Klausler ModFileWriter{context_} 65165987954SPeter Klausler .set_hermeticModuleFileOutput(hermeticModuleFileOutput_) 65265987954SPeter Klausler .WriteAll(); 65364ab3302SCarolineConcatto } 65464ab3302SCarolineConcatto 655f2e80893SPeter Klausler void Semantics::EmitMessages(llvm::raw_ostream &os) { 656f2e80893SPeter Klausler // Resolve the CharBlock locations of the Messages to ProvenanceRanges 657f2e80893SPeter Klausler // so messages from parsing and semantics are intermixed in source order. 658f2e80893SPeter Klausler context_.messages().ResolveProvenances(context_.allCookedSources()); 65992a54197Speter klausler context_.messages().Emit(os, context_.allCookedSources()); 66064ab3302SCarolineConcatto } 66164ab3302SCarolineConcatto 662d1e4a2d3SPeter Klausler void SemanticsContext::DumpSymbols(llvm::raw_ostream &os) { 663d1e4a2d3SPeter Klausler DoDumpSymbols(os, globalScope()); 66464ab3302SCarolineConcatto } 66564ab3302SCarolineConcatto 666*4f2b65fbSPeter Klausler ProgramTree &SemanticsContext::SaveProgramTree(ProgramTree &&tree) { 667*4f2b65fbSPeter Klausler return programTrees_.emplace_back(std::move(tree)); 668*4f2b65fbSPeter Klausler } 669*4f2b65fbSPeter Klausler 670d1e4a2d3SPeter Klausler void Semantics::DumpSymbols(llvm::raw_ostream &os) { context_.DumpSymbols(os); } 671d1e4a2d3SPeter Klausler 6728670e499SCaroline Concatto void Semantics::DumpSymbolsSources(llvm::raw_ostream &os) const { 67364ab3302SCarolineConcatto NameToSymbolMap symbols; 67464ab3302SCarolineConcatto GetSymbolNames(context_.globalScope(), symbols); 67592a54197Speter klausler const parser::AllCookedSources &allCooked{context_.allCookedSources()}; 67664ab3302SCarolineConcatto for (const auto &pair : symbols) { 67764ab3302SCarolineConcatto const Symbol &symbol{pair.second}; 67892a54197Speter klausler if (auto sourceInfo{allCooked.GetSourcePositionRange(symbol.name())}) { 679e12ffe6aSPeter Klausler os << symbol.name().ToString() << ": " << sourceInfo->first.path << ", " 680e12ffe6aSPeter Klausler << sourceInfo->first.line << ", " << sourceInfo->first.column << "-" 681e12ffe6aSPeter Klausler << sourceInfo->second.column << "\n"; 68264ab3302SCarolineConcatto } else if (symbol.has<semantics::UseDetails>()) { 68364ab3302SCarolineConcatto os << symbol.name().ToString() << ": " 68464ab3302SCarolineConcatto << symbol.GetUltimate().owner().symbol()->name().ToString() << "\n"; 68564ab3302SCarolineConcatto } 68664ab3302SCarolineConcatto } 68764ab3302SCarolineConcatto } 68864ab3302SCarolineConcatto 6898670e499SCaroline Concatto void DoDumpSymbols(llvm::raw_ostream &os, const Scope &scope, int indent) { 69064ab3302SCarolineConcatto PutIndent(os, indent); 69164ab3302SCarolineConcatto os << Scope::EnumToString(scope.kind()) << " scope:"; 69264ab3302SCarolineConcatto if (const auto *symbol{scope.symbol()}) { 69364ab3302SCarolineConcatto os << ' ' << symbol->name(); 69464ab3302SCarolineConcatto } 6954fede8bcSpeter klausler if (scope.alignment().has_value()) { 6964fede8bcSpeter klausler os << " size=" << scope.size() << " alignment=" << *scope.alignment(); 697c353ebbfSTim Keith } 698c353ebbfSTim Keith if (scope.derivedTypeSpec()) { 699c353ebbfSTim Keith os << " instantiation of " << *scope.derivedTypeSpec(); 700c353ebbfSTim Keith } 701f674ddc1SPeter Klausler os << " sourceRange=" << scope.sourceRange().size() << " bytes\n"; 70264ab3302SCarolineConcatto ++indent; 70364ab3302SCarolineConcatto for (const auto &pair : scope) { 70464ab3302SCarolineConcatto const auto &symbol{*pair.second}; 70564ab3302SCarolineConcatto PutIndent(os, indent); 70664ab3302SCarolineConcatto os << symbol << '\n'; 70764ab3302SCarolineConcatto if (const auto *details{symbol.detailsIf<GenericDetails>()}) { 70864ab3302SCarolineConcatto if (const auto &type{details->derivedType()}) { 70964ab3302SCarolineConcatto PutIndent(os, indent); 71064ab3302SCarolineConcatto os << *type << '\n'; 71164ab3302SCarolineConcatto } 71264ab3302SCarolineConcatto } 71364ab3302SCarolineConcatto } 71464ab3302SCarolineConcatto if (!scope.equivalenceSets().empty()) { 71564ab3302SCarolineConcatto PutIndent(os, indent); 71664ab3302SCarolineConcatto os << "Equivalence Sets:"; 71764ab3302SCarolineConcatto for (const auto &set : scope.equivalenceSets()) { 71864ab3302SCarolineConcatto os << ' '; 71964ab3302SCarolineConcatto char sep = '('; 72064ab3302SCarolineConcatto for (const auto &object : set) { 72164ab3302SCarolineConcatto os << sep << object.AsFortran(); 72264ab3302SCarolineConcatto sep = ','; 72364ab3302SCarolineConcatto } 72464ab3302SCarolineConcatto os << ')'; 72564ab3302SCarolineConcatto } 72664ab3302SCarolineConcatto os << '\n'; 72764ab3302SCarolineConcatto } 72864ab3302SCarolineConcatto if (!scope.crayPointers().empty()) { 72964ab3302SCarolineConcatto PutIndent(os, indent); 73064ab3302SCarolineConcatto os << "Cray Pointers:"; 73164ab3302SCarolineConcatto for (const auto &[pointee, pointer] : scope.crayPointers()) { 73264ab3302SCarolineConcatto os << " (" << pointer->name() << ',' << pointee << ')'; 73364ab3302SCarolineConcatto } 73464ab3302SCarolineConcatto } 73564ab3302SCarolineConcatto for (const auto &pair : scope.commonBlocks()) { 73664ab3302SCarolineConcatto const auto &symbol{*pair.second}; 73764ab3302SCarolineConcatto PutIndent(os, indent); 73864ab3302SCarolineConcatto os << symbol << '\n'; 73964ab3302SCarolineConcatto } 74064ab3302SCarolineConcatto for (const auto &child : scope.children()) { 74164ab3302SCarolineConcatto DoDumpSymbols(os, child, indent); 74264ab3302SCarolineConcatto } 74364ab3302SCarolineConcatto --indent; 74464ab3302SCarolineConcatto } 74564ab3302SCarolineConcatto 7468670e499SCaroline Concatto static void PutIndent(llvm::raw_ostream &os, int indent) { 74764ab3302SCarolineConcatto for (int i = 0; i < indent; ++i) { 74864ab3302SCarolineConcatto os << " "; 74964ab3302SCarolineConcatto } 75064ab3302SCarolineConcatto } 7512c8cb9acSJean Perier 7522c8cb9acSJean Perier void SemanticsContext::MapCommonBlockAndCheckConflicts(const Symbol &common) { 7532c8cb9acSJean Perier if (!commonBlockMap_) { 7542c8cb9acSJean Perier commonBlockMap_ = std::make_unique<CommonBlockMap>(); 7552c8cb9acSJean Perier } 7562c8cb9acSJean Perier commonBlockMap_->MapCommonBlockAndCheckConflicts(*this, common); 7572c8cb9acSJean Perier } 7582c8cb9acSJean Perier 7592c8cb9acSJean Perier CommonBlockList SemanticsContext::GetCommonBlocks() const { 7602c8cb9acSJean Perier if (commonBlockMap_) { 7612c8cb9acSJean Perier return commonBlockMap_->GetCommonBlocks(); 7622c8cb9acSJean Perier } 7632c8cb9acSJean Perier return {}; 7642c8cb9acSJean Perier } 7652c8cb9acSJean Perier 76633c27f28SPeter Klausler void SemanticsContext::NoteDefinedSymbol(const Symbol &symbol) { 76733c27f28SPeter Klausler isDefined_.insert(symbol); 76833c27f28SPeter Klausler } 76933c27f28SPeter Klausler 77033c27f28SPeter Klausler bool SemanticsContext::IsSymbolDefined(const Symbol &symbol) const { 77133c27f28SPeter Klausler return isDefined_.find(symbol) != isDefined_.end(); 77233c27f28SPeter Klausler } 77333c27f28SPeter Klausler 7747a77c20dSpeter klausler } // namespace Fortran::semantics 775