diff options
Diffstat (limited to 'flang/lib/Semantics/resolve-names.cpp')
| -rw-r--r-- | flang/lib/Semantics/resolve-names.cpp | 170 |
1 files changed, 104 insertions, 66 deletions
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 7397c3a51b61..88822974e013 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -315,6 +315,7 @@ private: bool IsConflictingAttr(Attr); MaybeExpr bindName_; // from BIND(C, NAME="...") + bool isCDefined_{false}; // BIND(C, NAME="...", CDEFINED) extension std::optional<SourceName> passName_; // from PASS(...) }; @@ -660,8 +661,8 @@ public: void MakeExternal(Symbol &); // C815 duplicated attribute checking; returns false on error - bool CheckDuplicatedAttr(SourceName, const Symbol &, Attr); - bool CheckDuplicatedAttrs(SourceName, const Symbol &, Attrs); + bool CheckDuplicatedAttr(SourceName, Symbol &, Attr); + bool CheckDuplicatedAttrs(SourceName, Symbol &, Attrs); void SetExplicitAttr(Symbol &symbol, Attr attr) const { symbol.attrs().set(attr); @@ -1086,6 +1087,58 @@ protected: void NoteScalarSpecificationArgument(const Symbol &symbol) { mustBeScalar_.emplace(symbol); } + // Declare an object or procedure entity. + // T is one of: EntityDetails, ObjectEntityDetails, ProcEntityDetails + template <typename T> + Symbol &DeclareEntity(const parser::Name &name, Attrs attrs) { + Symbol &symbol{MakeSymbol(name, attrs)}; + if (context().HasError(symbol) || symbol.has<T>()) { + return symbol; // OK or error already reported + } else if (symbol.has<UnknownDetails>()) { + symbol.set_details(T{}); + return symbol; + } else if (auto *details{symbol.detailsIf<EntityDetails>()}) { + symbol.set_details(T{std::move(*details)}); + return symbol; + } else if (std::is_same_v<EntityDetails, T> && + (symbol.has<ObjectEntityDetails>() || + symbol.has<ProcEntityDetails>())) { + return symbol; // OK + } else if (auto *details{symbol.detailsIf<UseDetails>()}) { + Say(name.source, + "'%s' is use-associated from module '%s' and cannot be re-declared"_err_en_US, + name.source, GetUsedModule(*details).name()); + } else if (auto *details{symbol.detailsIf<SubprogramNameDetails>()}) { + if (details->kind() == SubprogramKind::Module) { + Say2(name, + "Declaration of '%s' conflicts with its use as module procedure"_err_en_US, + symbol, "Module procedure definition"_en_US); + } else if (details->kind() == SubprogramKind::Internal) { + Say2(name, + "Declaration of '%s' conflicts with its use as internal procedure"_err_en_US, + symbol, "Internal procedure definition"_en_US); + } else { + DIE("unexpected kind"); + } + } else if (std::is_same_v<ObjectEntityDetails, T> && + symbol.has<ProcEntityDetails>()) { + SayWithDecl( + name, symbol, "'%s' is already declared as a procedure"_err_en_US); + } else if (std::is_same_v<ProcEntityDetails, T> && + symbol.has<ObjectEntityDetails>()) { + if (FindCommonBlockContaining(symbol)) { + SayWithDecl(name, symbol, + "'%s' may not be a procedure as it is in a COMMON block"_err_en_US); + } else { + SayWithDecl( + name, symbol, "'%s' is already declared as an object"_err_en_US); + } + } else if (!CheckPossibleBadForwardRef(symbol)) { + SayAlreadyDeclared(name, symbol); + } + context().SetError(symbol); + return symbol; + } private: // The attribute corresponding to the statement containing an ObjectDecl @@ -1150,59 +1203,6 @@ private: bool PassesLocalityChecks( const parser::Name &name, Symbol &symbol, Symbol::Flag flag); bool CheckForHostAssociatedImplicit(const parser::Name &); - - // Declare an object or procedure entity. - // T is one of: EntityDetails, ObjectEntityDetails, ProcEntityDetails - template <typename T> - Symbol &DeclareEntity(const parser::Name &name, Attrs attrs) { - Symbol &symbol{MakeSymbol(name, attrs)}; - if (context().HasError(symbol) || symbol.has<T>()) { - return symbol; // OK or error already reported - } else if (symbol.has<UnknownDetails>()) { - symbol.set_details(T{}); - return symbol; - } else if (auto *details{symbol.detailsIf<EntityDetails>()}) { - symbol.set_details(T{std::move(*details)}); - return symbol; - } else if (std::is_same_v<EntityDetails, T> && - (symbol.has<ObjectEntityDetails>() || - symbol.has<ProcEntityDetails>())) { - return symbol; // OK - } else if (auto *details{symbol.detailsIf<UseDetails>()}) { - Say(name.source, - "'%s' is use-associated from module '%s' and cannot be re-declared"_err_en_US, - name.source, GetUsedModule(*details).name()); - } else if (auto *details{symbol.detailsIf<SubprogramNameDetails>()}) { - if (details->kind() == SubprogramKind::Module) { - Say2(name, - "Declaration of '%s' conflicts with its use as module procedure"_err_en_US, - symbol, "Module procedure definition"_en_US); - } else if (details->kind() == SubprogramKind::Internal) { - Say2(name, - "Declaration of '%s' conflicts with its use as internal procedure"_err_en_US, - symbol, "Internal procedure definition"_en_US); - } else { - DIE("unexpected kind"); - } - } else if (std::is_same_v<ObjectEntityDetails, T> && - symbol.has<ProcEntityDetails>()) { - SayWithDecl( - name, symbol, "'%s' is already declared as a procedure"_err_en_US); - } else if (std::is_same_v<ProcEntityDetails, T> && - symbol.has<ObjectEntityDetails>()) { - if (FindCommonBlockContaining(symbol)) { - SayWithDecl(name, symbol, - "'%s' may not be a procedure as it is in a COMMON block"_err_en_US); - } else { - SayWithDecl( - name, symbol, "'%s' is already declared as an object"_err_en_US); - } - } else if (!CheckPossibleBadForwardRef(symbol)) { - SayAlreadyDeclared(name, symbol); - } - context().SetError(symbol); - return symbol; - } bool HasCycle(const Symbol &, const Symbol *interface); bool MustBeScalar(const Symbol &symbol) const { return mustBeScalar_.find(symbol) != mustBeScalar_.end(); @@ -1623,6 +1623,7 @@ private: void PreSpecificationConstruct(const parser::SpecificationConstruct &); void CreateCommonBlockSymbols(const parser::CommonStmt &); + void CreateObjectSymbols(const std::list<parser::ObjectDecl> &, Attr); void CreateGeneric(const parser::GenericSpec &); void FinishSpecificationPart(const std::list<parser::DeclarationConstruct> &); void AnalyzeStmtFunctionStmt(const parser::StmtFunctionStmt &); @@ -1762,6 +1763,7 @@ Attrs AttrsVisitor::EndAttrs() { cudaDataAttr_.reset(); passName_ = std::nullopt; bindName_.reset(); + isCDefined_ = false; return result; } @@ -1783,6 +1785,7 @@ void AttrsVisitor::SetBindNameOn(Symbol &symbol) { !symbol.attrs().test(Attr::BIND_C)) { return; } + symbol.SetIsCDefined(isCDefined_); std::optional<std::string> label{ evaluate::GetScalarConstantValue<evaluate::Ascii>(bindName_)}; // 18.9.2(2): discard leading and trailing blanks @@ -1820,9 +1823,12 @@ void AttrsVisitor::SetBindNameOn(Symbol &symbol) { void AttrsVisitor::Post(const parser::LanguageBindingSpec &x) { if (CheckAndSet(Attr::BIND_C)) { - if (x.v) { - bindName_ = EvaluateExpr(*x.v); + if (const auto &name{ + std::get<std::optional<parser::ScalarDefaultCharConstantExpr>>( + x.t)}) { + bindName_ = EvaluateExpr(*name); } + isCDefined_ = std::get<bool>(x.t); } } bool AttrsVisitor::Pre(const parser::IntentSpec &x) { @@ -2800,12 +2806,13 @@ void ScopeHandler::MakeExternal(Symbol &symbol) { } bool ScopeHandler::CheckDuplicatedAttr( - SourceName name, const Symbol &symbol, Attr attr) { + SourceName name, Symbol &symbol, Attr attr) { if (attr == Attr::SAVE) { // checked elsewhere } else if (symbol.attrs().test(attr)) { // C815 if (symbol.implicitAttrs().test(attr)) { // Implied attribute is now confirmed explicitly + symbol.implicitAttrs().reset(attr); } else { Say(name, "%s attribute was already specified on '%s'"_err_en_US, EnumToString(attr), name); @@ -2816,7 +2823,7 @@ bool ScopeHandler::CheckDuplicatedAttr( } bool ScopeHandler::CheckDuplicatedAttrs( - SourceName name, const Symbol &symbol, Attrs attrs) { + SourceName name, Symbol &symbol, Attrs attrs) { bool ok{true}; attrs.IterateOverMembers( [&](Attr x) { ok &= CheckDuplicatedAttr(name, symbol, x); }); @@ -4056,7 +4063,9 @@ void SubprogramVisitor::CreateEntry( Attrs attrs; const auto &suffix{std::get<std::optional<parser::Suffix>>(stmt.t)}; bool hasGlobalBindingName{outer.IsGlobal() && suffix && suffix->binding && - suffix->binding->v.has_value()}; + std::get<std::optional<parser::ScalarDefaultCharConstantExpr>>( + suffix->binding->t) + .has_value()}; if (!hasGlobalBindingName) { if (Symbol * extant{FindSymbol(outer, entryName)}) { if (!HandlePreviousCalls(entryName, *extant, subpFlag)) { @@ -4440,7 +4449,10 @@ Symbol &SubprogramVisitor::PushSubprogramScope(const parser::Name &name, bool hasModulePrefix) { Symbol *symbol{GetSpecificFromGeneric(name)}; if (!symbol) { - if (bindingSpec && currScope().IsGlobal() && bindingSpec->v) { + if (bindingSpec && currScope().IsGlobal() && + std::get<std::optional<parser::ScalarDefaultCharConstantExpr>>( + bindingSpec->t) + .has_value()) { // Create this new top-level subprogram with a binding label // in a new global scope, so that its symbol's name won't clash // with another symbol that has a distinct binding label. @@ -5021,6 +5033,10 @@ Symbol &DeclarationVisitor::DeclareUnknownEntity( charInfo_.length.reset(); if (symbol.attrs().test(Attr::EXTERNAL)) { ConvertToProcEntity(symbol); + } else if (symbol.attrs().HasAny(Attrs{Attr::ALLOCATABLE, + Attr::ASYNCHRONOUS, Attr::CONTIGUOUS, Attr::PARAMETER, + Attr::SAVE, Attr::TARGET, Attr::VALUE, Attr::VOLATILE})) { + ConvertToObjectEntity(symbol); } if (attrs.test(Attr::BIND_C)) { SetBindNameOn(symbol); @@ -5670,7 +5686,9 @@ bool DeclarationVisitor::Pre(const parser::ProcedureDeclarationStmt &x) { const auto &procAttrSpec{std::get<std::list<parser::ProcAttrSpec>>(x.t)}; for (const parser::ProcAttrSpec &procAttr : procAttrSpec) { if (auto *bindC{std::get_if<parser::LanguageBindingSpec>(&procAttr.u)}) { - if (bindC->v.has_value()) { + if (std::get<std::optional<parser::ScalarDefaultCharConstantExpr>>( + bindC->t) + .has_value()) { if (std::get<std::list<parser::ProcDecl>>(x.t).size() > 1) { Say(context().location().value(), "A procedure declaration statement with a binding name may not declare multiple procedures"_err_en_US); @@ -8538,11 +8556,19 @@ void ResolveNamesVisitor::PreSpecificationConstruct( } }, [&](const parser::Statement<parser::OtherSpecificationStmt> &y) { - if (const auto *commonStmt{parser::Unwrap<parser::CommonStmt>(y)}) { - CreateCommonBlockSymbols(*commonStmt); - } + common::visit( + common::visitors{ + [&](const common::Indirection<parser::CommonStmt> &z) { + CreateCommonBlockSymbols(z.value()); + }, + [&](const common::Indirection<parser::TargetStmt> &z) { + CreateObjectSymbols(z.value().v, Attr::TARGET); + }, + [](const auto &) {}, + }, + y.statement.u); }, - [&](const auto &) {}, + [](const auto &) {}, }, spec.u); } @@ -8562,6 +8588,15 @@ void ResolveNamesVisitor::CreateCommonBlockSymbols( } } +void ResolveNamesVisitor::CreateObjectSymbols( + const std::list<parser::ObjectDecl> &decls, Attr attr) { + for (const parser::ObjectDecl &decl : decls) { + SetImplicitAttr(DeclareEntity<ObjectEntityDetails>( + std::get<parser::ObjectName>(decl.t), Attrs{}), + attr); + } +} + void ResolveNamesVisitor::CreateGeneric(const parser::GenericSpec &x) { auto info{GenericSpecInfo{x}}; SourceName symbolName{info.symbolName()}; @@ -8886,6 +8921,9 @@ void ResolveNamesVisitor::Post(const parser::AssignedGotoStmt &x) { } void ResolveNamesVisitor::Post(const parser::CompilerDirective &x) { + if (std::holds_alternative<parser::CompilerDirective::VectorAlways>(x.u)) { + return; + } if (const auto *tkr{ std::get_if<std::list<parser::CompilerDirective::IgnoreTKR>>(&x.u)}) { if (currScope().IsTopLevel() || |
