template<typename... A> bool IsInitialDataTarget(const std::variant<A...> &);
bool IsInitialDataTarget(const DataRef &);
template<typename T> bool IsInitialDataTarget(const Expr<T> &);
-bool IsInitialDataTarget(const semantics::Symbol *s) { return true; }
+bool IsInitialDataTarget(const semantics::Symbol &s) { return true; }
+bool IsInitialDataTarget(const semantics::Symbol *s) {
+ return IsInitialDataTarget(*s);
+}
bool IsInitialDataTarget(const Component &x) {
return IsInitialDataTarget(x.base());
}
+bool IsInitialDataTarget(const NamedEntity &x) {
+ if (const Component * c{x.UnwrapComponent()}) {
+ return IsInitialDataTarget(*c);
+ } else {
+ return IsInitialDataTarget(x.GetLastSymbol());
+ }
+}
bool IsInitialDataTarget(const Triplet &x) {
if (auto lower{x.lower()}) {
if (!IsConstantExpr(*lower)) {
}
return IsInitialDataTarget(x.base());
}
-bool IsInitialDataTarget(const DataRef &x) {
- return std::visit([](const auto &y) { return IsInitialDataTarget(y); }, x.u);
-}
+bool IsInitialDataTarget(const DataRef &x) { return IsInitialDataTarget(x.u); }
bool IsInitialDataTarget(const Substring &x) {
return IsConstantExpr(x.lower()) && IsConstantExpr(x.upper());
}
void SetSaveAttr(Symbol &);
bool HandleUnrestrictedSpecificIntrinsicFunction(const parser::Name &);
const parser::Name *FindComponent(const parser::Name *, const parser::Name &);
- void CheckInitialDataTarget(const Symbol &, const SomeExpr &);
+ void CheckInitialDataTarget(const Symbol &, const SomeExpr &, SourceName);
void Initialization(const parser::Name &, const parser::Initialization &,
bool inComponentDecl);
// C764, C765
void DeclarationVisitor::CheckInitialDataTarget(
- const Symbol &pointer, const SomeExpr &expr) {
+ const Symbol &pointer, const SomeExpr &expr, SourceName source) {
+ if (!evaluate::IsInitialDataTarget(expr)) {
+ Say(source,
+ "Pointer '%s' cannot be initialized with a reference to a designator with non-constant subscripts"_err_en_US,
+ pointer.name());
+ return;
+ }
+ if (pointer.Rank() != expr.Rank()) {
+ Say(source,
+ "Pointer '%s' of rank %d cannot be initialized with a target of different rank (%d)"_err_en_US,
+ pointer.name(), pointer.Rank(), expr.Rank());
+ return;
+ }
if (auto base{evaluate::GetBaseObject(expr)}) {
if (const Symbol * baseSym{base->symbol()}) {
const Symbol &ultimate{baseSym->GetUltimate()};
- if (!IsAllocatable(ultimate) && ultimate.Corank() == 0 &&
- ultimate.attrs().HasAll({Attr::TARGET, Attr::SAVE}) &&
- evaluate::IsInitialDataTarget(expr)) {
- // TODO: check type compatibility
- // TODO: check non-deferred type parameter values
- // TODO: check contiguity if pointer is CONTIGUOUS
- if (pointer.Rank() != expr.Rank()) {
- Say(pointer.name(),
- "Pointer '%s' initialized with target of different rank"_err_en_US);
- }
+ if (IsAllocatable(ultimate)) {
+ Say(source,
+ "Pointer '%s' cannot be initialized with a reference to an allocatable '%s'"_err_en_US,
+ pointer.name(), ultimate.name());
+ return;
+ }
+ if (ultimate.Corank() > 0) {
+ Say(source,
+ "Pointer '%s' cannot be initialized with a reference to a coarray '%s'"_err_en_US,
+ pointer.name(), ultimate.name());
+ return;
+ }
+ if (!ultimate.attrs().test(Attr::TARGET)) {
+ Say(source,
+ "Pointer '%s' cannot be initialized with a reference to an object '%s' that lacks the TARGET attribute"_err_en_US,
+ pointer.name(), ultimate.name());
+ return;
+ }
+ if (!ultimate.attrs().test(Attr::SAVE)) {
+ Say(source,
+ "Pointer '%s' cannot be initialized with a reference to an object '%s' that lacks the SAVE attribute"_err_en_US,
+ pointer.name(), ultimate.name());
return;
}
}
}
- Say(pointer.name(),
- "Pointer '%s' initialized with invalid data target designator"_err_en_US);
+ // TODO: check type compatibility
+ // TODO: check non-deferred type parameter values
+ // TODO: check contiguity if pointer is CONTIGUOUS
}
void DeclarationVisitor::Initialization(const parser::Name &name,
[&](const parser::InitialDataTarget &initExpr) {
isPointer = true;
if (MaybeExpr expr{EvaluateExpr(initExpr)}) {
- CheckInitialDataTarget(ultimate, *expr);
+ CheckInitialDataTarget(
+ ultimate, *expr, initExpr.value().source);
details->set_init(std::move(*expr));
}
},
omp-clause-validity01.f90
# omp-nested01.f90
equivalence01.f90
+ init01.f90
)
# These test files have expected symbols in the source
--- /dev/null
+! Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
+!
+! Licensed under the Apache License, Version 2.0 (the "License");
+! you may not use this file except in compliance with the License.
+! You may obtain a copy of the License at
+!
+! http://www.apache.org/licenses/LICENSE-2.0
+!
+! Unless required by applicable law or agreed to in writing, software
+! distributed under the License is distributed on an "AS IS" BASIS,
+! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+! See the License for the specific language governing permissions and
+! limitations under the License.
+
+! Object pointer initializer error tests
+
+subroutine test(j)
+ integer, intent(in) :: j
+ real, allocatable, target, save :: x1
+ real, codimension[:], target, save :: x2
+ real, save :: x3
+ real, target :: x4
+ real, target, save :: x5(10)
+!ERROR: Pointer 'p1' cannot be initialized with a reference to an allocatable 'x1'
+ real, pointer :: p1 => x1
+!ERROR: Pointer 'p2' cannot be initialized with a reference to a coarray 'x2'
+ real, pointer :: p2 => x2
+!ERROR: Pointer 'p3' cannot be initialized with a reference to an object 'x3' that lacks the TARGET attribute
+ real, pointer :: p3 => x3
+!ERROR: Pointer 'p4' cannot be initialized with a reference to an object 'x4' that lacks the SAVE attribute
+ real, pointer :: p4 => x4
+!ERROR: Pointer 'p5' cannot be initialized with a reference to a designator with non-constant subscripts
+ real, pointer :: p5 => x5(j)
+!ERROR: Pointer 'p6' of rank 0 cannot be initialized with a target of different rank (1)
+ real, pointer :: p6 => x5
+
+!TODO: type incompatibility, non-deferred type parameter values, contiguity
+
+end subroutine test