1 //===-- lib/Semantics/semantics.cpp ---------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "flang/Semantics/semantics.h" 10 #include "assignment.h" 11 #include "canonicalize-do.h" 12 #include "canonicalize-omp.h" 13 #include "check-allocate.h" 14 #include "check-arithmeticif.h" 15 #include "check-coarray.h" 16 #include "check-data.h" 17 #include "check-deallocate.h" 18 #include "check-declarations.h" 19 #include "check-do-forall.h" 20 #include "check-if-stmt.h" 21 #include "check-io.h" 22 #include "check-namelist.h" 23 #include "check-nullify.h" 24 #include "check-omp-structure.h" 25 #include "check-purity.h" 26 #include "check-return.h" 27 #include "check-stop.h" 28 #include "mod-file.h" 29 #include "resolve-labels.h" 30 #include "resolve-names.h" 31 #include "rewrite-parse-tree.h" 32 #include "flang/Common/default-kinds.h" 33 #include "flang/Parser/parse-tree-visitor.h" 34 #include "flang/Parser/tools.h" 35 #include "flang/Semantics/expression.h" 36 #include "flang/Semantics/scope.h" 37 #include "flang/Semantics/symbol.h" 38 39 namespace Fortran::semantics { 40 41 using NameToSymbolMap = std::map<const char *, SymbolRef>; 42 static void DoDumpSymbols(std::ostream &, const Scope &, int indent = 0); 43 static void PutIndent(std::ostream &, int indent); 44 45 static void GetSymbolNames(const Scope &scope, NameToSymbolMap &symbols) { 46 // Finds all symbol names in the scope without collecting duplicates. 47 for (const auto &pair : scope) { 48 symbols.emplace(pair.second->name().begin(), *pair.second); 49 } 50 for (const auto &pair : scope.commonBlocks()) { 51 symbols.emplace(pair.second->name().begin(), *pair.second); 52 } 53 for (const auto &child : scope.children()) { 54 GetSymbolNames(child, symbols); 55 } 56 } 57 58 // A parse tree visitor that calls Enter/Leave functions from each checker 59 // class C supplied as template parameters. Enter is called before the node's 60 // children are visited, Leave is called after. No two checkers may have the 61 // same Enter or Leave function. Each checker must be constructible from 62 // SemanticsContext and have BaseChecker as a virtual base class. 63 template<typename... C> class SemanticsVisitor : public virtual C... { 64 public: 65 using C::Enter...; 66 using C::Leave...; 67 using BaseChecker::Enter; 68 using BaseChecker::Leave; 69 SemanticsVisitor(SemanticsContext &context) 70 : C{context}..., context_{context} {} 71 72 template<typename N> bool Pre(const N &node) { 73 if constexpr (common::HasMember<const N *, ConstructNode>) { 74 context_.PushConstruct(node); 75 } 76 Enter(node); 77 return true; 78 } 79 template<typename N> void Post(const N &node) { 80 Leave(node); 81 if constexpr (common::HasMember<const N *, ConstructNode>) { 82 context_.PopConstruct(); 83 } 84 } 85 86 template<typename T> bool Pre(const parser::Statement<T> &node) { 87 context_.set_location(node.source); 88 Enter(node); 89 return true; 90 } 91 template<typename T> bool Pre(const parser::UnlabeledStatement<T> &node) { 92 context_.set_location(node.source); 93 Enter(node); 94 return true; 95 } 96 template<typename T> void Post(const parser::Statement<T> &node) { 97 Leave(node); 98 context_.set_location(std::nullopt); 99 } 100 template<typename T> void Post(const parser::UnlabeledStatement<T> &node) { 101 Leave(node); 102 context_.set_location(std::nullopt); 103 } 104 105 bool Walk(const parser::Program &program) { 106 parser::Walk(program, *this); 107 return !context_.AnyFatalError(); 108 } 109 110 private: 111 SemanticsContext &context_; 112 }; 113 114 using StatementSemanticsPass1 = ExprChecker; 115 using StatementSemanticsPass2 = SemanticsVisitor<AllocateChecker, 116 ArithmeticIfStmtChecker, AssignmentChecker, CoarrayChecker, DataChecker, 117 DeallocateChecker, DoForallChecker, IfStmtChecker, IoChecker, 118 NamelistChecker, NullifyChecker, OmpStructureChecker, PurityChecker, 119 ReturnStmtChecker, StopChecker>; 120 121 static bool PerformStatementSemantics( 122 SemanticsContext &context, parser::Program &program) { 123 ResolveNames(context, program); 124 RewriteParseTree(context, program); 125 CheckDeclarations(context); 126 StatementSemanticsPass1{context}.Walk(program); 127 StatementSemanticsPass2{context}.Walk(program); 128 return !context.AnyFatalError(); 129 } 130 131 SemanticsContext::SemanticsContext( 132 const common::IntrinsicTypeDefaultKinds &defaultKinds, 133 const common::LanguageFeatureControl &languageFeatures, 134 parser::AllSources &allSources) 135 : defaultKinds_{defaultKinds}, languageFeatures_{languageFeatures}, 136 allSources_{allSources}, 137 intrinsics_{evaluate::IntrinsicProcTable::Configure(defaultKinds_)}, 138 foldingContext_{ 139 parser::ContextualMessages{&messages_}, defaultKinds_, intrinsics_} {} 140 141 SemanticsContext::~SemanticsContext() {} 142 143 int SemanticsContext::GetDefaultKind(TypeCategory category) const { 144 return defaultKinds_.GetDefaultKind(category); 145 } 146 147 bool SemanticsContext::IsEnabled(common::LanguageFeature feature) const { 148 return languageFeatures_.IsEnabled(feature); 149 } 150 151 bool SemanticsContext::ShouldWarn(common::LanguageFeature feature) const { 152 return languageFeatures_.ShouldWarn(feature); 153 } 154 155 const DeclTypeSpec &SemanticsContext::MakeNumericType( 156 TypeCategory category, int kind) { 157 if (kind == 0) { 158 kind = GetDefaultKind(category); 159 } 160 return globalScope_.MakeNumericType(category, KindExpr{kind}); 161 } 162 const DeclTypeSpec &SemanticsContext::MakeLogicalType(int kind) { 163 if (kind == 0) { 164 kind = GetDefaultKind(TypeCategory::Logical); 165 } 166 return globalScope_.MakeLogicalType(KindExpr{kind}); 167 } 168 169 bool SemanticsContext::AnyFatalError() const { 170 return !messages_.empty() && 171 (warningsAreErrors_ || messages_.AnyFatalError()); 172 } 173 bool SemanticsContext::HasError(const Symbol &symbol) { 174 return CheckError(symbol.test(Symbol::Flag::Error)); 175 } 176 bool SemanticsContext::HasError(const Symbol *symbol) { 177 return CheckError(!symbol || HasError(*symbol)); 178 } 179 bool SemanticsContext::HasError(const parser::Name &name) { 180 return HasError(name.symbol); 181 } 182 void SemanticsContext::SetError(Symbol &symbol, bool value) { 183 if (value) { 184 CHECK(AnyFatalError()); 185 symbol.set(Symbol::Flag::Error); 186 } 187 } 188 bool SemanticsContext::CheckError(bool error) { 189 CHECK(!error || AnyFatalError()); 190 return error; 191 } 192 193 const Scope &SemanticsContext::FindScope(parser::CharBlock source) const { 194 return const_cast<SemanticsContext *>(this)->FindScope(source); 195 } 196 197 Scope &SemanticsContext::FindScope(parser::CharBlock source) { 198 if (auto *scope{globalScope_.FindScope(source)}) { 199 return *scope; 200 } else { 201 common::die("SemanticsContext::FindScope(): invalid source location"); 202 } 203 } 204 205 void SemanticsContext::PopConstruct() { 206 CHECK(!constructStack_.empty()); 207 constructStack_.pop_back(); 208 } 209 210 void SemanticsContext::CheckIndexVarRedefine(const parser::CharBlock &location, 211 const Symbol &variable, parser::MessageFixedText &&message) { 212 if (const Symbol * root{GetAssociationRoot(variable)}) { 213 auto it{activeIndexVars_.find(*root)}; 214 if (it != activeIndexVars_.end()) { 215 std::string kind{EnumToString(it->second.kind)}; 216 Say(location, std::move(message), kind, root->name()) 217 .Attach(it->second.location, "Enclosing %s construct"_en_US, kind); 218 } 219 } 220 } 221 222 void SemanticsContext::WarnIndexVarRedefine( 223 const parser::CharBlock &location, const Symbol &variable) { 224 CheckIndexVarRedefine( 225 location, variable, "Possible redefinition of %s variable '%s'"_en_US); 226 } 227 228 void SemanticsContext::CheckIndexVarRedefine( 229 const parser::CharBlock &location, const Symbol &variable) { 230 CheckIndexVarRedefine( 231 location, variable, "Cannot redefine %s variable '%s'"_err_en_US); 232 } 233 234 void SemanticsContext::CheckIndexVarRedefine(const parser::Variable &variable) { 235 if (const Symbol * entity{GetLastName(variable).symbol}) { 236 CheckIndexVarRedefine(variable.GetSource(), *entity); 237 } 238 } 239 240 void SemanticsContext::CheckIndexVarRedefine(const parser::Name &name) { 241 if (const Symbol * entity{name.symbol}) { 242 CheckIndexVarRedefine(name.source, *entity); 243 } 244 } 245 246 void SemanticsContext::ActivateIndexVar( 247 const parser::Name &name, IndexVarKind kind) { 248 CheckIndexVarRedefine(name); 249 if (const Symbol * indexVar{name.symbol}) { 250 if (const Symbol * root{GetAssociationRoot(*indexVar)}) { 251 activeIndexVars_.emplace(*root, IndexVarInfo{name.source, kind}); 252 } 253 } 254 } 255 256 void SemanticsContext::DeactivateIndexVar(const parser::Name &name) { 257 if (Symbol * indexVar{name.symbol}) { 258 if (const Symbol * root{GetAssociationRoot(*indexVar)}) { 259 auto it{activeIndexVars_.find(*root)}; 260 if (it != activeIndexVars_.end() && it->second.location == name.source) { 261 activeIndexVars_.erase(it); 262 } 263 } 264 } 265 } 266 267 SymbolVector SemanticsContext::GetIndexVars(IndexVarKind kind) { 268 SymbolVector result; 269 for (const auto &[symbol, info] : activeIndexVars_) { 270 if (info.kind == kind) { 271 result.push_back(symbol); 272 } 273 } 274 return result; 275 } 276 277 bool Semantics::Perform() { 278 return ValidateLabels(context_, program_) && 279 parser::CanonicalizeDo(program_) && // force line break 280 CanonicalizeOmp(context_.messages(), program_) && 281 PerformStatementSemantics(context_, program_) && 282 ModFileWriter{context_}.WriteAll(); 283 } 284 285 void Semantics::EmitMessages(std::ostream &os) const { 286 context_.messages().Emit(os, cooked_); 287 } 288 289 void Semantics::DumpSymbols(std::ostream &os) { 290 DoDumpSymbols(os, context_.globalScope()); 291 } 292 293 void Semantics::DumpSymbolsSources(std::ostream &os) const { 294 NameToSymbolMap symbols; 295 GetSymbolNames(context_.globalScope(), symbols); 296 for (const auto &pair : symbols) { 297 const Symbol &symbol{pair.second}; 298 if (auto sourceInfo{cooked_.GetSourcePositionRange(symbol.name())}) { 299 os << symbol.name().ToString() << ": " << sourceInfo->first.file.path() 300 << ", " << sourceInfo->first.line << ", " << sourceInfo->first.column 301 << "-" << sourceInfo->second.column << "\n"; 302 } else if (symbol.has<semantics::UseDetails>()) { 303 os << symbol.name().ToString() << ": " 304 << symbol.GetUltimate().owner().symbol()->name().ToString() << "\n"; 305 } 306 } 307 } 308 309 void DoDumpSymbols(std::ostream &os, const Scope &scope, int indent) { 310 PutIndent(os, indent); 311 os << Scope::EnumToString(scope.kind()) << " scope:"; 312 if (const auto *symbol{scope.symbol()}) { 313 os << ' ' << symbol->name(); 314 } 315 os << '\n'; 316 ++indent; 317 for (const auto &pair : scope) { 318 const auto &symbol{*pair.second}; 319 PutIndent(os, indent); 320 os << symbol << '\n'; 321 if (const auto *details{symbol.detailsIf<GenericDetails>()}) { 322 if (const auto &type{details->derivedType()}) { 323 PutIndent(os, indent); 324 os << *type << '\n'; 325 } 326 } 327 } 328 if (!scope.equivalenceSets().empty()) { 329 PutIndent(os, indent); 330 os << "Equivalence Sets:"; 331 for (const auto &set : scope.equivalenceSets()) { 332 os << ' '; 333 char sep = '('; 334 for (const auto &object : set) { 335 os << sep << object.AsFortran(); 336 sep = ','; 337 } 338 os << ')'; 339 } 340 os << '\n'; 341 } 342 if (!scope.crayPointers().empty()) { 343 PutIndent(os, indent); 344 os << "Cray Pointers:"; 345 for (const auto &[pointee, pointer] : scope.crayPointers()) { 346 os << " (" << pointer->name() << ',' << pointee << ')'; 347 } 348 } 349 for (const auto &pair : scope.commonBlocks()) { 350 const auto &symbol{*pair.second}; 351 PutIndent(os, indent); 352 os << symbol << '\n'; 353 } 354 for (const auto &child : scope.children()) { 355 DoDumpSymbols(os, child, indent); 356 } 357 --indent; 358 } 359 360 static void PutIndent(std::ostream &os, int indent) { 361 for (int i = 0; i < indent; ++i) { 362 os << " "; 363 } 364 } 365 } 366