@@ -661,8 +661,8 @@ class ScopeHandler : public ImplicitRulesVisitor {
661
661
void MakeExternal (Symbol &);
662
662
663
663
// C815 duplicated attribute checking; returns false on error
664
- bool CheckDuplicatedAttr (SourceName, const Symbol &, Attr);
665
- bool CheckDuplicatedAttrs (SourceName, const Symbol &, Attrs);
664
+ bool CheckDuplicatedAttr (SourceName, Symbol &, Attr);
665
+ bool CheckDuplicatedAttrs (SourceName, Symbol &, Attrs);
666
666
667
667
void SetExplicitAttr (Symbol &symbol, Attr attr) const {
668
668
symbol.attrs ().set (attr);
@@ -1087,6 +1087,58 @@ class DeclarationVisitor : public ArraySpecVisitor,
1087
1087
void NoteScalarSpecificationArgument (const Symbol &symbol) {
1088
1088
mustBeScalar_.emplace (symbol);
1089
1089
}
1090
+ // Declare an object or procedure entity.
1091
+ // T is one of: EntityDetails, ObjectEntityDetails, ProcEntityDetails
1092
+ template <typename T>
1093
+ Symbol &DeclareEntity (const parser::Name &name, Attrs attrs) {
1094
+ Symbol &symbol{MakeSymbol (name, attrs)};
1095
+ if (context ().HasError (symbol) || symbol.has <T>()) {
1096
+ return symbol; // OK or error already reported
1097
+ } else if (symbol.has <UnknownDetails>()) {
1098
+ symbol.set_details (T{});
1099
+ return symbol;
1100
+ } else if (auto *details{symbol.detailsIf <EntityDetails>()}) {
1101
+ symbol.set_details (T{std::move (*details)});
1102
+ return symbol;
1103
+ } else if (std::is_same_v<EntityDetails, T> &&
1104
+ (symbol.has <ObjectEntityDetails>() ||
1105
+ symbol.has <ProcEntityDetails>())) {
1106
+ return symbol; // OK
1107
+ } else if (auto *details{symbol.detailsIf <UseDetails>()}) {
1108
+ Say (name.source ,
1109
+ " '%s' is use-associated from module '%s' and cannot be re-declared" _err_en_US,
1110
+ name.source , GetUsedModule (*details).name ());
1111
+ } else if (auto *details{symbol.detailsIf <SubprogramNameDetails>()}) {
1112
+ if (details->kind () == SubprogramKind::Module) {
1113
+ Say2 (name,
1114
+ " Declaration of '%s' conflicts with its use as module procedure" _err_en_US,
1115
+ symbol, " Module procedure definition" _en_US);
1116
+ } else if (details->kind () == SubprogramKind::Internal) {
1117
+ Say2 (name,
1118
+ " Declaration of '%s' conflicts with its use as internal procedure" _err_en_US,
1119
+ symbol, " Internal procedure definition" _en_US);
1120
+ } else {
1121
+ DIE (" unexpected kind" );
1122
+ }
1123
+ } else if (std::is_same_v<ObjectEntityDetails, T> &&
1124
+ symbol.has <ProcEntityDetails>()) {
1125
+ SayWithDecl (
1126
+ name, symbol, " '%s' is already declared as a procedure" _err_en_US);
1127
+ } else if (std::is_same_v<ProcEntityDetails, T> &&
1128
+ symbol.has <ObjectEntityDetails>()) {
1129
+ if (FindCommonBlockContaining (symbol)) {
1130
+ SayWithDecl (name, symbol,
1131
+ " '%s' may not be a procedure as it is in a COMMON block" _err_en_US);
1132
+ } else {
1133
+ SayWithDecl (
1134
+ name, symbol, " '%s' is already declared as an object" _err_en_US);
1135
+ }
1136
+ } else if (!CheckPossibleBadForwardRef (symbol)) {
1137
+ SayAlreadyDeclared (name, symbol);
1138
+ }
1139
+ context ().SetError (symbol);
1140
+ return symbol;
1141
+ }
1090
1142
1091
1143
private:
1092
1144
// The attribute corresponding to the statement containing an ObjectDecl
@@ -1151,59 +1203,6 @@ class DeclarationVisitor : public ArraySpecVisitor,
1151
1203
bool PassesLocalityChecks (
1152
1204
const parser::Name &name, Symbol &symbol, Symbol::Flag flag);
1153
1205
bool CheckForHostAssociatedImplicit (const parser::Name &);
1154
-
1155
- // Declare an object or procedure entity.
1156
- // T is one of: EntityDetails, ObjectEntityDetails, ProcEntityDetails
1157
- template <typename T>
1158
- Symbol &DeclareEntity (const parser::Name &name, Attrs attrs) {
1159
- Symbol &symbol{MakeSymbol (name, attrs)};
1160
- if (context ().HasError (symbol) || symbol.has <T>()) {
1161
- return symbol; // OK or error already reported
1162
- } else if (symbol.has <UnknownDetails>()) {
1163
- symbol.set_details (T{});
1164
- return symbol;
1165
- } else if (auto *details{symbol.detailsIf <EntityDetails>()}) {
1166
- symbol.set_details (T{std::move (*details)});
1167
- return symbol;
1168
- } else if (std::is_same_v<EntityDetails, T> &&
1169
- (symbol.has <ObjectEntityDetails>() ||
1170
- symbol.has <ProcEntityDetails>())) {
1171
- return symbol; // OK
1172
- } else if (auto *details{symbol.detailsIf <UseDetails>()}) {
1173
- Say (name.source ,
1174
- " '%s' is use-associated from module '%s' and cannot be re-declared" _err_en_US,
1175
- name.source , GetUsedModule (*details).name ());
1176
- } else if (auto *details{symbol.detailsIf <SubprogramNameDetails>()}) {
1177
- if (details->kind () == SubprogramKind::Module) {
1178
- Say2 (name,
1179
- " Declaration of '%s' conflicts with its use as module procedure" _err_en_US,
1180
- symbol, " Module procedure definition" _en_US);
1181
- } else if (details->kind () == SubprogramKind::Internal) {
1182
- Say2 (name,
1183
- " Declaration of '%s' conflicts with its use as internal procedure" _err_en_US,
1184
- symbol, " Internal procedure definition" _en_US);
1185
- } else {
1186
- DIE (" unexpected kind" );
1187
- }
1188
- } else if (std::is_same_v<ObjectEntityDetails, T> &&
1189
- symbol.has <ProcEntityDetails>()) {
1190
- SayWithDecl (
1191
- name, symbol, " '%s' is already declared as a procedure" _err_en_US);
1192
- } else if (std::is_same_v<ProcEntityDetails, T> &&
1193
- symbol.has <ObjectEntityDetails>()) {
1194
- if (FindCommonBlockContaining (symbol)) {
1195
- SayWithDecl (name, symbol,
1196
- " '%s' may not be a procedure as it is in a COMMON block" _err_en_US);
1197
- } else {
1198
- SayWithDecl (
1199
- name, symbol, " '%s' is already declared as an object" _err_en_US);
1200
- }
1201
- } else if (!CheckPossibleBadForwardRef (symbol)) {
1202
- SayAlreadyDeclared (name, symbol);
1203
- }
1204
- context ().SetError (symbol);
1205
- return symbol;
1206
- }
1207
1206
bool HasCycle (const Symbol &, const Symbol *interface);
1208
1207
bool MustBeScalar (const Symbol &symbol) const {
1209
1208
return mustBeScalar_.find (symbol) != mustBeScalar_.end ();
@@ -1624,6 +1623,7 @@ class ResolveNamesVisitor : public virtual ScopeHandler,
1624
1623
1625
1624
void PreSpecificationConstruct (const parser::SpecificationConstruct &);
1626
1625
void CreateCommonBlockSymbols (const parser::CommonStmt &);
1626
+ void CreateObjectSymbols (const std::list<parser::ObjectDecl> &, Attr);
1627
1627
void CreateGeneric (const parser::GenericSpec &);
1628
1628
void FinishSpecificationPart (const std::list<parser::DeclarationConstruct> &);
1629
1629
void AnalyzeStmtFunctionStmt (const parser::StmtFunctionStmt &);
@@ -2806,12 +2806,13 @@ void ScopeHandler::MakeExternal(Symbol &symbol) {
2806
2806
}
2807
2807
2808
2808
bool ScopeHandler::CheckDuplicatedAttr (
2809
- SourceName name, const Symbol &symbol, Attr attr) {
2809
+ SourceName name, Symbol &symbol, Attr attr) {
2810
2810
if (attr == Attr::SAVE) {
2811
2811
// checked elsewhere
2812
2812
} else if (symbol.attrs ().test (attr)) { // C815
2813
2813
if (symbol.implicitAttrs ().test (attr)) {
2814
2814
// Implied attribute is now confirmed explicitly
2815
+ symbol.implicitAttrs ().reset (attr);
2815
2816
} else {
2816
2817
Say (name, " %s attribute was already specified on '%s'" _err_en_US,
2817
2818
EnumToString (attr), name);
@@ -2822,7 +2823,7 @@ bool ScopeHandler::CheckDuplicatedAttr(
2822
2823
}
2823
2824
2824
2825
bool ScopeHandler::CheckDuplicatedAttrs (
2825
- SourceName name, const Symbol &symbol, Attrs attrs) {
2826
+ SourceName name, Symbol &symbol, Attrs attrs) {
2826
2827
bool ok{true };
2827
2828
attrs.IterateOverMembers (
2828
2829
[&](Attr x) { ok &= CheckDuplicatedAttr (name, symbol, x); });
@@ -5032,6 +5033,10 @@ Symbol &DeclarationVisitor::DeclareUnknownEntity(
5032
5033
charInfo_.length .reset ();
5033
5034
if (symbol.attrs ().test (Attr::EXTERNAL)) {
5034
5035
ConvertToProcEntity (symbol);
5036
+ } else if (symbol.attrs ().HasAny (Attrs{Attr::ALLOCATABLE,
5037
+ Attr::ASYNCHRONOUS, Attr::CONTIGUOUS, Attr::PARAMETER,
5038
+ Attr::SAVE, Attr::TARGET, Attr::VALUE, Attr::VOLATILE})) {
5039
+ ConvertToObjectEntity (symbol);
5035
5040
}
5036
5041
if (attrs.test (Attr::BIND_C)) {
5037
5042
SetBindNameOn (symbol);
@@ -8551,11 +8556,19 @@ void ResolveNamesVisitor::PreSpecificationConstruct(
8551
8556
}
8552
8557
},
8553
8558
[&](const parser::Statement<parser::OtherSpecificationStmt> &y) {
8554
- if (const auto *commonStmt{parser::Unwrap<parser::CommonStmt>(y)}) {
8555
- CreateCommonBlockSymbols (*commonStmt);
8556
- }
8559
+ common::visit (
8560
+ common::visitors{
8561
+ [&](const common::Indirection<parser::CommonStmt> &z) {
8562
+ CreateCommonBlockSymbols (z.value ());
8563
+ },
8564
+ [&](const common::Indirection<parser::TargetStmt> &z) {
8565
+ CreateObjectSymbols (z.value ().v , Attr::TARGET);
8566
+ },
8567
+ [](const auto &) {},
8568
+ },
8569
+ y.statement .u );
8557
8570
},
8558
- [& ](const auto &) {},
8571
+ [](const auto &) {},
8559
8572
},
8560
8573
spec.u );
8561
8574
}
@@ -8575,6 +8588,15 @@ void ResolveNamesVisitor::CreateCommonBlockSymbols(
8575
8588
}
8576
8589
}
8577
8590
8591
+ void ResolveNamesVisitor::CreateObjectSymbols (
8592
+ const std::list<parser::ObjectDecl> &decls, Attr attr) {
8593
+ for (const parser::ObjectDecl &decl : decls) {
8594
+ SetImplicitAttr (DeclareEntity<ObjectEntityDetails>(
8595
+ std::get<parser::ObjectName>(decl.t ), Attrs{}),
8596
+ attr);
8597
+ }
8598
+ }
8599
+
8578
8600
void ResolveNamesVisitor::CreateGeneric (const parser::GenericSpec &x) {
8579
8601
auto info{GenericSpecInfo{x}};
8580
8602
SourceName symbolName{info.symbolName ()};
0 commit comments