1 // Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef FORTRAN_SEMANTICS_RESOLVE_NAMES_UTILS_H_ 16 #define FORTRAN_SEMANTICS_RESOLVE_NAMES_UTILS_H_ 17 18 // Utility functions and class for use in resolve-names.cc. 19 20 #include "scope.h" 21 #include "symbol.h" 22 #include "type.h" 23 #include "../parser/message.h" 24 #include <forward_list> 25 26 namespace Fortran::parser { 27 class CharBlock; 28 struct ArraySpec; 29 struct CoarraySpec; 30 struct ComponentArraySpec; 31 struct DataRef; 32 struct DefinedOpName; 33 struct Designator; 34 struct Expr; 35 struct GenericSpec; 36 struct Name; 37 } 38 39 namespace Fortran::semantics { 40 41 using SourceName = parser::CharBlock; 42 class SemanticsContext; 43 44 // Record that a Name has been resolved to a Symbol 45 Symbol &Resolve(const parser::Name &, Symbol &); 46 Symbol *Resolve(const parser::Name &, Symbol *); 47 48 // Create a copy of msg with a new isFatal value. 49 parser::MessageFixedText WithIsFatal( 50 const parser::MessageFixedText &msg, bool isFatal); 51 52 // Is this the name of a defined operator, e.g. ".foo." 53 bool IsDefinedOperator(const SourceName &); 54 bool IsIntrinsicOperator(const SemanticsContext &, const SourceName &); 55 bool IsLogicalConstant(const SemanticsContext &, const SourceName &); 56 57 // Analyze a generic-spec and generate a symbol name and GenericKind for it. 58 class GenericSpecInfo { 59 public: GenericSpecInfo(const parser::DefinedOpName & x)60 GenericSpecInfo(const parser::DefinedOpName &x) { Analyze(x); } GenericSpecInfo(const parser::GenericSpec & x)61 GenericSpecInfo(const parser::GenericSpec &x) { Analyze(x); } 62 kind()63 GenericKind kind() const { return kind_; } symbolName()64 const SourceName &symbolName() const { return symbolName_.value(); } 65 // Some intrinsic operators have more than one name (e.g. `operator(.eq.)` and 66 // `operator(==)`). GetAllNames() returns them all, including symbolName. 67 std::forward_list<std::string> GetAllNames() const; 68 // Set the GenericKind in this symbol and resolve the corresponding 69 // name if there is one 70 void Resolve(Symbol *) const; 71 Symbol *FindInScope(const Scope &) const; 72 73 private: 74 GenericKind kind_; 75 const parser::Name *parseName_{nullptr}; 76 std::optional<SourceName> symbolName_; 77 78 void Analyze(const parser::DefinedOpName &); 79 void Analyze(const parser::GenericSpec &); 80 }; 81 82 // Analyze a parser::ArraySpec or parser::CoarraySpec 83 ArraySpec AnalyzeArraySpec(SemanticsContext &, const parser::ArraySpec &); 84 ArraySpec AnalyzeArraySpec( 85 SemanticsContext &, const parser::ComponentArraySpec &); 86 ArraySpec AnalyzeCoarraySpec( 87 SemanticsContext &context, const parser::CoarraySpec &); 88 89 // Perform consistency checks on equivalence sets 90 class EquivalenceSets { 91 public: EquivalenceSets(SemanticsContext & context)92 EquivalenceSets(SemanticsContext &context) : context_{context} {} sets()93 std::vector<EquivalenceSet> &sets() { return sets_; }; 94 // Resolve this designator and add to the current equivalence set 95 void AddToSet(const parser::Designator &); 96 // Finish the current equivalence set: determine if it overlaps 97 // with any of the others and perform necessary merges if it does. 98 void FinishSet(const parser::CharBlock &); 99 100 private: 101 bool CheckCanEquivalence( 102 const parser::CharBlock &, const Symbol &, const Symbol &); 103 void MergeInto(const parser::CharBlock &, EquivalenceSet &, std::size_t); 104 const EquivalenceObject *Find(const EquivalenceSet &, const Symbol &); 105 bool CheckDesignator(const parser::Designator &); 106 bool CheckDataRef(const parser::CharBlock &, const parser::DataRef &); 107 bool CheckObject(const parser::Name &); 108 bool CheckArrayBound(const parser::Expr &); 109 bool CheckSubstringBound(const parser::Expr &, bool); 110 bool IsCharacterSequenceType(const DeclTypeSpec *); 111 bool IsDefaultKindNumericType(const IntrinsicTypeSpec &); 112 bool IsNumericSequenceType(const DeclTypeSpec *); 113 bool IsSequenceType( 114 const DeclTypeSpec *, std::function<bool(const IntrinsicTypeSpec &)>); 115 116 SemanticsContext &context_; 117 std::vector<EquivalenceSet> sets_; // all equivalence sets in this scope 118 // Map object to index of set it is in 119 std::map<EquivalenceObject, std::size_t> objectToSet_; 120 EquivalenceSet currSet_; // equivalence set currently being constructed 121 struct { 122 Symbol *symbol{nullptr}; 123 std::vector<ConstantSubscript> subscripts; 124 std::optional<ConstantSubscript> substringStart; 125 } currObject_; // equivalence object currently being constructed 126 }; 127 128 } 129 #endif // FORTRAN_SEMANTICS_RESOLVE_NAMES_H_ 130