Lines Matching full:symbol
20 #include "flang/Semantics/symbol.h"
52 void Check(const Symbol &);
53 void CheckCommonBlock(const Symbol &);
55 const Procedure *Characterize(const Symbol &);
63 void CheckValue(const Symbol &, const DerivedTypeSpec *);
64 void CheckVolatile(const Symbol &, const DerivedTypeSpec *);
65 void CheckContiguous(const Symbol &);
66 void CheckPointer(const Symbol &);
68 const Symbol &proc, const Symbol *interface, const WithPassArg &);
69 void CheckProcBinding(const Symbol &, const ProcBindingDetails &);
70 void CheckObjectEntity(const Symbol &, const ObjectEntityDetails &);
71 void CheckPointerInitialization(const Symbol &);
72 void CheckArraySpec(const Symbol &, const ArraySpec &);
73 void CheckProcEntity(const Symbol &, const ProcEntityDetails &);
74 void CheckSubprogram(const Symbol &, const SubprogramDetails &);
75 void CheckExternal(const Symbol &);
76 void CheckAssumedTypeEntity(const Symbol &, const ObjectEntityDetails &);
77 void CheckDerivedType(const Symbol &, const DerivedTypeDetails &);
79 const Symbol &subroutine, SourceName, const Symbol &derivedType);
80 bool CheckDistinguishableFinals(const Symbol &f1, SourceName f1name,
81 const Symbol &f2, SourceName f2name, const Symbol &derivedType);
82 void CheckGeneric(const Symbol &, const GenericDetails &);
83 void CheckHostAssoc(const Symbol &, const HostAssocDetails &);
85 SourceName, GenericKind, const Symbol &, const Procedure &);
89 const SourceName &, const Symbol &, const Procedure &, std::size_t);
90 bool CheckDefinedAssignment(const Symbol &, const Procedure &);
91 bool CheckDefinedAssignmentArg(const Symbol &, const DummyArgument &, int);
92 void CheckSpecifics(const Symbol &, const GenericDetails &);
97 bool CheckConflicting(const Symbol &, Attr, Attr);
98 void WarnMissingFinal(const Symbol &);
99 void CheckSymbolType(const Symbol &); // C702
116 parser::Message *SayWithDeclaration(const Symbol &symbol, A &&...x) {
118 if (msg && messages_.at().begin() != symbol.name().begin()) {
119 evaluate::AttachDeclaration(*msg, symbol);
146 void CheckGlobalName(const Symbol &);
147 void CheckProcedureAssemblyName(const Symbol &symbol);
148 void CheckExplicitSave(const Symbol &);
149 parser::Messages WhyNotInteroperableDerivedType(const Symbol &);
151 const Symbol &, bool allowNonInteroperableType = false);
152 parser::Messages WhyNotInteroperableFunctionResult(const Symbol &);
153 parser::Messages WhyNotInteroperableProcedure(const Symbol &, bool isError);
154 void CheckBindC(const Symbol &);
157 const Symbol &, const GenericDetails &, common::DefinedIo);
158 bool CheckDioDummyIsData(const Symbol &, const Symbol *, std::size_t);
160 const Symbol &, const Symbol &, common::DefinedIo ioKind, const Symbol &);
161 void CheckDioDummyIsDefaultInteger(const Symbol &, const Symbol &);
162 void CheckDioDummyIsScalar(const Symbol &, const Symbol &);
163 void CheckDioDummyAttrs(const Symbol &, const Symbol &, Attr);
165 const Symbol &, const Symbol *, common::DefinedIo, const Symbol &);
166 void CheckGenericVsIntrinsic(const Symbol &, const GenericDetails &);
167 void CheckDefaultIntegerArg(const Symbol &, const Symbol *, Attr);
169 const Symbol &, const Symbol *, std::size_t, Attr);
170 void CheckDioVlistArg(const Symbol &, const Symbol *, std::size_t);
171 void CheckDioArgCount(const Symbol &, common::DefinedIo ioKind, std::size_t);
175 const Symbol &proc;
176 const Symbol &generic;
179 const Symbol &, const Symbol &generic);
180 void CheckModuleProcedureDef(const Symbol &);
187 // This symbol is the one attached to the innermost enclosing scope
188 // that has a symbol.
189 const Symbol *innermostSymbol_{nullptr};
190 // Cache of calls to Procedure::Characterize(Symbol)
195 std::map<std::pair<SourceName, const Symbol *>, SymbolRef> moduleProcs_;
210 void Add(const Symbol &, GenericKind, const Symbol &, const Procedure &);
215 const Symbol &, const Symbol &, bool isHardConflict);
216 void AttachDeclaration(parser::Message &, const Scope &, const Symbol &);
223 std::map<SourceName, std::map<const Symbol *, ProcedureInfo>>
259 static bool IsBlockData(const Symbol &symbol) {
260 return symbol.scope() && IsBlockData(*symbol.scope());
263 void CheckHelper::Check(const Symbol &symbol) {
264 if (symbol.has<UseErrorDetails>()) {
267 if (symbol.name().size() > common::maxNameLen &&
268 &symbol == &symbol.GetUltimate()) {
269 Warn(common::LanguageFeature::LongNames, symbol.name(),
271 symbol.name(), symbol.name().size(), common::maxNameLen);
273 if (context_.HasError(symbol)) {
276 auto restorer{messages_.SetLocation(symbol.name())};
277 context_.set_location(symbol.name());
278 const DeclTypeSpec *type{symbol.GetType()};
285 CheckHostAssoc(symbol, x);
289 CheckProcBinding(symbol, x);
292 [&](const ObjectEntityDetails &x) { CheckObjectEntity(symbol, x); },
293 [&](const ProcEntityDetails &x) { CheckProcEntity(symbol, x); },
294 [&](const SubprogramDetails &x) { CheckSubprogram(symbol, x); },
295 [&](const DerivedTypeDetails &x) { CheckDerivedType(symbol, x); },
296 [&](const GenericDetails &x) { CheckGeneric(symbol, x); },
299 symbol.details());
300 if (symbol.attrs().test(Attr::VOLATILE)) {
301 CheckVolatile(symbol, derived);
303 if (symbol.attrs().test(Attr::BIND_C)) {
304 CheckBindC(symbol);
306 if (symbol.attrs().test(Attr::SAVE) &&
307 !symbol.implicitAttrs().test(Attr::SAVE)) {
308 CheckExplicitSave(symbol);
310 if (symbol.attrs().test(Attr::CONTIGUOUS)) {
311 CheckContiguous(symbol);
313 CheckGlobalName(symbol);
314 CheckProcedureAssemblyName(symbol);
315 if (symbol.attrs().test(Attr::ASYNCHRONOUS) &&
316 !evaluate::IsVariable(symbol)) {
320 if (symbol.attrs().HasAny({Attr::INTENT_IN, Attr::INTENT_INOUT,
322 !IsDummy(symbol)) {
331 } else if (symbol.attrs().test(Attr::VALUE)) {
332 CheckValue(symbol, derived);
339 if (symbol.attrs().test(Attr::PROTECTED)) {
340 if (symbol.owner().kind() != Scope::Kind::Module) { // C854
344 if (!evaluate::IsVariable(symbol) && !IsProcedurePointer(symbol)) { // C855
348 if (FindCommonBlockContaining(symbol)) { // C856
353 if (IsPointer(symbol)) {
354 CheckPointer(symbol);
362 } else if (!FindCommonBlockContaining(symbol) && IsSaved(symbol)) {
363 if (IsInitialized(symbol)) {
371 if (symbol.attrs().test(Attr::VOLATILE) &&
372 (IsDummy(symbol) || !InInterface())) {
378 } else if (IsProcedure(symbol) && !IsPureProcedure(symbol) &&
379 IsDummy(symbol)) {
384 const auto *object{symbol.detailsIf<ObjectEntityDetails>()};
387 bool canHaveAssumedParameter{(isChar && IsNamedConstant(symbol)) ||
388 (IsAssumedLengthCharacter(symbol) && // C722
389 (IsExternal(symbol) ||
390 ClassifyProcedure(symbol) ==
392 symbol.test(Symbol::Flag::ParentComp)};
393 if (!IsStmtFunctionDummy(symbol)) { // C726
397 IsStmtFunctionResult(symbol); // Avoids multiple messages
399 canHaveAssumedParameter |= symbol.has<AssocEntityDetails>();
402 if (IsProcedurePointer(symbol) && symbol.HasExplicitInterface()) {
407 if (InFunction() && IsFunctionResult(symbol)) {
409 if (type->IsPolymorphic() && IsAllocatable(symbol)) { // C1585
416 if (HasImpureFinal(symbol)) { // C1584
435 if (IsAssumedLengthCharacter(symbol) && IsFunction(symbol)) { // C723
436 if (symbol.attrs().test(Attr::RECURSIVE)) {
440 if (symbol.Rank() > 0) {
444 if (!IsStmtFunction(symbol)) {
445 if (IsElementalProcedure(symbol)) {
448 } else if (IsPureProcedure(symbol)) {
453 if (const Symbol *result{FindFunctionResult(symbol)}) {
459 if (IsProcedurePointer(symbol) && IsDummy(symbol)) {
465 if (IsDummy(symbol)) {
466 if (IsNamedConstant(symbol)) {
470 } else if (IsFunctionResult(symbol)) {
471 if (IsNamedConstant(symbol)) {
476 if (IsAutomatic(symbol)) {
477 if (const Symbol * common{FindCommonBlockContaining(symbol)}) {
480 symbol.name(), common->name());
481 } else if (symbol.owner().IsModule()) {
484 symbol.name());
485 } else if (IsBlockData(symbol.owner())) {
488 symbol.name());
489 } else if (symbol.owner().kind() == Scope::Kind::MainProgram) {
493 symbol.name());
497 symbol.name());
501 if (IsProcedure(symbol)) {
502 if (IsAllocatable(symbol)) {
504 "Procedure '%s' may not be ALLOCATABLE"_err_en_US, symbol.name());
506 if (!symbol.HasExplicitInterface() && symbol.Rank() > 0) {
509 symbol.name());
514 void CheckHelper::CheckCommonBlock(const Symbol &symbol) {
515 CheckGlobalName(symbol);
516 if (symbol.attrs().test(Attr::BIND_C)) {
517 CheckBindC(symbol);
519 for (MutableSymbolRef ref : symbol.get<CommonBlockDetails>().objects()) {
520 if (ref->test(Symbol::Flag::CrayPointee)) {
529 void CheckHelper::CheckExplicitSave(const Symbol &symbol) {
530 const Symbol &ultimate{symbol.GetUltimate()};
531 if (ultimate.test(Symbol::Flag::InDataStmt)) {
533 } else if (symbol.has<UseDetails>()) {
536 symbol.name());
540 symbol.name());
544 symbol.name());
545 } else if (const Symbol * common{FindCommonBlockContaining(ultimate)}) {
548 symbol.name(), common->name());
552 symbol.name());
556 symbol.name());
561 const Symbol &symbol, const DerivedTypeSpec *derived) { // C863 - C865
562 if (IsProcedure(symbol)) {
567 if (IsAssumedSizeArray(symbol)) {
571 if (evaluate::IsCoarray(symbol)) {
574 if (IsAllocatable(symbol)) {
576 } else if (IsPointer(symbol)) {
579 if (IsIntentInOut(symbol)) {
582 } else if (IsIntentOut(symbol)) {
586 if (symbol.attrs().test(Attr::VOLATILE)) {
590 if (IsOptional(symbol)) {
594 if (symbol.Rank() > 0) {
605 if (evaluate::IsAssumedRank(symbol)) {
609 if (IsAssumedLengthCharacter(symbol)) {
617 const Symbol &symbol, const ObjectEntityDetails &details) {
618 if (const DeclTypeSpec *type{symbol.GetType()};
620 if (!IsDummy(symbol)) {
623 symbol.name());
625 if (symbol.attrs().test(Attr::ALLOCATABLE)) {
628 symbol.name());
630 if (symbol.attrs().test(Attr::POINTER)) {
633 symbol.name());
635 if (symbol.attrs().test(Attr::VALUE)) {
638 symbol.name());
640 if (symbol.attrs().test(Attr::INTENT_OUT)) {
643 symbol.name());
645 if (evaluate::IsCoarray(symbol)) {
648 symbol.name());
653 symbol.name());
660 const Symbol &symbol, const ObjectEntityDetails &details) {
661 CheckSymbolType(symbol);
662 CheckArraySpec(symbol, details.shape());
663 CheckConflicting(symbol, Attr::ALLOCATABLE, Attr::PARAMETER);
664 CheckConflicting(symbol, Attr::ASYNCHRONOUS, Attr::PARAMETER);
665 CheckConflicting(symbol, Attr::SAVE, Attr::PARAMETER);
666 CheckConflicting(symbol, Attr::TARGET, Attr::PARAMETER);
667 CheckConflicting(symbol, Attr::VOLATILE, Attr::PARAMETER);
673 symbol.name(), details.shape().Rank(), common::maxRank);
678 symbol.name(), details.shape().Rank(), details.coshape().Rank(),
681 CheckAssumedTypeEntity(symbol, details);
682 WarnMissingFinal(symbol);
685 bool isComponent{symbol.owner().IsDerivedType()};
687 if (!isComponent && !IsPointer(symbol) && derived) {
691 symbol.name());
696 symbol.name(), component.BuildResultDesignatorName());
701 if (IsAllocatable(symbol)) {
705 symbol.name());
712 symbol.name(), deferredMsg);
717 symbol.name());
723 symbol.name());
725 if (evaluate::IsAssumedRank(symbol)) {
727 symbol.name());
731 if (IsIntentOut(symbol)) {
735 if (FindUltimateComponent(symbol, [](const Symbol &x) {
741 if (IsOrContainsEventOrLockComponent(symbol)) { // C847
745 if (IsAssumedSizeArray(symbol)) { // C834
763 !IsPointer(symbol) && !IsIntentIn(symbol) &&
764 !symbol.attrs().test(Attr::VALUE)) {
767 if (IsIntentOut(symbol)) {
774 if (FindUltimateComponent(*derived, [](const Symbol &x) {
783 if (HasImpureFinal(symbol)) { // C1587
790 } else if (!IsIntentInOut(symbol)) { // C1586
806 if (auto ignoreTKR{GetIgnoreTKR(symbol)}; !ignoreTKR.empty()) {
807 const Symbol *ownerSymbol{symbol.owner().symbol()};
820 if (IsPassedViaDescriptor(symbol)) {
821 if (IsAllocatableOrObjectPointer(&symbol)) {
830 if (ignoreTKR.count() == 1 && evaluate::IsAssumedRank(symbol)) {
853 if (IsAllocatable(symbol)) {
857 if (evaluate::IsCoarray(symbol)) {
861 if (IsPointer(symbol)) {
865 if (!symbol.attrs().HasAny(Attrs{Attr::VALUE, Attr::INTENT_IN,
870 } else if (IsFunctionResult(symbol)) { // C15101
875 if (IsAllocatable(symbol)) {
879 if (IsPointer(symbol)) {
885 if (HasDeclarationInitializer(symbol)) { // C808; ignore DATA initialization
886 CheckPointerInitialization(symbol);
887 if (IsAutomatic(symbol)) {
890 } else if (IsDummy(symbol)) {
892 } else if (IsFunctionResult(symbol)) {
894 } else if (IsInBlankCommon(symbol)) {
899 if (symbol.owner().kind() == Scope::Kind::BlockData) {
900 if (IsAllocatable(symbol)) {
903 } else if (IsInitialized(symbol) && !FindCommonBlockContaining(symbol)) {
909 IsAutomaticallyDestroyed(symbol) &&
910 !IsIntentOut(symbol) /*has better messages*/ &&
911 !IsFunctionResult(symbol) /*ditto*/) {
915 WhyNotDefinable(symbol.name(), symbol.owner(), {}, symbol)}) {
918 symbol.name())}) {
923 if (symbol.attrs().test(Attr::EXTERNAL)) {
924 SayWithDeclaration(symbol,
926 symbol.name());
931 const Scope &progUnit{GetProgramUnitContaining(symbol)};
932 const auto *subpDetails{!isComponent && progUnit.symbol()
933 ? progUnit.symbol()->detailsIf<SubprogramDetails>()
935 bool inDeviceSubprogram{IsCUDADeviceContext(&symbol.owner())};
937 if (IsSaved(symbol)) {
940 symbol.name());
942 if (IsPointer(symbol)) {
945 symbol.name());
956 symbol.name(),
962 if (auto dyType{evaluate::DynamicType::From(symbol)}) {
967 symbol.name(), dyType->AsFortran());
977 symbol.name());
978 } else if (IsAllocatableOrPointer(symbol) ||
979 symbol.attrs().test(Attr::TARGET)) {
982 symbol.name());
983 } else if (auto shape{evaluate::GetShape(foldingContext_, symbol)};
988 symbol.name());
992 if (isComponent && !IsAllocatable(symbol)) {
995 symbol.name());
999 if (!IsAutomatic(symbol) && !IsAllocatable(symbol) &&
1000 !details.isDummy() && !evaluate::IsExplicitShape(symbol)) {
1003 symbol.name());
1010 symbol.name());
1011 } else if (IsPointer(symbol)) {
1014 symbol.name());
1015 } else if (!IsAllocatable(symbol)) {
1018 symbol.name());
1022 if (IsAllocatableOrPointer(symbol) || symbol.attrs().test(Attr::TARGET)) {
1025 symbol.name());
1029 symbol.name());
1034 symbol.owner().kind() != Scope::Kind::MainProgram) ||
1039 symbol.name());
1051 symbol.name(),
1053 } else if (FindEquivalenceSet(symbol)) {
1056 symbol.name(),
1060 if (subpDetails /* not a module variable */ && IsSaved(symbol) &&
1061 !inDeviceSubprogram && !IsAllocatable(symbol) &&
1065 symbol.name(),
1070 const DeclTypeSpec *type{symbol.GetType()};
1075 [](const Symbol &) { return false; })}) {
1078 symbol.name(), iter.BuildResultDesignatorName());
1085 symbol.name(),
1088 } else if (!subpDetails && symbol.owner().kind() != Scope::Kind::Module &&
1089 symbol.owner().kind() != Scope::Kind::MainProgram &&
1090 symbol.owner().kind() != Scope::Kind::BlockConstruct) {
1100 if (IsAssumedShape(symbol)) {
1101 SayWithDeclaration(symbol,
1104 } else if (IsDeferredShape(symbol)) {
1105 SayWithDeclaration(symbol,
1108 } else if (evaluate::IsAssumedRank(symbol)) {
1109 SayWithDeclaration(symbol,
1116 void CheckHelper::CheckPointerInitialization(const Symbol &symbol) {
1117 if (IsPointer(symbol) && !context_.HasError(symbol) &&
1119 if (const auto *object{symbol.detailsIf<ObjectEntityDetails>()}) {
1121 if (auto designator{evaluate::AsGenericExpr(symbol)}) {
1122 auto restorer{messages_.SetLocation(symbol.name())};
1123 context_.set_location(symbol.name());
1128 } else if (const auto *proc{symbol.detailsIf<ProcEntityDetails>()}) {
1132 const Symbol &local{DEREF(*proc->init())};
1133 const Symbol &ultimate{local.GetUltimate()};
1143 ultimate.name(), symbol.name());
1152 symbol.name(), ultimate.name());
1157 symbol.name(), ultimate.name());
1161 SomeExpr lhs{evaluate::ProcedureDesignator{symbol}};
1164 GetProgramUnitOrBlockConstructContaining(symbol),
1186 const Symbol &symbol, const ArraySpec &arraySpec) {
1197 GetCUDADataAttr(&symbol).value_or(common::CUDADataAttr::Device) ==
1199 bool isCrayPointee{symbol.test(Symbol::Flag::CrayPointee)};
1204 } else if (IsAllocatableOrPointer(symbol) && !canBeDeferred &&
1206 if (symbol.owner().IsDerivedType()) { // C745
1207 if (IsAllocatable(symbol)) {
1214 if (IsAllocatable(symbol)) { // C832
1222 } else if (IsDummy(symbol)) {
1234 if (!IsNamedConstant(symbol) && !isCUDAShared &&
1239 } else if (IsNamedConstant(symbol)) {
1245 !(IsAllocatableOrPointer(symbol) || isCrayPointee)) {
1246 if (symbol.owner().IsDerivedType()) { // C749
1255 context_.Say(std::move(*msg), symbol.name());
1260 const Symbol &symbol, const ProcEntityDetails &details) {
1261 CheckSymbolType(symbol);
1262 const Symbol *interface{details.procInterface()};
1264 if (!symbol.attrs().test(Attr::POINTER) && // C843
1265 symbol.attrs().HasAny(
1288 } else if (IsPointer(symbol)) {
1289 CheckPointerInitialization(symbol);
1299 interface->name(), symbol.name());
1303 symbol.name()); // C1517
1307 symbol.name()); // C1517
1310 if (symbol.owner().IsDerivedType()) {
1311 CheckPassArg(symbol, interface, details);
1313 } else if (symbol.owner().IsDerivedType()) {
1314 const auto &name{symbol.name()};
1318 CheckExternal(symbol);
1331 void Check(const Symbol &, const Symbol &);
1335 void CheckDummyArg(const Symbol &, const Symbol &, const DummyArgument &,
1337 void CheckDummyDataObject(const Symbol &, const Symbol &,
1339 void CheckDummyProcedure(const Symbol &, const Symbol &,
1342 const Symbol &, const Symbol &, common::Intent, common::Intent);
1345 const Symbol &, const Symbol &, parser::MessageFixedText &&, A &&...);
1347 bool CheckSameAttrs(const Symbol &, const Symbol &, ATTRS, ATTRS);
1389 const Symbol &symbol, const SubprogramDetails &details) {
1393 if (!context_.HasError(symbol) && !details.isDummy() &&
1395 if (!Procedure::Characterize(symbol, foldingContext_)) {
1396 context_.SetError(symbol);
1399 if (const Symbol *iface{FindSeparateModuleSubprogramInterface(&symbol)}) {
1400 SubprogramMatchHelper{*this}.Check(symbol, *iface);
1405 const Symbol *subprogram{entryScope->symbol()};
1428 if (auto *msg{messages_.Say(symbol.name(), *error)}) {
1436 details.result().name() != symbol.name()) { // F'2023 C1569 & C1583
1437 if (auto iter{symbol.owner().find(details.result().name())};
1438 iter != symbol.owner().end()) {
1439 const Symbol &resNameSym{*iter->second};
1443 details.entryScope() ? details.entryScope() : symbol.scope()};
1445 if (auto *msg{messages_.Say(symbol.name(),
1447 details.result().name(), symbol.name())}) {
1458 symbol, *stmtFunction, context_.foldingContext())}) {
1459 SayWithDeclaration(symbol, std::move(*msg));
1460 } else if (IsPointer(symbol)) {
1461 SayWithDeclaration(symbol,
1463 } else if (details.result().flags().test(Symbol::Flag::Implicit)) {
1465 if (const Symbol *
1466 host{symbol.owner().parent().FindSymbol(symbol.name())}) {
1469 symbol.name(),
1470 "An implicitly typed statement function should not appear when the same symbol is available in its host scope"_port_en_US),
1474 if (GetProgramUnitOrBlockConstructContaining(symbol).kind() ==
1476 messages_.Say(symbol.name(),
1480 if (IsElementalProcedure(symbol)) {
1485 for (const Symbol *dummy : details.dummyArgs()) {
1500 CheckExternal(symbol);
1501 CheckModuleProcedureDef(symbol);
1507 messages_.Say(symbol.name(),
1513 symbol.attrs().HasAny({Attr::RECURSIVE, Attr::PURE, Attr::ELEMENTAL})) {
1514 messages_.Say(symbol.name(),
1519 if (ClassifyProcedure(symbol) == ProcedureDefinitionClass::Internal) {
1520 messages_.Say(symbol.name(),
1529 messages_.Say(symbol.name(),
1532 if (!IsStmtFunction(symbol)) {
1533 if (const Scope * outerDevice{FindCUDADeviceContext(&symbol.owner())};
1534 outerDevice && outerDevice->symbol()) {
1535 if (auto *msg{messages_.Say(symbol.name(),
1537 symbol.name(), outerDevice->symbol()->name())}) {
1538 msg->Attach(outerDevice->symbol()->name(),
1545 void CheckHelper::CheckExternal(const Symbol &symbol) {
1546 if (IsExternal(symbol)) {
1547 std::string interfaceName{symbol.name().ToString()};
1548 if (const auto *bind{symbol.GetBindName()}) {
1551 if (const Symbol * global{FindGlobal(symbol)};
1552 global && global != &symbol) {
1560 if ((symbol.flags().test(Symbol::Flag::Function) ||
1561 symbol.flags().test(Symbol::Flag::Subroutine))) {
1564 global->name(), symbol.name());
1566 } else if (auto chars{Characterize(symbol)}) {
1582 global->name(), symbol.name());
1588 context_.SetError(symbol);
1591 evaluate::AttachDeclaration(msg, symbol);
1596 const Symbol &previous{*iter->second};
1597 if (auto chars{Characterize(symbol)}) {
1604 symbol.name(), whyNot)}) {
1606 evaluate::AttachDeclaration(msg, symbol);
1612 externalNames_.emplace(interfaceName, symbol);
1618 const Symbol &derivedType, const DerivedTypeDetails &details) {
1628 CHECK(scope->symbol() == &derivedType);
1642 for (const Symbol &component : components) {
1680 const Symbol &ref{*pair.second};
1694 const Symbol &subroutine, SourceName finalName, const Symbol &derivedType) {
1718 const Symbol *errSym{&subroutine};
1721 if (const Symbol *argSym{details->dummyArgs()[0]}) {
1798 bool CheckHelper::CheckDistinguishableFinals(const Symbol &f1,
1799 SourceName f1Name, const Symbol &f2, SourceName f2Name,
1800 const Symbol &derivedType) {
1821 const Symbol &symbol, const HostAssocDetails &details) {
1822 const Symbol &hostSymbol{details.symbol()};
1823 if (hostSymbol.test(Symbol::Flag::ImplicitOrError)) {
1827 symbol.name());
1830 "No explicit type declared for '%s'"_err_en_US, symbol.name());
1836 const Symbol &symbol, const GenericDetails &details) {
1837 CheckSpecifics(symbol, details);
1840 CheckDefinedIoProc(symbol, details, io);
1844 CheckGenericVsIntrinsic(symbol, details);
1861 const Symbol &generic, const GenericDetails &details) {
1864 for (const Symbol &specific : details.specificProcs()) {
2002 const Symbol &specific, const Procedure &proc) {
2008 [&](SourceName opName, const Symbol &specific, const Procedure &proc) {
2097 const Symbol &symbol, const Procedure &proc, std::size_t pos) {
2118 parser::ToUpperCaseLetters(opName.ToString()), symbol.name(),
2120 symbol);
2124 SayWithDeclaration(symbol, std::move(*msg),
2125 parser::ToUpperCaseLetters(opName.ToString()), symbol.name(), arg.name);
2133 const Symbol &specific, const Procedure &proc) {
2165 const Symbol &symbol, const DummyArgument &arg, int pos) {
2204 SayWithDeclaration(symbol, std::move(*msg), symbol.name(), arg.name);
2205 context_.SetError(symbol);
2210 symbol.name(), arg.name),
2211 symbol);
2217 // Report a conflicting attribute error if symbol has both of these attributes
2218 bool CheckHelper::CheckConflicting(const Symbol &symbol, Attr a1, Attr a2) {
2219 if (symbol.attrs().test(a1) && symbol.attrs().test(a2)) {
2221 symbol.name(), AttrToString(a1), AttrToString(a2));
2228 void CheckHelper::WarnMissingFinal(const Symbol &symbol) {
2229 const auto *object{symbol.detailsIf<ObjectEntityDetails>()};
2231 (!IsAutomaticallyDestroyed(symbol) &&
2232 symbol.owner().kind() != Scope::Kind::DerivedType)) {
2237 const Symbol *derivedSym{derived ? &derived->typeSymbol() : nullptr};
2239 const Symbol *initialDerivedSym{derivedSym};
2245 ? Warn(common::UsageWarning::Final, symbol.name(),
2247 symbol.name(), derivedSym->name(), rank)
2248 : Warn(common::UsageWarning::Final, symbol.name(),
2250 symbol.name(), initialDerivedSym->name(),
2262 const Procedure *CheckHelper::Characterize(const Symbol &symbol) {
2263 auto it{characterizeCache_.find(symbol)};
2265 auto pair{characterizeCache_.emplace(SymbolRef{symbol},
2266 Procedure::Characterize(symbol, context_.foldingContext()))};
2272 void CheckHelper::CheckVolatile(const Symbol &symbol,
2274 if (IsIntentIn(symbol)) {
2278 if (IsProcedure(symbol)) {
2281 if (symbol.has<UseDetails>() || symbol.has<HostAssocDetails>()) {
2282 const Symbol &ultimate{symbol.GetUltimate()};
2296 void CheckHelper::CheckContiguous(const Symbol &symbol) {
2297 if (evaluate::IsVariable(symbol) &&
2298 ((IsPointer(symbol) && symbol.Rank() > 0) || IsAssumedShape(symbol) ||
2299 evaluate::IsAssumedRank(symbol))) {
2301 parser::MessageFixedText msg{symbol.owner().IsDerivedType()
2306 messages_.Say(std::move(msg), symbol.name());
2309 symbol.name());
2314 void CheckHelper::CheckPointer(const Symbol &symbol) { // C852
2315 CheckConflicting(symbol, Attr::POINTER, Attr::TARGET);
2316 CheckConflicting(symbol, Attr::POINTER, Attr::ALLOCATABLE); // C751
2317 CheckConflicting(symbol, Attr::POINTER, Attr::INTRINSIC);
2323 CheckConflicting(symbol, Attr::POINTER, Attr::PARAMETER);
2324 if (symbol.Corank() > 0) {
2327 symbol.name());
2334 const Symbol &proc, const Symbol *interface0, const WithPassArg &details) {
2339 const Symbol *interface {
2369 Symbol *argSym{dummyArgs[0]};
2391 const Symbol &passArg{*dummyArgs[*passArgIndex]};
2417 const Symbol &typeSymbol{*proc.owner().GetSymbol()};
2447 const Symbol &symbol, const ProcBindingDetails &binding) {
2448 const Scope &dtScope{symbol.owner()};
2450 if (symbol.attrs().test(Attr::DEFERRED)) {
2451 if (const Symbol *dtSymbol{dtScope.symbol()}) {
2458 if (symbol.attrs().test(Attr::NON_OVERRIDABLE)) {
2461 symbol.name());
2464 if (binding.symbol().attrs().test(Attr::INTRINSIC) &&
2466 binding.symbol().name().ToString())) {
2469 binding.symbol().name(), symbol.name());
2472 if (const Symbol *
2473 overridden{FindOverriddenBinding(symbol, isInaccessibleDeferred)}) {
2477 symbol.name());
2482 symbol.name());
2486 if (!IsPureProcedure(symbol) && IsPureProcedure(*overridden)) {
2491 if (!IsElementalProcedure(binding.symbol()) &&
2497 bool isNopass{symbol.attrs().test(Attr::NOPASS)};
2504 const auto *bindingChars{Characterize(symbol)};
2512 } else if (!context_.HasError(binding.symbol())) {
2529 if (symbol.attrs().test(Attr::PRIVATE)) {
2549 CheckPassArg(symbol, &binding.symbol(), binding);
2554 common::Restorer<const Symbol *> restorer{innermostSymbol_, innermostSymbol_};
2555 if (const Symbol *symbol{scope.symbol()}) {
2556 innermostSymbol_ = symbol;
2574 if (scope.IsSubmodule() && scope.symbol()) {
2576 Check(*scope.symbol());
2602 kind = scope.symbol()->get<ModuleDetails>().isSubmodule()
2628 return FindCommonBlockContaining(object.symbol) != nullptr;
2631 const Symbol &commonBlock{DEREF(FindCommonBlockContaining(iter->symbol))};
2634 if (auto *details{object.symbol.detailsIf<ObjectEntityDetails>()}) {
2637 if (auto *msg{messages_.Say(object.symbol.name(),
2639 msg->Attach(iter->symbol.name(),
2643 object.symbol.name())
2646 iter->symbol.name());
2664 static bool InCommonWithBind(const Symbol &symbol) {
2665 if (const auto *details{symbol.detailsIf<ObjectEntityDetails>()}) {
2666 const Symbol *commonBlock{details->commonBlock()};
2675 const Symbol &symbol{object.symbol};
2676 if (symbol.owner().IsDerivedType()) {
2679 } else if (IsDummy(symbol)) {
2681 } else if (symbol.IsFuncResult()) {
2683 } else if (IsPointer(symbol)) {
2685 } else if (IsAllocatable(symbol)) {
2688 } else if (symbol.Corank() > 0) {
2690 } else if (symbol.has<UseDetails>()) {
2693 } else if (symbol.attrs().test(Attr::BIND_C)) {
2696 } else if (symbol.attrs().test(Attr::TARGET)) {
2699 } else if (IsNamedConstant(symbol)) {
2701 } else if (InCommonWithBind(symbol)) {
2704 } else if (!symbol.has<ObjectEntityDetails>()) {
2706 } else if (const auto *type{symbol.GetType()}) {
2718 } else if (IsAutomatic(symbol)) {
2721 } else if (symbol.test(Symbol::Flag::CrayPointee)) {
2722 messages_.Say(object.symbol.name(),
2724 object.symbol.name());
2728 context_.Say(object.source, std::move(msg), symbol.name());
2739 const Symbol &symbol{*pair.second};
2740 if (!(symbol.has<CommonBlockDetails>() || symbol.has<UseDetails>() ||
2741 symbol.has<UseErrorDetails>() || symbol.has<DerivedTypeDetails>() ||
2742 symbol.has<SubprogramDetails>() ||
2743 symbol.has<ObjectEntityDetails>() ||
2744 (symbol.has<ProcEntityDetails>() &&
2745 !symbol.attrs().test(Attr::POINTER)))) {
2746 messages_.Say(symbol.name(),
2748 symbol.name());
2757 auto addSpecifics{[&](const Symbol &generic) {
2766 if (const Symbol *result{FindFunctionResult(generic)};
2780 const Symbol &specific{*specifics[i]};
2797 const Symbol &symbol{*pair.second};
2798 addSpecifics(symbol);
2799 const Symbol &ultimate{symbol.GetUltimate()};
2811 static bool IsSubprogramDefinition(const Symbol &symbol) {
2812 const auto *subp{symbol.detailsIf<SubprogramDetails>()};
2813 return subp && !subp->isInterface() && symbol.scope() &&
2814 symbol.scope()->kind() == Scope::Kind::Subprogram;
2817 static bool IsExternalProcedureDefinition(const Symbol &symbol) {
2818 return IsBlockData(symbol) ||
2819 (IsSubprogramDefinition(symbol) &&
2820 (IsExternal(symbol) || symbol.GetBindName()));
2823 static std::optional<std::string> DefinesGlobalName(const Symbol &symbol) {
2824 if (const auto *module{symbol.detailsIf<ModuleDetails>()}) {
2825 if (!module->isSubmodule() && !symbol.owner().IsIntrinsicModules()) {
2826 return symbol.name().ToString();
2828 } else if (IsBlockData(symbol)) {
2829 return symbol.name().ToString();
2831 const std::string *bindC{symbol.GetBindName()};
2832 if (symbol.has<CommonBlockDetails>() ||
2833 IsExternalProcedureDefinition(symbol) ||
2834 (symbol.owner().IsGlobal() && IsExternal(symbol))) {
2835 return bindC ? *bindC : symbol.name().ToString();
2837 (symbol.has<ObjectEntityDetails>() || IsModuleProcedure(symbol))) {
2845 void CheckHelper::CheckGlobalName(const Symbol &symbol) {
2846 if (auto global{DefinesGlobalName(symbol)}) {
2847 auto pair{globalNames_.emplace(std::move(*global), symbol)};
2849 const Symbol &other{*pair.first->second};
2850 if (context_.HasError(symbol) || context_.HasError(other)) {
2852 } else if (symbol.has<CommonBlockDetails>() &&
2853 other.has<CommonBlockDetails>() && symbol.name() == other.name()) {
2856 } else if ((IsProcedure(symbol) || IsBlockData(symbol)) &&
2858 (!IsExternalProcedureDefinition(symbol) ||
2861 } else if (symbol.has<ModuleDetails>()) {
2862 Warn(common::LanguageFeature::BenignNameClash, symbol.name(),
2866 Warn(common::LanguageFeature::BenignNameClash, symbol.name(),
2869 } else if (auto *msg{messages_.Say(symbol.name(),
2873 context_.SetError(symbol);
2880 void CheckHelper::CheckProcedureAssemblyName(const Symbol &symbol) {
2881 if (!IsProcedure(symbol) || symbol != symbol.GetUltimate())
2883 const std::string *bindName{symbol.GetBindName()};
2885 symbol.GetIsExplicitBindName() && bindName};
2886 if (hasExplicitBindingLabel || IsExternal(symbol)) {
2890 symbol.name().ToString(), context_.underscoring())};
2891 auto pair{procedureAssemblyNames_.emplace(std::move(assemblyName), symbol)};
2893 const Symbol &other{*pair.first->second};
2902 if (auto *msg{messages_.Say(symbol.name(),
2908 context_.SetError(symbol);
2918 const Symbol &symbol) {
2920 if (examinedByWhyNotInteroperable_.find(symbol) !=
2924 examinedByWhyNotInteroperable_.insert(symbol);
2925 if (const auto *derived{symbol.detailsIf<DerivedTypeDetails>()}) {
2927 msgs.Say(symbol.name(),
2930 msgs.Say(symbol.name(),
2933 symbol.scope()->GetDerivedTypeParent()}) { // C1803
2934 if (symbol.attrs().test(Attr::BIND_C)) {
2935 msgs.Say(symbol.name(),
2939 if (parent->symbol()) {
2940 auto bad{WhyNotInteroperableDerivedType(*parent->symbol())};
2942 auto &msg{msgs.Say(symbol.name(),
2949 msgs.Say(symbol.name(),
2954 const Symbol *parentComponent{symbol.scope()
2955 ? derived->GetParentComponent(*symbol.scope())
2957 for (const auto &pair : *symbol.scope()) {
2958 const Symbol &component{*pair.second};
3018 msgs.Say(common::LanguageFeature::EmptyBindCDerivedType, symbol.name(),
3024 examinedByWhyNotInteroperable_.erase(symbol);
3030 const Symbol &symbol, bool allowNonInteroperableType) {
3032 if (examinedByWhyNotInteroperable_.find(symbol) !=
3036 bool isExplicitBindC{symbol.attrs().test(Attr::BIND_C)};
3037 examinedByWhyNotInteroperable_.insert(symbol);
3038 CHECK(symbol.has<ObjectEntityDetails>());
3039 if (isExplicitBindC && !symbol.owner().IsModule()) {
3040 msgs.Say(symbol.name(),
3043 auto shape{evaluate::GetShape(foldingContext_, symbol)};
3046 if (IsAllocatableOrPointer(symbol) && !IsDummy(symbol)) {
3047 msgs.Say(symbol.name(),
3053 msgs.Say(symbol.name(),
3056 } else if (!evaluate::IsExplicitShape(symbol) &&
3057 !IsAssumedSizeArray(symbol) &&
3058 !(IsDummy(symbol) && !symbol.attrs().test(Attr::VALUE))) {
3059 msgs.Say(symbol.name(),
3063 if (const auto *type{symbol.GetType()}) {
3068 context_.Warn(common::UsageWarning::Portability, symbol.name(),
3073 msgs.Say(symbol.name(),
3080 msgs.Say(symbol.name(),
3086 msgs.Say(symbol.name(),
3092 } else if (IsAssumedLengthCharacter(symbol) &&
3093 !IsAllocatableOrPointer(symbol)) {
3094 } else if (IsAllocatableOrPointer(symbol) &&
3109 if (IsDummy(symbol)) {
3110 msgs.Say(common::UsageWarning::LogicalVsCBool, symbol.name(),
3113 msgs.Say(common::UsageWarning::LogicalVsCBool, symbol.name(),
3117 } else if (symbol.attrs().test(Attr::VALUE)) {
3118 msgs.Say(symbol.name(),
3121 msgs.Say(symbol.name(),
3125 if (IsOptional(symbol) && !symbol.attrs().test(Attr::VALUE)) {
3126 msgs.Say(symbol.name(),
3129 if (IsDescriptor(symbol) && IsPointer(symbol) &&
3130 symbol.attrs().test(Attr::CONTIGUOUS)) {
3131 msgs.Say(symbol.name(),
3135 examinedByWhyNotInteroperable_.erase(symbol);
3141 const Symbol &symbol) {
3143 if (IsPointer(symbol) || IsAllocatable(symbol)) {
3144 msgs.Say(symbol.name(),
3147 if (const DeclTypeSpec * type{symbol.GetType()};
3156 msgs.Say(symbol.name(),
3160 if (symbol.Rank() > 0) {
3161 msgs.Say(symbol.name(),
3164 if (symbol.Corank()) {
3165 msgs.Say(symbol.name(),
3172 const Symbol &symbol, bool isError) {
3174 if (examinedByWhyNotInteroperable_.find(symbol) !=
3178 isError |= symbol.attrs().test(Attr::BIND_C);
3179 examinedByWhyNotInteroperable_.insert(symbol);
3180 if (const auto *proc{symbol.detailsIf<ProcEntityDetails>()}) {
3184 msgs.Say(symbol.name(),
3188 msgs.Say(symbol.name(),
3194 bad.AttachTo(msgs.Say(symbol.name(),
3197 msgs.Say(symbol.name(),
3201 } else if (const auto *subp{symbol.detailsIf<SubprogramDetails>()}) {
3202 for (const Symbol *dummy : subp->dummyArgs()) {
3225 msgs.Say(symbol.name(),
3239 examinedByWhyNotInteroperable_.erase(symbol);
3244 void CheckHelper::CheckBindC(const Symbol &symbol) {
3245 bool isExplicitBindC{symbol.attrs().test(Attr::BIND_C)};
3247 CheckConflicting(symbol, Attr::BIND_C, Attr::ELEMENTAL);
3248 CheckConflicting(symbol, Attr::BIND_C, Attr::INTRINSIC);
3249 CheckConflicting(symbol, Attr::BIND_C, Attr::PARAMETER);
3251 // symbol must be interoperable (e.g., dummy argument of interoperable
3255 if (const std::string * bindName{symbol.GetBindName()};
3263 messages_.Say(symbol.name(),
3264 "Symbol has a BIND(C) name that is not a valid C language identifier"_err_en_US);
3265 context_.SetError(symbol);
3269 if (symbol.GetIsExplicitBindName()) { // BIND(C,NAME=...); C1552, C1529
3270 auto defClass{ClassifyProcedure(symbol)};
3271 if (IsProcedurePointer(symbol)) {
3272 messages_.Say(symbol.name(),
3274 context_.SetError(symbol);
3276 IsExternal(symbol)) {
3277 } else if (symbol.attrs().test(Attr::ABSTRACT)) {
3278 messages_.Say(symbol.name(),
3280 context_.SetError(symbol);
3283 messages_.Say(symbol.name(),
3285 context_.SetError(symbol);
3288 if (symbol.has<ObjectEntityDetails>()) {
3289 whyNot = WhyNotInteroperableObject(symbol);
3290 } else if (symbol.has<ProcEntityDetails>() ||
3291 symbol.has<SubprogramDetails>()) {
3292 whyNot = WhyNotInteroperableProcedure(symbol, /*isError=*/isExplicitBindC);
3293 } else if (symbol.has<DerivedTypeDetails>()) {
3294 whyNot = WhyNotInteroperableDerivedType(symbol);
3305 context_.SetError(symbol);
3311 const Symbol &subp, const Symbol *arg, std::size_t position) {
3328 common::DefinedIo ioKind, const Symbol &proc, const Symbol &generic) {
3341 const Symbol &specific{specRef->get<ProcBindingDetails>().symbol()};
3357 void CheckHelper::CheckDioDummyIsDerived(const Symbol &subp, const Symbol &arg,
3358 common::DefinedIo ioKind, const Symbol &generic) {
3379 const Symbol &subp, const Symbol &arg) {
3393 void CheckHelper::CheckDioDummyIsScalar(const Symbol &subp, const Symbol &arg) {
3402 void CheckHelper::CheckDioDtvArg(const Symbol &subp, const Symbol *arg,
3403 common::DefinedIo ioKind, const Symbol &generic) {
3418 const Symbol &symbol, const GenericDetails &generic) {
3419 if (symbol.attrs().test(Attr::INTRINSIC)) {
3422 bool isSubroutine{table.IsIntrinsicSubroutine(symbol.name().ToString())};
3423 if (isSubroutine || table.IsIntrinsicFunction(symbol.name().ToString())) {
3425 const Symbol &ultimate{ref->GetUltimate()};
3426 bool specificFunc{ultimate.test(Symbol::Flag::Function)};
3427 bool specificSubr{ultimate.test(Symbol::Flag::Subroutine)};
3439 messages_.Say(symbol.name(),
3441 symbol.name(), isSubroutine ? "subroutine" : "function",
3450 const Symbol &subp, const Symbol *arg, Attr intent) {
3459 void CheckHelper::CheckDioAssumedLenCharacterArg(const Symbol &subp,
3460 const Symbol *arg, std::size_t argPosition, Attr intent) {
3482 const Symbol &subp, const Symbol *arg, std::size_t argPosition) {
3498 const Symbol &subp, common::DefinedIo ioKind, std::size_t argCount) {
3514 const Symbol &subp, const Symbol &arg, Attr goodIntent) {
3533 void CheckHelper::CheckDefinedIoProc(const Symbol &symbol,
3536 const Symbol &ultimate{ref->GetUltimate()};
3538 const Symbol &specific{*(binding ? &binding->symbol() : &ultimate)};
3546 const std::vector<Symbol *> &dummyArgs{subpDetails->dummyArgs()};
3553 CheckDioDtvArg(specific, arg, ioKind, symbol);
3597 void CheckHelper::CheckSymbolType(const Symbol &symbol) {
3598 const Symbol *result{FindFunctionResult(symbol)};
3599 const Symbol &relevant{result ? *result : symbol};
3601 } else if (IsProcedurePointer(symbol) && result && IsPointer(*result)) {
3607 !(IsDummy(symbol) && !IsProcedure(relevant))) { // C708
3610 symbol.name());
3615 symbol.name(), dyType->AsFortran());
3620 void CheckHelper::CheckModuleProcedureDef(const Symbol &symbol) {
3621 auto procClass{ClassifyProcedure(symbol)};
3622 if (const auto *subprogram{symbol.detailsIf<SubprogramDetails>()};
3625 symbol.attrs().test(Attr::MODULE)) &&
3627 const Symbol &interface {
3628 subprogram->moduleInterface() ? *subprogram->moduleInterface() : symbol
3630 if (const Symbol *
3632 ? interface.owner().symbol()
3635 std::pair<SourceName, const Symbol *> key{symbol.name(), module};
3638 moduleProcs_.emplace(std::move(key), symbol);
3640 auto *msg{messages_.Say(symbol.name(),
3642 symbol.name(), GetModuleOrSubmoduleName(*module))}) {
3644 symbol.name());
3651 const Symbol &symbol1, const Symbol &symbol2) {
3731 const Symbol *arg1{args1[i]};
3732 const Symbol *arg2{args2[i]};
3759 void SubprogramMatchHelper::CheckDummyArg(const Symbol &symbol1,
3760 const Symbol &symbol2, const DummyArgument &arg1,
3788 void SubprogramMatchHelper::CheckDummyDataObject(const Symbol &symbol1,
3789 const Symbol &symbol2, const DummyDataObject &obj1,
3805 void SubprogramMatchHelper::CheckDummyProcedure(const Symbol &symbol1,
3806 const Symbol &symbol2, const DummyProcedure &proc1,
3825 bool SubprogramMatchHelper::CheckSameIntent(const Symbol &symbol1,
3826 const Symbol &symbol2, common::Intent intent1, common::Intent intent2) {
3837 // Report an error referring to first symbol with declaration of second symbol
3839 void SubprogramMatchHelper::Say(const Symbol &symbol1, const Symbol &symbol2,
3848 const Symbol &symbol1, const Symbol &symbol2, ATTRS attrs1, ATTRS attrs2) {
3886 void DistinguishabilityHelper::Add(const Symbol &generic, GenericKind kind,
3887 const Symbol &ultimateSpecific, const Procedure &procedure) {
3920 const SourceName &name, GenericKind kind, const Symbol &proc1,
3921 const Symbol &proc2, bool isHardConflict) {
3973 parser::Message &msg, const Scope &scope, const Symbol &proc) {