summaryrefslogtreecommitdiff
path: root/flang/lib/Semantics/resolve-names.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'flang/lib/Semantics/resolve-names.cpp')
-rw-r--r--flang/lib/Semantics/resolve-names.cpp170
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() ||