mirror of
https://github.com/intel/llvm.git
synced 2026-01-21 20:53:29 +08:00
[flang] Improve error messages
Original-commit: flang-compiler/f18@4046134512 Reviewed-on: https://github.com/flang-compiler/f18/pull/311 Tree-same-pre-rewrite: false
This commit is contained in:
@@ -1490,10 +1490,21 @@ static MaybeExpr AnalyzeExpr(ExpressionAnalysisContext &context,
|
||||
const auto &innermost{context.context().FindScope(expr.source)};
|
||||
if (const auto *pureFunc{
|
||||
semantics::FindPureFunctionContaining(&innermost)}) {
|
||||
if (semantics::IsOrHasPointerComponent(*symbol) &&
|
||||
semantics::IsExternallyVisibleObject(*value, *pureFunc)) {
|
||||
context.Say(expr.source,
|
||||
"Externally visible object must not be associated with a pointer in a PURE function"_err_en_US);
|
||||
if (const Symbol *
|
||||
pointer{semantics::FindPointerComponent(*symbol)}) {
|
||||
if (const Symbol *
|
||||
object{semantics::FindExternallyVisibleObject(
|
||||
*value, *pureFunc)}) {
|
||||
if (auto *msg{context.Say(expr.source,
|
||||
"Externally visible object '%s' must not be "
|
||||
"associated with pointer component '%s' in a "
|
||||
"PURE function"_err_en_US,
|
||||
object->name().ToString().data(),
|
||||
pointer->name().ToString().data())}) {
|
||||
msg->Attach(object->name(), "Object declaration"_en_US)
|
||||
.Attach(pointer->name(), "Pointer declaration"_en_US);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,70 +143,84 @@ bool IsPureFunction(const Scope &scope) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool HasPointerComponent(
|
||||
static const Symbol *FindPointerComponent(
|
||||
const Scope &scope, std::set<const Scope *> &visited) {
|
||||
if (scope.kind() != Scope::Kind::DerivedType) {
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
if (!visited.insert(&scope).second) {
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
// If there's a top-level pointer component, return it for clearer error
|
||||
// messaging.
|
||||
for (const auto &pair : scope) {
|
||||
const Symbol &symbol{*pair.second};
|
||||
if (symbol.attrs().test(Attr::POINTER)) {
|
||||
return true;
|
||||
return &symbol;
|
||||
}
|
||||
}
|
||||
for (const auto &pair : scope) {
|
||||
const Symbol &symbol{*pair.second};
|
||||
if (const auto *details{symbol.detailsIf<ObjectEntityDetails>()}) {
|
||||
if (const DeclTypeSpec * type{details->type()}) {
|
||||
if (const DerivedTypeSpec * derived{type->AsDerived()}) {
|
||||
if (const Scope * nested{derived->scope()}) {
|
||||
if (HasPointerComponent(*nested, visited)) {
|
||||
return true;
|
||||
if (const Symbol *
|
||||
pointer{FindPointerComponent(*nested, visited)}) {
|
||||
return pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool HasPointerComponent(const Scope &scope) {
|
||||
const Symbol *FindPointerComponent(const Scope &scope) {
|
||||
std::set<const Scope *> visited;
|
||||
return HasPointerComponent(scope, visited);
|
||||
return FindPointerComponent(scope, visited);
|
||||
}
|
||||
|
||||
bool HasPointerComponent(const DerivedTypeSpec &derived) {
|
||||
const Symbol *FindPointerComponent(const DerivedTypeSpec &derived) {
|
||||
if (const Scope * scope{derived.scope()}) {
|
||||
return HasPointerComponent(*scope);
|
||||
return FindPointerComponent(*scope);
|
||||
} else {
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool HasPointerComponent(const DeclTypeSpec &type) {
|
||||
const Symbol *FindPointerComponent(const DeclTypeSpec &type) {
|
||||
if (const DerivedTypeSpec * derived{type.AsDerived()}) {
|
||||
return HasPointerComponent(*derived);
|
||||
return FindPointerComponent(*derived);
|
||||
} else {
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool HasPointerComponent(const DeclTypeSpec *type) {
|
||||
return type != nullptr && HasPointerComponent(*type);
|
||||
const Symbol *FindPointerComponent(const DeclTypeSpec *type) {
|
||||
return type ? FindPointerComponent(*type) : nullptr;
|
||||
}
|
||||
|
||||
bool IsOrHasPointerComponent(const Symbol &symbol) {
|
||||
return symbol.attrs().test(Attr::POINTER) ||
|
||||
HasPointerComponent(symbol.GetType());
|
||||
const Symbol *FindPointerComponent(const Symbol &symbol) {
|
||||
return symbol.attrs().test(Attr::POINTER)
|
||||
? &symbol
|
||||
: FindPointerComponent(symbol.GetType());
|
||||
}
|
||||
|
||||
// C1594 specifies several ways by which an object might be globally visible.
|
||||
bool IsExternallyVisibleObject(const Symbol &object, const Scope &scope) {
|
||||
return IsUseAssociated(object, scope) || IsHostAssociated(object, scope) ||
|
||||
const Symbol *FindExternallyVisibleObject(
|
||||
const Symbol &object, const Scope &scope) {
|
||||
// TODO: Storage association with any object for which this predicate holds,
|
||||
// once EQUIVALENCE is supported.
|
||||
if (IsUseAssociated(object, scope) || IsHostAssociated(object, scope) ||
|
||||
(IsPureFunction(scope) && IsPointerDummy(object)) ||
|
||||
(object.attrs().test(Attr::INTENT_IN) && IsDummy(object)) ||
|
||||
FindCommonBlockContaining(object) != nullptr;
|
||||
// TODO: Storage association with any object for which this predicate holds
|
||||
(object.attrs().test(Attr::INTENT_IN) && IsDummy(object))) {
|
||||
return &object;
|
||||
} else if (const Symbol * block{FindCommonBlockContaining(object)}) {
|
||||
return block;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,10 @@ const Symbol *FindCommonBlockContaining(const Symbol &object);
|
||||
const Scope *FindProgramUnitContaining(const Scope &);
|
||||
const Scope *FindProgramUnitContaining(const Symbol &);
|
||||
const Scope *FindPureFunctionContaining(const Scope *);
|
||||
const Symbol *FindPointerComponent(const Scope &);
|
||||
const Symbol *FindPointerComponent(const DerivedTypeSpec &);
|
||||
const Symbol *FindPointerComponent(const DeclTypeSpec &);
|
||||
const Symbol *FindPointerComponent(const Symbol &);
|
||||
|
||||
bool IsCommonBlockContaining(const Symbol &block, const Symbol &object);
|
||||
bool IsAncestor(const Scope *maybeAncestor, const Scope &maybeDescendent);
|
||||
@@ -39,35 +43,35 @@ bool IsPointerDummy(const Symbol &);
|
||||
bool IsFunction(const Symbol &);
|
||||
bool IsPureFunction(const Symbol &);
|
||||
bool IsPureFunction(const Scope &);
|
||||
bool HasPointerComponent(const Scope &);
|
||||
bool HasPointerComponent(const DerivedTypeSpec &);
|
||||
bool HasPointerComponent(const DeclTypeSpec &);
|
||||
bool IsOrHasPointerComponent(const Symbol &);
|
||||
|
||||
// Determines whether an object might be visible outside a
|
||||
// PURE function (C1594)
|
||||
bool IsExternallyVisibleObject(const Symbol &, const Scope &);
|
||||
// PURE function (C1594); returns a non-null Symbol pointer for
|
||||
// diagnostic purposes if so.
|
||||
const Symbol *FindExternallyVisibleObject(const Symbol &, const Scope &);
|
||||
|
||||
template<typename A> bool IsExternallyVisibleObject(const A &, const Scope &) {
|
||||
return false; // default base case
|
||||
template<typename A>
|
||||
const Symbol *FindExternallyVisibleObject(const A &, const Scope &) {
|
||||
return nullptr; // default base case
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool IsExternallyVisibleObject(
|
||||
const Symbol *FindExternallyVisibleObject(
|
||||
const evaluate::Designator<T> &designator, const Scope &scope) {
|
||||
if (const Symbol * symbol{designator.GetBaseObject().symbol()}) {
|
||||
return IsExternallyVisibleObject(*symbol, scope);
|
||||
} else {
|
||||
return FindExternallyVisibleObject(*symbol, scope);
|
||||
} else if (std::holds_alternative<evaluate::CoarrayRef>(designator.u)) {
|
||||
// Coindexed values are visible even if their image-local objects are not.
|
||||
return std::holds_alternative<evaluate::CoarrayRef>(designator.u);
|
||||
return designator.GetBaseObject().symbol();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool IsExternallyVisibleObject(
|
||||
const Symbol *FindExternallyVisibleObject(
|
||||
const evaluate::Expr<T> &expr, const Scope &scope) {
|
||||
return std::visit(
|
||||
[&](const auto &x) { return IsExternallyVisibleObject(x, scope); },
|
||||
[&](const auto &x) { return FindExternallyVisibleObject(x, scope); },
|
||||
expr.u);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,11 +23,11 @@ module module1
|
||||
use usefrom
|
||||
implicit none
|
||||
type :: has_pointer1
|
||||
real, pointer :: p
|
||||
type(has_pointer1), allocatable :: link1
|
||||
real, pointer :: ptop
|
||||
type(has_pointer1), allocatable :: link1 ! don't loop during analysis
|
||||
end type has_pointer1
|
||||
type :: has_pointer2
|
||||
type(has_pointer1) :: p
|
||||
type(has_pointer1) :: pnested
|
||||
type(has_pointer2), allocatable :: link2
|
||||
end type has_pointer2
|
||||
type, extends(has_pointer2) :: has_pointer3
|
||||
@@ -35,7 +35,7 @@ module module1
|
||||
end type has_pointer3
|
||||
type :: t1(k)
|
||||
integer, kind :: k
|
||||
real, pointer :: p
|
||||
real, pointer :: pt1
|
||||
type(t1(k)), allocatable :: link
|
||||
end type t1
|
||||
type :: t2(k)
|
||||
@@ -54,11 +54,9 @@ module module1
|
||||
type(t4(k)), allocatable :: link
|
||||
end type t4
|
||||
real :: modulevar1
|
||||
real :: commonvar1
|
||||
type(has_pointer1) :: modulevar2, commonvar2
|
||||
type(has_pointer2) :: modulevar3, commonvar3
|
||||
type(has_pointer3) :: modulevar4, commonvar4
|
||||
common /cblock/ commonvar1
|
||||
type(has_pointer1) :: modulevar2
|
||||
type(has_pointer2) :: modulevar3
|
||||
type(has_pointer3) :: modulevar4
|
||||
|
||||
contains
|
||||
|
||||
@@ -72,35 +70,31 @@ module module1
|
||||
real, intent(inout) :: dummy2
|
||||
real, pointer :: dummy3
|
||||
real, intent(inout) :: dummy4[*]
|
||||
real :: commonvar1
|
||||
common /cblock/ commonvar1
|
||||
pf1 = 0.
|
||||
x1 = t1(0)(local1)
|
||||
!ERROR: Externally visible object must not be associated with a pointer in a PURE function
|
||||
!ERROR: Externally visible object 'usedfrom1' must not be associated with pointer component 'pt1' in a PURE function
|
||||
x1 = t1(0)(usedfrom1)
|
||||
!ERROR: Externally visible object must not be associated with a pointer in a PURE function
|
||||
!ERROR: Externally visible object 'modulevar1' must not be associated with pointer component 'pt1' in a PURE function
|
||||
x1 = t1(0)(modulevar1)
|
||||
!ERROR: Externally visible object must not be associated with a pointer in a PURE function
|
||||
!ERROR: Externally visible object 'cblock' must not be associated with pointer component 'pt1' in a PURE function
|
||||
x1 = t1(0)(commonvar1)
|
||||
!ERROR: Externally visible object must not be associated with a pointer in a PURE function
|
||||
!ERROR: Externally visible object 'dummy1' must not be associated with pointer component 'pt1' in a PURE function
|
||||
x1 = t1(0)(dummy1)
|
||||
x1 = t1(0)(dummy2)
|
||||
!ERROR: Externally visible object must not be associated with a pointer in a PURE function
|
||||
!ERROR: Externally visible object 'dummy3' must not be associated with pointer component 'pt1' in a PURE function
|
||||
x1 = t1(0)(dummy3)
|
||||
! TODO when semantics handles coindexing:
|
||||
! TODO !ERROR: Externally visible object must not be associated with a pointer in a PURE function
|
||||
! TODO x1 = t1(0)(dummy4[0])
|
||||
x1 = t1(0)(dummy4)
|
||||
!ERROR: Externally visible object must not be associated with a pointer in a PURE function
|
||||
!ERROR: Externally visible object 'modulevar2' must not be associated with pointer component 'ptop' in a PURE function
|
||||
x2 = t2(0)(modulevar2)
|
||||
!ERROR: Externally visible object must not be associated with a pointer in a PURE function
|
||||
x2 = t2(0)(commonvar2)
|
||||
!ERROR: Externally visible object must not be associated with a pointer in a PURE function
|
||||
!ERROR: Externally visible object 'modulevar3' must not be associated with pointer component 'ptop' in a PURE function
|
||||
x3 = t3(0)(modulevar3)
|
||||
!ERROR: Externally visible object must not be associated with a pointer in a PURE function
|
||||
x3 = t3(0)(commonvar3)
|
||||
!ERROR: Externally visible object must not be associated with a pointer in a PURE function
|
||||
!ERROR: Externally visible object 'modulevar4' must not be associated with pointer component 'ptop' in a PURE function
|
||||
x4 = t4(0)(modulevar4)
|
||||
!ERROR: Externally visible object must not be associated with a pointer in a PURE function
|
||||
x4 = t4(0)(commonvar4)
|
||||
contains
|
||||
subroutine subr(dummy1a, dummy2a, dummy3a, dummy4a)
|
||||
real :: local1a
|
||||
@@ -113,37 +107,31 @@ module module1
|
||||
real, pointer :: dummy3a
|
||||
real, intent(inout) :: dummy4a[*]
|
||||
x1a = t1(0)(local1a)
|
||||
!ERROR: Externally visible object must not be associated with a pointer in a PURE function
|
||||
!ERROR: Externally visible object 'usedfrom1' must not be associated with pointer component 'pt1' in a PURE function
|
||||
x1a = t1(0)(usedfrom1)
|
||||
!ERROR: Externally visible object must not be associated with a pointer in a PURE function
|
||||
!ERROR: Externally visible object 'modulevar1' must not be associated with pointer component 'pt1' in a PURE function
|
||||
x1a = t1(0)(modulevar1)
|
||||
!ERROR: Externally visible object must not be associated with a pointer in a PURE function
|
||||
!ERROR: Externally visible object 'cblock' must not be associated with pointer component 'pt1' in a PURE function
|
||||
x1a = t1(0)(commonvar1)
|
||||
!ERROR: Externally visible object must not be associated with a pointer in a PURE function
|
||||
!ERROR: Externally visible object 'dummy1' must not be associated with pointer component 'pt1' in a PURE function
|
||||
x1a = t1(0)(dummy1)
|
||||
!ERROR: Externally visible object must not be associated with a pointer in a PURE function
|
||||
!ERROR: Externally visible object 'dummy1a' must not be associated with pointer component 'pt1' in a PURE function
|
||||
x1a = t1(0)(dummy1a)
|
||||
x1a = t1(0)(dummy2a)
|
||||
!ERROR: Externally visible object must not be associated with a pointer in a PURE function
|
||||
!ERROR: Externally visible object 'dummy3' must not be associated with pointer component 'pt1' in a PURE function
|
||||
x1a = t1(0)(dummy3)
|
||||
!ERROR: Externally visible object must not be associated with a pointer in a PURE function
|
||||
!ERROR: Externally visible object 'dummy3a' must not be associated with pointer component 'pt1' in a PURE function
|
||||
x1a = t1(0)(dummy3a)
|
||||
! TODO when semantics handles coindexing:
|
||||
! TODO !ERROR: Externally visible object must not be associated with a pointer in a PURE function
|
||||
! TODO x1a = t1(0)(dummy4a[0])
|
||||
x1a = t1(0)(dummy4a)
|
||||
!ERROR: Externally visible object must not be associated with a pointer in a PURE function
|
||||
!ERROR: Externally visible object 'modulevar2' must not be associated with pointer component 'ptop' in a PURE function
|
||||
x2a = t2(0)(modulevar2)
|
||||
!ERROR: Externally visible object must not be associated with a pointer in a PURE function
|
||||
x2a = t2(0)(commonvar2)
|
||||
!ERROR: Externally visible object must not be associated with a pointer in a PURE function
|
||||
!ERROR: Externally visible object 'modulevar3' must not be associated with pointer component 'ptop' in a PURE function
|
||||
x3a = t3(0)(modulevar3)
|
||||
!ERROR: Externally visible object must not be associated with a pointer in a PURE function
|
||||
x3a = t3(0)(commonvar3)
|
||||
!ERROR: Externally visible object must not be associated with a pointer in a PURE function
|
||||
!ERROR: Externally visible object 'modulevar4' must not be associated with pointer component 'ptop' in a PURE function
|
||||
x4a = t4(0)(modulevar4)
|
||||
!ERROR: Externally visible object must not be associated with a pointer in a PURE function
|
||||
x4a = t4(0)(commonvar4)
|
||||
end subroutine subr
|
||||
end function pf1
|
||||
|
||||
@@ -157,6 +145,8 @@ module module1
|
||||
real, intent(inout) :: dummy2
|
||||
real, pointer :: dummy3
|
||||
real, intent(inout) :: dummy4[*]
|
||||
real :: commonvar1
|
||||
common /cblock/ commonvar1
|
||||
ipf1 = 0.
|
||||
x1 = t1(0)(local1)
|
||||
x1 = t1(0)(usedfrom1)
|
||||
@@ -169,10 +159,7 @@ module module1
|
||||
! TODO x1 = t1(0)(dummy4[0])
|
||||
x1 = t1(0)(dummy4)
|
||||
x2 = t2(0)(modulevar2)
|
||||
x2 = t2(0)(commonvar2)
|
||||
x3 = t3(0)(modulevar3)
|
||||
x3 = t3(0)(commonvar3)
|
||||
x4 = t4(0)(modulevar4)
|
||||
x4 = t4(0)(commonvar4)
|
||||
end function ipf1
|
||||
end module module1
|
||||
|
||||
Reference in New Issue
Block a user