forked from OSchip/llvm-project
[flang] Change AttachDeclaration to take reference instead of pointer
AttachDeclaration (and so also SayWithDeclaration) don't do anything when passed a null pointer for the symbol and in all but one place they are called the symbol can't be null. So change both function to take `const Symbol &` rather than `const Symbol *`. Change it to handle procedure bindings as well. Add `SayWithDeclaration` to `CheckHelper` to simplify calling the one in `evaluate` and prevent attaching the declaration when it would point at the same line. Original-commit: flang-compiler/f18@5f1c2ff663 Reviewed-on: https://github.com/flang-compiler/f18/pull/841 Tree-same-pre-rewrite: false
This commit is contained in:
parent
e2b939e5f3
commit
abc99c63ff
|
@ -739,27 +739,35 @@ bool HasVectorSubscript(const Expr<SomeType> &expr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
parser::Message *AttachDeclaration(
|
parser::Message *AttachDeclaration(
|
||||||
parser::Message &message, const Symbol *symbol) {
|
parser::Message &message, const Symbol &symbol) {
|
||||||
if (symbol) {
|
const Symbol *unhosted{&symbol};
|
||||||
const Symbol *unhosted{symbol};
|
|
||||||
while (
|
while (
|
||||||
const auto *assoc{unhosted->detailsIf<semantics::HostAssocDetails>()}) {
|
const auto *assoc{unhosted->detailsIf<semantics::HostAssocDetails>()}) {
|
||||||
unhosted = &assoc->symbol();
|
unhosted = &assoc->symbol();
|
||||||
}
|
}
|
||||||
if (const auto *use{symbol->detailsIf<semantics::UseDetails>()}) {
|
if (const auto *binding{
|
||||||
|
unhosted->detailsIf<semantics::ProcBindingDetails>()}) {
|
||||||
|
if (binding->symbol().name() != symbol.name()) {
|
||||||
|
message.Attach(binding->symbol().name(),
|
||||||
|
"Procedure '%s' is bound to '%s'"_en_US, symbol.name(),
|
||||||
|
binding->symbol().name());
|
||||||
|
return &message;
|
||||||
|
}
|
||||||
|
unhosted = &binding->symbol();
|
||||||
|
}
|
||||||
|
if (const auto *use{symbol.detailsIf<semantics::UseDetails>()}) {
|
||||||
message.Attach(use->location(),
|
message.Attach(use->location(),
|
||||||
"'%s' is USE-associated with '%s' in module '%s'"_en_US,
|
"'%s' is USE-associated with '%s' in module '%s'"_en_US, symbol.name(),
|
||||||
symbol->name(), unhosted->name(), use->module().name());
|
unhosted->name(), use->module().name());
|
||||||
} else {
|
} else {
|
||||||
message.Attach(
|
message.Attach(
|
||||||
unhosted->name(), "Declaration of '%s'"_en_US, symbol->name());
|
unhosted->name(), "Declaration of '%s'"_en_US, unhosted->name());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return &message;
|
return &message;
|
||||||
}
|
}
|
||||||
|
|
||||||
parser::Message *AttachDeclaration(
|
parser::Message *AttachDeclaration(
|
||||||
parser::Message *message, const Symbol *symbol) {
|
parser::Message *message, const Symbol &symbol) {
|
||||||
if (message) {
|
if (message) {
|
||||||
AttachDeclaration(*message, symbol);
|
AttachDeclaration(*message, symbol);
|
||||||
}
|
}
|
||||||
|
|
|
@ -810,11 +810,11 @@ bool HasVectorSubscript(const Expr<SomeType> &);
|
||||||
// Utilities for attaching the location of the declaration of a symbol
|
// Utilities for attaching the location of the declaration of a symbol
|
||||||
// of interest to a message, if both pointers are non-null. Handles
|
// of interest to a message, if both pointers are non-null. Handles
|
||||||
// the case of USE association gracefully.
|
// the case of USE association gracefully.
|
||||||
parser::Message *AttachDeclaration(parser::Message &, const Symbol *);
|
parser::Message *AttachDeclaration(parser::Message &, const Symbol &);
|
||||||
parser::Message *AttachDeclaration(parser::Message *, const Symbol *);
|
parser::Message *AttachDeclaration(parser::Message *, const Symbol &);
|
||||||
template<typename MESSAGES, typename... A>
|
template<typename MESSAGES, typename... A>
|
||||||
parser::Message *SayWithDeclaration(
|
parser::Message *SayWithDeclaration(
|
||||||
MESSAGES &messages, const Symbol *symbol, A &&... x) {
|
MESSAGES &messages, const Symbol &symbol, A &&... x) {
|
||||||
return AttachDeclaration(messages.Say(std::forward<A>(x)...), symbol);
|
return AttachDeclaration(messages.Say(std::forward<A>(x)...), symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -147,7 +147,7 @@ private:
|
||||||
template<typename... A> parser::Message *Say(A &&... x) {
|
template<typename... A> parser::Message *Say(A &&... x) {
|
||||||
auto *msg{messages_.Say(std::forward<A>(x)...)};
|
auto *msg{messages_.Say(std::forward<A>(x)...)};
|
||||||
if (pointer_) {
|
if (pointer_) {
|
||||||
return AttachDeclaration(msg, pointer_);
|
return AttachDeclaration(msg, *pointer_);
|
||||||
} else if (!source_.empty()) {
|
} else if (!source_.empty()) {
|
||||||
msg->Attach(source_, "Declaration of %s"_en_US, description_);
|
msg->Attach(source_, "Declaration of %s"_en_US, description_);
|
||||||
}
|
}
|
||||||
|
@ -227,7 +227,7 @@ void CheckPointerAssignment(parser::ContextualMessages &messages,
|
||||||
// from the RHS.
|
// from the RHS.
|
||||||
if (!IsPointer(lhs)) {
|
if (!IsPointer(lhs)) {
|
||||||
SayWithDeclaration(
|
SayWithDeclaration(
|
||||||
messages, &lhs, "'%s' is not a pointer"_err_en_US, lhs.name());
|
messages, lhs, "'%s' is not a pointer"_err_en_US, lhs.name());
|
||||||
} else {
|
} else {
|
||||||
auto type{characteristics::TypeAndShape::Characterize(lhs)};
|
auto type{characteristics::TypeAndShape::Characterize(lhs)};
|
||||||
auto proc{characteristics::Procedure::Characterize(lhs, intrinsics)};
|
auto proc{characteristics::Procedure::Characterize(lhs, intrinsics)};
|
||||||
|
@ -584,7 +584,7 @@ static const char *WhyBaseObjectIsSuspicious(
|
||||||
void CheckDefinabilityInPureScope(parser::ContextualMessages &messages,
|
void CheckDefinabilityInPureScope(parser::ContextualMessages &messages,
|
||||||
const Symbol &lhs, const Scope &scope) {
|
const Symbol &lhs, const Scope &scope) {
|
||||||
if (const char *why{WhyBaseObjectIsSuspicious(lhs, scope)}) {
|
if (const char *why{WhyBaseObjectIsSuspicious(lhs, scope)}) {
|
||||||
evaluate::SayWithDeclaration(messages, &lhs,
|
evaluate::SayWithDeclaration(messages, lhs,
|
||||||
"A PURE subprogram may not define '%s' because it is %s"_err_en_US,
|
"A PURE subprogram may not define '%s' because it is %s"_err_en_US,
|
||||||
lhs.name(), why);
|
lhs.name(), why);
|
||||||
}
|
}
|
||||||
|
@ -611,7 +611,7 @@ void CheckCopyabilityInPureScope(parser::ContextualMessages &messages,
|
||||||
if (const Symbol * base{GetFirstSymbol(expr)}) {
|
if (const Symbol * base{GetFirstSymbol(expr)}) {
|
||||||
if (const char *why{WhyBaseObjectIsSuspicious(*base, scope)}) {
|
if (const char *why{WhyBaseObjectIsSuspicious(*base, scope)}) {
|
||||||
if (auto pointer{GetPointerComponentDesignatorName(expr)}) {
|
if (auto pointer{GetPointerComponentDesignatorName(expr)}) {
|
||||||
evaluate::SayWithDeclaration(messages, base,
|
evaluate::SayWithDeclaration(messages, *base,
|
||||||
"A PURE subprogram may not copy the value of '%s' because it is %s and has the POINTER component '%s'"_err_en_US,
|
"A PURE subprogram may not copy the value of '%s' because it is %s and has the POINTER component '%s'"_err_en_US,
|
||||||
base->name(), why, *pointer);
|
base->name(), why, *pointer);
|
||||||
}
|
}
|
||||||
|
@ -634,7 +634,7 @@ void AssignmentContext::CheckForPureContext(const SomeExpr &lhs,
|
||||||
if (const Symbol * base{GetFirstSymbol(rhs)}) {
|
if (const Symbol * base{GetFirstSymbol(rhs)}) {
|
||||||
if (const char *why{
|
if (const char *why{
|
||||||
WhyBaseObjectIsSuspicious(*base, scope)}) { // C1594(3)
|
WhyBaseObjectIsSuspicious(*base, scope)}) { // C1594(3)
|
||||||
evaluate::SayWithDeclaration(messages, base,
|
evaluate::SayWithDeclaration(messages, *base,
|
||||||
"A PURE subprogram may not use '%s' as the target of pointer assignment because it is %s"_err_en_US,
|
"A PURE subprogram may not use '%s' as the target of pointer assignment because it is %s"_err_en_US,
|
||||||
base->name(), why);
|
base->name(), why);
|
||||||
}
|
}
|
||||||
|
@ -652,7 +652,7 @@ void AssignmentContext::CheckForPureContext(const SomeExpr &lhs,
|
||||||
const DerivedTypeSpec &derived{type->GetDerivedTypeSpec()};
|
const DerivedTypeSpec &derived{type->GetDerivedTypeSpec()};
|
||||||
if (auto bad{FindPolymorphicAllocatableNonCoarrayUltimateComponent(
|
if (auto bad{FindPolymorphicAllocatableNonCoarrayUltimateComponent(
|
||||||
derived)}) {
|
derived)}) {
|
||||||
evaluate::SayWithDeclaration(messages, &*bad,
|
evaluate::SayWithDeclaration(messages, *bad,
|
||||||
"Deallocation of polymorphic non-coarray component '%s' is not permitted in a PURE subprogram"_err_en_US,
|
"Deallocation of polymorphic non-coarray component '%s' is not permitted in a PURE subprogram"_err_en_US,
|
||||||
bad.BuildResultDesignatorName());
|
bad.BuildResultDesignatorName());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -170,7 +170,7 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
|
||||||
tbp{FindImmediateComponent(derived, [](const Symbol &symbol) {
|
tbp{FindImmediateComponent(derived, [](const Symbol &symbol) {
|
||||||
return symbol.has<ProcBindingDetails>();
|
return symbol.has<ProcBindingDetails>();
|
||||||
})}) { // 15.5.2.4(2)
|
})}) { // 15.5.2.4(2)
|
||||||
evaluate::SayWithDeclaration(messages, tbp,
|
evaluate::SayWithDeclaration(messages, *tbp,
|
||||||
"Actual argument associated with TYPE(*) %s may not have type-bound procedure '%s'"_err_en_US,
|
"Actual argument associated with TYPE(*) %s may not have type-bound procedure '%s'"_err_en_US,
|
||||||
dummyName, tbp->name());
|
dummyName, tbp->name());
|
||||||
}
|
}
|
||||||
|
@ -178,7 +178,7 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
|
||||||
finalizer{FindImmediateComponent(derived, [](const Symbol &symbol) {
|
finalizer{FindImmediateComponent(derived, [](const Symbol &symbol) {
|
||||||
return symbol.has<FinalProcDetails>();
|
return symbol.has<FinalProcDetails>();
|
||||||
})}) { // 15.5.2.4(2)
|
})}) { // 15.5.2.4(2)
|
||||||
evaluate::SayWithDeclaration(messages, finalizer,
|
evaluate::SayWithDeclaration(messages, *finalizer,
|
||||||
"Actual argument associated with TYPE(*) %s may not have FINAL subroutine '%s'"_err_en_US,
|
"Actual argument associated with TYPE(*) %s may not have FINAL subroutine '%s'"_err_en_US,
|
||||||
dummyName, finalizer->name());
|
dummyName, finalizer->name());
|
||||||
}
|
}
|
||||||
|
@ -187,7 +187,7 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
|
||||||
if (dummy.intent != common::Intent::In && !dummyIsValue) {
|
if (dummy.intent != common::Intent::In && !dummyIsValue) {
|
||||||
if (auto bad{
|
if (auto bad{
|
||||||
FindAllocatableUltimateComponent(derived)}) { // 15.5.2.4(6)
|
FindAllocatableUltimateComponent(derived)}) { // 15.5.2.4(6)
|
||||||
evaluate::SayWithDeclaration(messages, &*bad,
|
evaluate::SayWithDeclaration(messages, *bad,
|
||||||
"Coindexed actual argument with ALLOCATABLE ultimate component '%s' must be associated with a %s with VALUE or INTENT(IN) attributes"_err_en_US,
|
"Coindexed actual argument with ALLOCATABLE ultimate component '%s' must be associated with a %s with VALUE or INTENT(IN) attributes"_err_en_US,
|
||||||
bad.BuildResultDesignatorName(), dummyName);
|
bad.BuildResultDesignatorName(), dummyName);
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,7 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
|
||||||
if (const DeclTypeSpec * type{coarray.GetType()}) {
|
if (const DeclTypeSpec * type{coarray.GetType()}) {
|
||||||
if (const DerivedTypeSpec * derived{type->AsDerived()}) {
|
if (const DerivedTypeSpec * derived{type->AsDerived()}) {
|
||||||
if (auto bad{semantics::FindPointerUltimateComponent(*derived)}) {
|
if (auto bad{semantics::FindPointerUltimateComponent(*derived)}) {
|
||||||
evaluate::SayWithDeclaration(messages, &coarray,
|
evaluate::SayWithDeclaration(messages, coarray,
|
||||||
"Coindexed object '%s' with POINTER ultimate component '%s' cannot be associated with %s"_err_en_US,
|
"Coindexed object '%s' with POINTER ultimate component '%s' cannot be associated with %s"_err_en_US,
|
||||||
coarray.name(), bad.BuildResultDesignatorName(), dummyName);
|
coarray.name(), bad.BuildResultDesignatorName(), dummyName);
|
||||||
}
|
}
|
||||||
|
@ -207,7 +207,7 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
|
||||||
}
|
}
|
||||||
if (actualIsVolatile != dummyIsVolatile) { // 15.5.2.4(22)
|
if (actualIsVolatile != dummyIsVolatile) { // 15.5.2.4(22)
|
||||||
if (auto bad{semantics::FindCoarrayUltimateComponent(derived)}) {
|
if (auto bad{semantics::FindCoarrayUltimateComponent(derived)}) {
|
||||||
evaluate::SayWithDeclaration(messages, &*bad,
|
evaluate::SayWithDeclaration(messages, *bad,
|
||||||
"VOLATILE attribute must match for %s when actual argument has a coarray ultimate component '%s'"_err_en_US,
|
"VOLATILE attribute must match for %s when actual argument has a coarray ultimate component '%s'"_err_en_US,
|
||||||
dummyName, bad.BuildResultDesignatorName());
|
dummyName, bad.BuildResultDesignatorName());
|
||||||
}
|
}
|
||||||
|
@ -232,8 +232,8 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
|
||||||
"Scalar actual argument may not be associated with assumed-shape %s"_err_en_US,
|
"Scalar actual argument may not be associated with assumed-shape %s"_err_en_US,
|
||||||
dummyName);
|
dummyName);
|
||||||
}
|
}
|
||||||
if (actualIsAssumedSize) {
|
if (actualIsAssumedSize && actualLastSymbol) {
|
||||||
evaluate::SayWithDeclaration(messages, actualLastSymbol,
|
evaluate::SayWithDeclaration(messages, *actualLastSymbol,
|
||||||
"Assumed-size array may not be associated with assumed-shape %s"_err_en_US,
|
"Assumed-size array may not be associated with assumed-shape %s"_err_en_US,
|
||||||
dummyName);
|
dummyName);
|
||||||
}
|
}
|
||||||
|
@ -467,7 +467,7 @@ static void CheckProcedureArg(evaluate::ActualArgument &arg,
|
||||||
} else if (argInterface.attrs.test(
|
} else if (argInterface.attrs.test(
|
||||||
characteristics::Procedure::Attr::Elemental)) {
|
characteristics::Procedure::Attr::Elemental)) {
|
||||||
if (argProcSymbol) { // C1533
|
if (argProcSymbol) { // C1533
|
||||||
evaluate::SayWithDeclaration(messages, argProcSymbol,
|
evaluate::SayWithDeclaration(messages, *argProcSymbol,
|
||||||
"Non-intrinsic ELEMENTAL procedure '%s' may not be passed as an actual argument"_err_en_US,
|
"Non-intrinsic ELEMENTAL procedure '%s' may not be passed as an actual argument"_err_en_US,
|
||||||
argProcSymbol->name());
|
argProcSymbol->name());
|
||||||
return; // avoid piling on with checks below
|
return; // avoid piling on with checks below
|
||||||
|
|
|
@ -54,6 +54,14 @@ private:
|
||||||
void CheckVolatile(
|
void CheckVolatile(
|
||||||
const Symbol &, bool isAssociated, const DerivedTypeSpec *);
|
const Symbol &, bool isAssociated, const DerivedTypeSpec *);
|
||||||
void CheckBinding(const Symbol &);
|
void CheckBinding(const Symbol &);
|
||||||
|
template<typename... A>
|
||||||
|
void SayWithDeclaration(const Symbol &symbol, A &&... x) {
|
||||||
|
if (parser::Message * msg{messages_.Say(std::forward<A>(x)...)}) {
|
||||||
|
if (messages_.at() != symbol.name()) {
|
||||||
|
evaluate::AttachDeclaration(*msg, symbol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SemanticsContext &context_;
|
SemanticsContext &context_;
|
||||||
evaluate::FoldingContext &foldingContext_{context_.foldingContext()};
|
evaluate::FoldingContext &foldingContext_{context_.foldingContext()};
|
||||||
|
@ -131,7 +139,7 @@ void CheckHelper::Check(const Symbol &symbol) {
|
||||||
for (const Symbol &component : components) {
|
for (const Symbol &component : components) {
|
||||||
if (component.attrs().test(Attr::DEFERRED)) {
|
if (component.attrs().test(Attr::DEFERRED)) {
|
||||||
if (symbol.scope()->FindComponent(component.name()) == &component) {
|
if (symbol.scope()->FindComponent(component.name()) == &component) {
|
||||||
evaluate::SayWithDeclaration(messages_, &component,
|
SayWithDeclaration(component,
|
||||||
"Non-ABSTRACT extension of ABSTRACT derived type '%s' lacks a binding for DEFERRED procedure '%s'"_err_en_US,
|
"Non-ABSTRACT extension of ABSTRACT derived type '%s' lacks a binding for DEFERRED procedure '%s'"_err_en_US,
|
||||||
parentDerived->typeSymbol().name(), component.name());
|
parentDerived->typeSymbol().name(), component.name());
|
||||||
}
|
}
|
||||||
|
@ -157,12 +165,12 @@ void CheckHelper::Check(const Symbol &symbol) {
|
||||||
}
|
}
|
||||||
if (!IsDummy(symbol) && !IsFunctionResult(symbol)) {
|
if (!IsDummy(symbol) && !IsFunctionResult(symbol)) {
|
||||||
if (IsPolymorphicAllocatable(symbol)) {
|
if (IsPolymorphicAllocatable(symbol)) {
|
||||||
evaluate::SayWithDeclaration(messages_, &symbol,
|
SayWithDeclaration(symbol,
|
||||||
"Deallocation of polymorphic object '%s' is not permitted in a PURE subprogram"_err_en_US,
|
"Deallocation of polymorphic object '%s' is not permitted in a PURE subprogram"_err_en_US,
|
||||||
symbol.name());
|
symbol.name());
|
||||||
} else if (derived) {
|
} else if (derived) {
|
||||||
if (auto bad{FindPolymorphicAllocatableUltimateComponent(*derived)}) {
|
if (auto bad{FindPolymorphicAllocatableUltimateComponent(*derived)}) {
|
||||||
evaluate::SayWithDeclaration(messages_, &*bad,
|
SayWithDeclaration(*bad,
|
||||||
"Deallocation of polymorphic object '%s%s' is not permitted in a PURE subprogram"_err_en_US,
|
"Deallocation of polymorphic object '%s%s' is not permitted in a PURE subprogram"_err_en_US,
|
||||||
symbol.name(), bad.BuildResultDesignatorName());
|
symbol.name(), bad.BuildResultDesignatorName());
|
||||||
}
|
}
|
||||||
|
@ -193,7 +201,7 @@ void CheckHelper::Check(const Symbol &symbol) {
|
||||||
}
|
}
|
||||||
if (derived) {
|
if (derived) {
|
||||||
if (auto bad{FindPolymorphicAllocatableUltimateComponent(*derived)}) {
|
if (auto bad{FindPolymorphicAllocatableUltimateComponent(*derived)}) {
|
||||||
evaluate::SayWithDeclaration(messages_, &*bad,
|
SayWithDeclaration(*bad,
|
||||||
"Result of PURE function may not have polymorphic ALLOCATABLE ultimate component '%s'"_err_en_US,
|
"Result of PURE function may not have polymorphic ALLOCATABLE ultimate component '%s'"_err_en_US,
|
||||||
bad.BuildResultDesignatorName());
|
bad.BuildResultDesignatorName());
|
||||||
}
|
}
|
||||||
|
@ -383,7 +391,7 @@ void CheckHelper::CheckBinding(const Symbol &symbol) {
|
||||||
if (const Symbol * dtSymbol{dtScope.symbol()}) {
|
if (const Symbol * dtSymbol{dtScope.symbol()}) {
|
||||||
if (symbol.attrs().test(Attr::DEFERRED)) {
|
if (symbol.attrs().test(Attr::DEFERRED)) {
|
||||||
if (!dtSymbol->attrs().test(Attr::ABSTRACT)) {
|
if (!dtSymbol->attrs().test(Attr::ABSTRACT)) {
|
||||||
evaluate::SayWithDeclaration(messages_, dtSymbol,
|
SayWithDeclaration(*dtSymbol,
|
||||||
"Procedure bound to non-ABSTRACT derived type '%s' may not be DEFERRED"_err_en_US,
|
"Procedure bound to non-ABSTRACT derived type '%s' may not be DEFERRED"_err_en_US,
|
||||||
dtSymbol->name());
|
dtSymbol->name());
|
||||||
}
|
}
|
||||||
|
@ -396,7 +404,7 @@ void CheckHelper::CheckBinding(const Symbol &symbol) {
|
||||||
}
|
}
|
||||||
if (const Symbol * overridden{FindOverriddenBinding(symbol)}) {
|
if (const Symbol * overridden{FindOverriddenBinding(symbol)}) {
|
||||||
if (overridden->attrs().test(Attr::NON_OVERRIDABLE)) {
|
if (overridden->attrs().test(Attr::NON_OVERRIDABLE)) {
|
||||||
evaluate::SayWithDeclaration(messages_, overridden,
|
SayWithDeclaration(*overridden,
|
||||||
"Override of NON_OVERRIDABLE '%s' is not permitted"_err_en_US,
|
"Override of NON_OVERRIDABLE '%s' is not permitted"_err_en_US,
|
||||||
symbol.name());
|
symbol.name());
|
||||||
}
|
}
|
||||||
|
@ -404,13 +412,13 @@ void CheckHelper::CheckBinding(const Symbol &symbol) {
|
||||||
overridden->detailsIf<ProcBindingDetails>()}) {
|
overridden->detailsIf<ProcBindingDetails>()}) {
|
||||||
if (!binding.symbol().attrs().test(Attr::PURE) &&
|
if (!binding.symbol().attrs().test(Attr::PURE) &&
|
||||||
overriddenBinding->symbol().attrs().test(Attr::PURE)) {
|
overriddenBinding->symbol().attrs().test(Attr::PURE)) {
|
||||||
evaluate::SayWithDeclaration(messages_, overridden,
|
SayWithDeclaration(*overridden,
|
||||||
"An overridden PURE type-bound procedure binding must also be PURE"_err_en_US);
|
"An overridden PURE type-bound procedure binding must also be PURE"_err_en_US);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!binding.symbol().attrs().test(Attr::ELEMENTAL) &&
|
if (!binding.symbol().attrs().test(Attr::ELEMENTAL) &&
|
||||||
overriddenBinding->symbol().attrs().test(Attr::ELEMENTAL)) {
|
overriddenBinding->symbol().attrs().test(Attr::ELEMENTAL)) {
|
||||||
evaluate::SayWithDeclaration(messages_, overridden,
|
SayWithDeclaration(*overridden,
|
||||||
"A type-bound procedure and its override must both, or neither, be ELEMENTAL"_err_en_US);
|
"A type-bound procedure and its override must both, or neither, be ELEMENTAL"_err_en_US);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -424,33 +432,33 @@ void CheckHelper::CheckBinding(const Symbol &symbol) {
|
||||||
if (passIndex == *overriddenBinding->passIndex()) {
|
if (passIndex == *overriddenBinding->passIndex()) {
|
||||||
if (!(bindingChars && overriddenChars &&
|
if (!(bindingChars && overriddenChars &&
|
||||||
bindingChars->CanOverride(*overriddenChars, passIndex))) {
|
bindingChars->CanOverride(*overriddenChars, passIndex))) {
|
||||||
evaluate::SayWithDeclaration(messages_, overridden,
|
SayWithDeclaration(*overridden,
|
||||||
"A type-bound procedure and its override must have compatible interfaces apart from their passed argument"_err_en_US);
|
"A type-bound procedure and its override must have compatible interfaces apart from their passed argument"_err_en_US);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
evaluate::SayWithDeclaration(messages_, overridden,
|
SayWithDeclaration(*overridden,
|
||||||
"A type-bound procedure and its override must use the same PASS argument"_err_en_US);
|
"A type-bound procedure and its override must use the same PASS argument"_err_en_US);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
evaluate::SayWithDeclaration(messages_, overridden,
|
SayWithDeclaration(*overridden,
|
||||||
"A passed-argument type-bound procedure may not override a NOPASS procedure"_err_en_US);
|
"A passed-argument type-bound procedure may not override a NOPASS procedure"_err_en_US);
|
||||||
}
|
}
|
||||||
} else if (overriddenBinding->passIndex()) {
|
} else if (overriddenBinding->passIndex()) {
|
||||||
evaluate::SayWithDeclaration(messages_, overridden,
|
SayWithDeclaration(*overridden,
|
||||||
"A NOPASS type-bound procedure may not override a passed-argument procedure"_err_en_US);
|
"A NOPASS type-bound procedure may not override a passed-argument procedure"_err_en_US);
|
||||||
} else if (!(bindingChars && overriddenChars &&
|
} else if (!(bindingChars && overriddenChars &&
|
||||||
bindingChars->CanOverride(
|
bindingChars->CanOverride(
|
||||||
*overriddenChars, std::nullopt))) {
|
*overriddenChars, std::nullopt))) {
|
||||||
evaluate::SayWithDeclaration(messages_, overridden,
|
SayWithDeclaration(*overridden,
|
||||||
"A type-bound procedure and its override must have compatible interfaces"_err_en_US);
|
"A type-bound procedure and its override must have compatible interfaces"_err_en_US);
|
||||||
}
|
}
|
||||||
if (symbol.attrs().test(Attr::PRIVATE) &&
|
if (symbol.attrs().test(Attr::PRIVATE) &&
|
||||||
overridden->attrs().test(Attr::PUBLIC)) {
|
overridden->attrs().test(Attr::PUBLIC)) {
|
||||||
evaluate::SayWithDeclaration(messages_, overridden,
|
SayWithDeclaration(*overridden,
|
||||||
"A PRIVATE procedure may not override a PUBLIC procedure"_err_en_US);
|
"A PRIVATE procedure may not override a PUBLIC procedure"_err_en_US);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
evaluate::SayWithDeclaration(messages_, overridden,
|
SayWithDeclaration(*overridden,
|
||||||
"A type-bound procedure binding may not have the same name as a parent component"_err_en_US);
|
"A type-bound procedure binding may not have the same name as a parent component"_err_en_US);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1315,7 +1315,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(
|
||||||
"ABSTRACT derived type '%s' may not be used in a "
|
"ABSTRACT derived type '%s' may not be used in a "
|
||||||
"structure constructor"_err_en_US,
|
"structure constructor"_err_en_US,
|
||||||
typeName),
|
typeName),
|
||||||
&typeSymbol);
|
typeSymbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This iterator traverses all of the components in the derived type and its
|
// This iterator traverses all of the components in the derived type and its
|
||||||
|
@ -1477,14 +1477,14 @@ MaybeExpr ExpressionAnalyzer::Analyze(
|
||||||
"incompatible with component '%s' of type %s"_err_en_US,
|
"incompatible with component '%s' of type %s"_err_en_US,
|
||||||
valueType->AsFortran(), symbol->name(),
|
valueType->AsFortran(), symbol->name(),
|
||||||
symType->AsFortran()),
|
symType->AsFortran()),
|
||||||
symbol);
|
*symbol);
|
||||||
} else {
|
} else {
|
||||||
AttachDeclaration(
|
AttachDeclaration(
|
||||||
Say(expr.source,
|
Say(expr.source,
|
||||||
"Value in structure constructor is incompatible with "
|
"Value in structure constructor is incompatible with "
|
||||||
" component '%s' of type %s"_err_en_US,
|
" component '%s' of type %s"_err_en_US,
|
||||||
symbol->name(), symType->AsFortran()),
|
symbol->name(), symType->AsFortran()),
|
||||||
symbol);
|
*symbol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1505,7 +1505,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(
|
||||||
"Structure constructor lacks a value for "
|
"Structure constructor lacks a value for "
|
||||||
"component '%s'"_err_en_US,
|
"component '%s'"_err_en_US,
|
||||||
symbol.name()),
|
symbol.name()),
|
||||||
&symbol);
|
symbol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1727,7 +1727,7 @@ void ExpressionAnalyzer::CheckForBadRecursion(
|
||||||
"Assumed-length CHARACTER(*) function '%s' cannot call itself"_err_en_US,
|
"Assumed-length CHARACTER(*) function '%s' cannot call itself"_err_en_US,
|
||||||
callSite);
|
callSite);
|
||||||
}
|
}
|
||||||
AttachDeclaration(msg, &proc);
|
AttachDeclaration(msg, proc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2125,7 +2125,7 @@ static void CheckFuncRefToArrayElementRefHasSubscripts(
|
||||||
"A result variable must be declared with RESULT to allow recursive "
|
"A result variable must be declared with RESULT to allow recursive "
|
||||||
"function calls"_en_US);
|
"function calls"_en_US);
|
||||||
} else {
|
} else {
|
||||||
AttachDeclaration(&msg, name->symbol);
|
AttachDeclaration(&msg, *name->symbol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,7 +143,7 @@ public:
|
||||||
void SayWithDecl(const Symbol &symbol, const parser::CharBlock &at,
|
void SayWithDecl(const Symbol &symbol, const parser::CharBlock &at,
|
||||||
parser::MessageFixedText &&msg, A &&... args) {
|
parser::MessageFixedText &&msg, A &&... args) {
|
||||||
auto &message{Say(at, std::move(msg), args...)};
|
auto &message{Say(at, std::move(msg), args...)};
|
||||||
evaluate::AttachDeclaration(&message, &symbol);
|
evaluate::AttachDeclaration(&message, symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Scope &FindScope(parser::CharBlock) const;
|
const Scope &FindScope(parser::CharBlock) const;
|
||||||
|
|
Loading…
Reference in New Issue