[flang] pass call03

Original-commit: flang-compiler/f18@8c076bd89b
Reviewed-on: https://github.com/flang-compiler/f18/pull/782
Tree-same-pre-rewrite: false
This commit is contained in:
peter klausler 2019-10-10 16:06:05 -07:00
parent d022fc1cca
commit b8d4f79d59
9 changed files with 162 additions and 81 deletions

View File

@ -122,16 +122,18 @@ std::optional<TypeAndShape> TypeAndShape::Characterize(
return std::nullopt;
}
bool TypeAndShape::IsCompatibleWith(
parser::ContextualMessages &messages, const TypeAndShape &that) const {
bool TypeAndShape::IsCompatibleWith(parser::ContextualMessages &messages,
const TypeAndShape &that, const char *thisDesc, const char *thatDesc,
bool isElemental) const {
const auto &len{that.LEN()};
if (!type_.IsTypeCompatibleWith(that.type_)) {
std::stringstream lenstr;
if (len) {
len->AsFortran(lenstr);
}
messages.Say("Target type '%s' is not compatible with '%s'"_err_en_US,
that.type_.AsFortran(lenstr.str()), type_.AsFortran());
messages.Say("%s type '%s' is not compatible with %s type '%s'"_err_en_US,
thatDesc, that.type_.AsFortran(lenstr.str()), thisDesc,
type_.AsFortran());
return false;
}
// When associating with a character scalar, length must not be greater.
@ -146,7 +148,8 @@ bool TypeAndShape::IsCompatibleWith(
}
}
}
return CheckConformance(messages, shape_, that.shape_);
return isElemental ||
CheckConformance(messages, shape_, that.shape_, thisDesc, thatDesc);
}
void TypeAndShape::AcquireShape(const semantics::ObjectEntityDetails &object) {

View File

@ -103,8 +103,9 @@ public:
const Attrs &attrs() const { return attrs_; }
int Rank() const { return GetRank(shape_); }
bool IsCompatibleWith(
parser::ContextualMessages &, const TypeAndShape &) const;
bool IsCompatibleWith(parser::ContextualMessages &, const TypeAndShape &,
const char * = "POINTER", const char * = "TARGET",
bool isElemental = false) const;
std::ostream &Dump(std::ostream &) const;

View File

@ -31,7 +31,7 @@ static void CheckImplicitInterfaceArg(
evaluate::ActualArgument &arg, parser::ContextualMessages &messages) {
if (const auto &kw{arg.keyword}) {
messages.Say(*kw,
"Keyword '%s=' cannot appear in a reference to a procedure with an implicit interface"_err_en_US,
"Keyword '%s=' may not appear in a reference to a procedure with an implicit interface"_err_en_US,
*kw);
}
if (auto type{arg.GetType()}) {
@ -112,8 +112,17 @@ static void InspectType(
static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
const evaluate::Expr<evaluate::SomeType> &actual,
const characteristics::TypeAndShape &actualType,
parser::ContextualMessages &messages, const Scope &scope) {
dummy.type.IsCompatibleWith(messages, actualType);
const characteristics::Procedure &proc, evaluate::FoldingContext &context,
const Scope &scope) {
// Basic type & rank checking
parser::ContextualMessages &messages{context.messages()};
int dummyRank{evaluate::GetRank(dummy.type.shape())};
bool isElemental{dummyRank == 0 &&
proc.attrs.test(characteristics::Procedure::Attr::Elemental)};
dummy.type.IsCompatibleWith(
messages, actualType, "dummy argument", "actual argument", isElemental);
bool actualIsPolymorphic{actualType.type().IsPolymorphic()};
bool dummyIsPolymorphic{dummy.type.type().IsPolymorphic()};
bool actualIsCoindexed{ExtractCoarrayRef(actual).has_value()};
@ -121,6 +130,25 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
characteristics::TypeAndShape::Attr::AssumedSize)};
bool dummyIsAssumedSize{dummy.type.attrs().test(
characteristics::TypeAndShape::Attr::AssumedSize)};
bool dummyIsAsynchronous{
dummy.attrs.test(characteristics::DummyDataObject::Attr::Asynchronous)};
bool dummyIsVolatile{
dummy.attrs.test(characteristics::DummyDataObject::Attr::Volatile)};
bool dummyIsValue{
dummy.attrs.test(characteristics::DummyDataObject::Attr::Value)};
bool actualIsAsynchronous{false};
bool actualIsVolatile{false};
const Symbol *actualFirstSymbol{evaluate::GetFirstSymbol(actual)};
if (actualFirstSymbol != nullptr) {
const Symbol &ultimate{actualFirstSymbol->GetUltimate()};
actualIsAsynchronous =
actualFirstSymbol->attrs().test(Attr::ASYNCHRONOUS) ||
ultimate.attrs().test(Attr::ASYNCHRONOUS);
actualIsVolatile = actualFirstSymbol->attrs().test(Attr::VOLATILE) ||
ultimate.attrs().test(Attr::VOLATILE);
}
if (actualIsPolymorphic && dummyIsPolymorphic &&
actualIsCoindexed) { // 15.5.2.4(2)
messages.Say(
@ -131,6 +159,8 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
messages.Say(
"Assumed-size polymorphic array may not be associated with a monomorphic dummy argument"_err_en_US);
}
// derived type actual argument checks
if (!actualType.type().IsUnlimitedPolymorphic() &&
actualType.type().category() == TypeCategory::Derived) {
const auto &derived{actualType.type().GetDerivedTypeSpec()};
@ -157,8 +187,7 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
}
}
if (actualIsCoindexed && concerns.allocatable &&
dummy.intent != common::Intent::In &&
!dummy.attrs.test(characteristics::DummyDataObject::Attr::Value)) {
dummy.intent != common::Intent::In && !dummyIsValue) {
// 15.5.2.4(6)
if (auto *msg{messages.Say(
"Coindexed actual argument with ALLOCATABLE ultimate component must be associated with a dummy argument with VALUE or INTENT(IN) attributes"_err_en_US)}) {
@ -166,24 +195,32 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
"Declaration of ALLOCATABLE component"_en_US);
}
}
if (concerns.coarray &&
actualIsVolatile != dummyIsVolatile) { // 15.5.2.4(22)
if (auto *msg{messages.Say(
"VOLATILE attributes must match when actual argument has a coarray ultimate component"_err_en_US)}) {
msg->Attach(
concerns.coarray->name(), "Declaration of coarray component"_en_US);
}
}
}
// rank and shape
const auto *actualLastSymbol{evaluate::GetLastSymbol(actual)};
const ObjectEntityDetails *actualLastObject{actualLastSymbol
? actualLastSymbol->detailsIf<ObjectEntityDetails>()
? actualLastSymbol->GetUltimate().detailsIf<ObjectEntityDetails>()
: nullptr};
int actualRank{evaluate::GetRank(actualType.shape())};
int dummyRank{evaluate::GetRank(dummy.type.shape())};
if (dummy.type.attrs().test(
characteristics::TypeAndShape::Attr::AssumedShape)) {
// 15.5.2.4(16)
if (actualRank != dummyRank) {
if (actualRank == 0) {
messages.Say(
"Rank of actual argument (%d) differs from assumed-shape dummy argument (%d)"_err_en_US,
actualRank, dummyRank);
"Scalar actual argument may not be associated with assumed-shape dummy argument"_err_en_US);
}
if (actualIsAssumedSize) {
if (auto *msg{messages.Say(
"Assumed-size array cannot be associated with assumed-shape dummy argument"_err_en_US)}) {
"Assumed-size array may not be associated with assumed-shape dummy argument"_err_en_US)}) {
msg->Attach(actualLastSymbol->name(),
"Declaration of assumed-size array actual argument"_en_US);
}
@ -212,21 +249,22 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
"Element of assumed-shape array may not be associated with a dummy argument array"_err_en_US);
}
}
// definability
const char *reason{nullptr};
if (dummy.intent == common::Intent::Out) {
reason = "INTENT(OUT)";
} else if (dummy.intent == common::Intent::InOut) {
reason = "INTENT(IN OUT)";
} else if (dummy.attrs.test(
characteristics::DummyDataObject::Attr::Asynchronous)) {
} else if (dummyIsAsynchronous) {
reason = "ASYNCHRONOUS";
} else if (dummy.attrs.test(
characteristics::DummyDataObject::Attr::Volatile)) {
} else if (dummyIsVolatile) {
reason = "VOLATILE";
}
if (reason != nullptr) {
bool vectorSubscriptIsOk{isElemental || dummyIsValue}; // 15.5.2.4(21)
std::unique_ptr<parser::Message> why{
WhyNotModifiable(messages.at(), actual, scope)};
WhyNotModifiable(messages.at(), actual, scope, vectorSubscriptIsOk)};
if (why.get() != nullptr) {
if (auto *msg{messages.Say(
"Actual argument associated with %s dummy must be definable"_err_en_US,
@ -235,12 +273,39 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
}
}
}
// TODO pmk more here
// Cases when temporaries might be needed but must not be permitted.
if ((actualIsAsynchronous || actualIsVolatile) &&
(dummyIsAsynchronous || dummyIsVolatile) && !dummyIsValue) {
if (actualIsCoindexed) { // C1538
messages.Say(
"Coindexed ASYNCHRONOUS or VOLATILE actual argument may not be associated with dummy argument with ASYNCHRONOUS or VOLATILE attributes unless VALUE"_err_en_US);
}
if (actualRank > 0 && !IsSimplyContiguous(actual, context.intrinsics())) {
bool dummyIsContiguous{
dummy.attrs.test(characteristics::DummyDataObject::Attr::Contiguous)};
bool dummyIsAssumedRank{dummy.type.attrs().test(
characteristics::TypeAndShape::Attr::AssumedRank)};
bool dummyIsAssumedShape{dummy.type.attrs().test(
characteristics::TypeAndShape::Attr::AssumedShape)};
bool actualIsPointer{actualLastSymbol &&
actualLastSymbol->GetUltimate().attrs().test(Attr::POINTER)};
bool dummyIsPointer{
dummy.attrs.test(characteristics::DummyDataObject::Attr::Pointer)};
if (dummyIsContiguous ||
!(dummyIsAssumedShape || dummyIsAssumedRank ||
(actualIsPointer && dummyIsPointer))) { // C1539 & C1540
messages.Say(
"ASYNCHRONOUS or VOLATILE actual argument that is not simply contiguous may not be associated with a contiguous dummy argument"_err_en_US);
}
}
}
}
static void CheckExplicitInterfaceArg(const evaluate::ActualArgument &arg,
const characteristics::DummyArgument &dummy,
evaluate::FoldingContext &context, const Scope &scope) {
const characteristics::Procedure &proc, evaluate::FoldingContext &context,
const Scope &scope) {
auto &messages{context.messages()};
std::visit(
common::visitors{
@ -249,7 +314,7 @@ static void CheckExplicitInterfaceArg(const evaluate::ActualArgument &arg,
if (auto type{characteristics::TypeAndShape::Characterize(
*expr, context)}) {
CheckExplicitDataArg(
object, *expr, *type, context.messages(), scope);
object, *expr, *type, proc, context, scope);
} else if (object.type.type().IsTypelessIntrinsicArgument() &&
std::holds_alternative<evaluate::BOZLiteralConstant>(
expr->u)) {
@ -341,7 +406,8 @@ static void RearrangeArguments(const characteristics::Procedure &proc,
bool CheckExplicitInterface(const characteristics::Procedure &proc,
ActualArguments &actuals, FoldingContext &context, const Scope &scope) {
if (!RearrangeArguments(proc, actuals, context.messages())) {
parser::ContextualMessages &messages{context.messages()};
if (!RearrangeArguments(proc, actuals, messages)) {
return false;
}
int index{0};
@ -353,12 +419,12 @@ bool CheckExplicitInterface(const characteristics::Procedure &proc,
}
} else if (!dummy.IsOptional()) {
if (dummy.name.empty()) {
context.messages().Say(
messages.Say(
"Dummy argument #%d is not OPTIONAL and is not associated with an "
"actual argument in this procedure reference"_err_en_US,
index);
} else {
context.messages().Say(
messages.Say(
"Dummy argument '%s' (#%d) is not OPTIONAL and is not associated "
"with an actual argument in this procedure reference"_err_en_US,
dummy.name, index);

View File

@ -721,17 +721,19 @@ std::optional<Expr<SubscriptInteger>> ExpressionAnalyzer::AsSubscript(
MaybeExpr &&expr) {
if (expr.has_value()) {
if (expr->Rank() > 1) {
Say("subscript expression has rank %d"_err_en_US, expr->Rank());
Say("Subscript expression has rank %d greater than 1"_err_en_US,
expr->Rank());
}
if (auto *intExpr{std::get_if<Expr<SomeInteger>>(&expr->u)}) {
if (auto *ssIntExpr{std::get_if<Expr<SubscriptInteger>>(&intExpr->u)}) {
return {std::move(*ssIntExpr)};
return std::move(*ssIntExpr);
} else {
return Expr<SubscriptInteger>{
Convert<SubscriptInteger, TypeCategory::Integer>{
std::move(*intExpr)}};
}
return {Expr<SubscriptInteger>{
Convert<SubscriptInteger, TypeCategory::Integer>{
std::move(*intExpr)}}};
} else {
Say("subscript expression is not INTEGER"_err_en_US);
Say("Subscript expression is not INTEGER"_err_en_US);
}
}
return std::nullopt;
@ -741,8 +743,9 @@ std::optional<Expr<SubscriptInteger>> ExpressionAnalyzer::TripletPart(
const std::optional<parser::Subscript> &s) {
if (s.has_value()) {
return AsSubscript(Analyze(*s));
} else {
return std::nullopt;
}
return std::nullopt;
}
std::optional<Subscript> ExpressionAnalyzer::AnalyzeSectionSubscript(
@ -750,9 +753,9 @@ std::optional<Subscript> ExpressionAnalyzer::AnalyzeSectionSubscript(
return std::visit(
common::visitors{
[&](const parser::SubscriptTriplet &t) {
return std::make_optional(Subscript{Triplet{
return std::make_optional<Subscript>(Triplet{
TripletPart(std::get<0>(t.t)), TripletPart(std::get<1>(t.t)),
TripletPart(std::get<2>(t.t))}});
TripletPart(std::get<2>(t.t))});
},
[&](const auto &s) -> std::optional<Subscript> {
if (auto subscriptExpr{AsSubscript(Analyze(s))}) {
@ -768,16 +771,15 @@ std::optional<Subscript> ExpressionAnalyzer::AnalyzeSectionSubscript(
// Empty result means an error occurred
std::vector<Subscript> ExpressionAnalyzer::AnalyzeSectionSubscripts(
const std::list<parser::SectionSubscript> &sss) {
bool error{false};
std::vector<Subscript> subscripts;
for (const auto &s : sss) {
if (auto subscript{AnalyzeSectionSubscript(s)}) {
subscripts.emplace_back(std::move(*subscript));
} else {
error = true;
return {};
}
}
return !error ? subscripts : std::vector<Subscript>{};
return subscripts;
}
MaybeExpr ExpressionAnalyzer::Analyze(const parser::ArrayElement &ae) {

View File

@ -511,11 +511,11 @@ std::optional<parser::MessageFixedText> WhyNotModifiable(
}
}
std::unique_ptr<parser::Message> WhyNotModifiable(
parser::CharBlock at, const SomeExpr &expr, const Scope &scope) {
std::unique_ptr<parser::Message> WhyNotModifiable(parser::CharBlock at,
const SomeExpr &expr, const Scope &scope, bool vectorSubscriptIsOk) {
if (evaluate::IsVariable(expr)) {
if (auto dataRef{evaluate::ExtractDataRef(expr)}) {
if (evaluate::HasVectorSubscript(expr)) {
if (!vectorSubscriptIsOk && evaluate::HasVectorSubscript(expr)) {
return std::make_unique<parser::Message>(
at, "variable has a vector subscript"_en_US);
} else {

View File

@ -115,8 +115,8 @@ bool IsAssumedLengthCharacter(const Symbol &);
bool IsAssumedLengthCharacterFunction(const Symbol &);
std::optional<parser::MessageFixedText> WhyNotModifiable(
const Symbol &, const Scope &);
std::unique_ptr<parser::Message> WhyNotModifiable(
SourceName, const SomeExpr &, const Scope &);
std::unique_ptr<parser::Message> WhyNotModifiable(SourceName, const SomeExpr &,
const Scope &, bool vectorSubscriptIsOk = false);
// Is the symbol modifiable in this scope
bool IsExternalInPureContext(const Symbol &symbol, const Scope &scope);

View File

@ -87,6 +87,12 @@ module m01
subroutine valueassumedsize(x)
real, value :: x(*)
end subroutine
subroutine volatileassumedsize(x)
real, volatile :: x(*)
end subroutine
subroutine volatilecontiguous(x)
real, volatile :: x(*)
end subroutine
subroutine test01(x) ! 15.5.2.4(2)
class(t), intent(in) :: x[*]
@ -176,11 +182,11 @@ module m01
subroutine test10(a) ! 15.5.2.4(16)
real :: scalar, matrix(2,3)
real :: a(*)
!ERROR: Rank of actual argument (0) differs from assumed-shape dummy argument (1)
!ERROR: Scalar actual argument may not be associated with assumed-shape dummy argument
call assumedshape(scalar)
!ERROR: Rank of actual argument (2) differs from assumed-shape dummy argument (1)
!ERROR: Rank of dummy argument is 1, but actual argument has rank 2
call assumedshape(matrix)
!ERROR: Assumed-size array cannot be associated with assumed-shape dummy argument
!ERROR: Assumed-size array may not be associated with assumed-shape dummy argument
call assumedshape(a)
end subroutine
@ -233,9 +239,9 @@ module m01
type(ultimateCoarray), volatile :: b
call coarr(a) ! ok
call volcoarr(b) ! ok
!ERROR: VOLATILE attributes must match when argument has a coarray ultimate component
!ERROR: VOLATILE attributes must match when actual argument has a coarray ultimate component
call coarr(b)
!ERROR: VOLATILE attributes must match when argument has a coarray ultimate component
!ERROR: VOLATILE attributes must match when actual argument has a coarray ultimate component
call volcoarr(a)
end subroutine
@ -249,14 +255,17 @@ module m01
call asynchronousValue(b[1]) ! ok
call asynchronousValue(c[1]) ! ok
call asynchronousValue(d[1]) ! ok
!ERROR: coindexed ASYNCHRONOUS or VOLATILE effective argument must not be associated with dummy argument with ASYNCHRONOUS or VOLATILE attributes unless VALUE
!ERROR: Coindexed ASYNCHRONOUS or VOLATILE actual argument may not be associated with dummy argument with ASYNCHRONOUS or VOLATILE attributes unless VALUE
call asynchronous(b[1])
!ERROR: Coindexed ASYNCHRONOUS or VOLATILE actual argument may not be associated with dummy argument with ASYNCHRONOUS or VOLATILE attributes unless VALUE
call volatile(b[1])
!ERROR: coindexed ASYNCHRONOUS or VOLATILE effective argument must not be associated with dummy argument with ASYNCHRONOUS or VOLATILE attributes unless VALUE
!ERROR: Coindexed ASYNCHRONOUS or VOLATILE actual argument may not be associated with dummy argument with ASYNCHRONOUS or VOLATILE attributes unless VALUE
call asynchronous(c[1])
!ERROR: Coindexed ASYNCHRONOUS or VOLATILE actual argument may not be associated with dummy argument with ASYNCHRONOUS or VOLATILE attributes unless VALUE
call volatile(c[1])
!ERROR: coindexed ASYNCHRONOUS or VOLATILE effective argument must not be associated with dummy argument with ASYNCHRONOUS or VOLATILE attributes unless VALUE
!ERROR: Coindexed ASYNCHRONOUS or VOLATILE actual argument may not be associated with dummy argument with ASYNCHRONOUS or VOLATILE attributes unless VALUE
call asynchronous(d[1])
!ERROR: Coindexed ASYNCHRONOUS or VOLATILE actual argument may not be associated with dummy argument with ASYNCHRONOUS or VOLATILE attributes unless VALUE
call volatile(d[1])
end subroutine
@ -271,18 +280,18 @@ module m01
call valueassumedsize(b(::2)) ! ok
call valueassumedsize(c(::2)) ! ok
call valueassumedsize(d(::2)) ! ok
!ERROR: ASYNCHRONOUS or VOLATILE effective argument that is not simply contiguous cannot be associated with a contiguous dummy argument
call assumedsize(b(::2))
!ERROR: ASYNCHRONOUS or VOLATILE effective argument that is not simply contiguous cannot be associated with a contiguous dummy argument
call contiguous(b(::2))
!ERROR: ASYNCHRONOUS or VOLATILE effective argument that is not simply contiguous cannot be associated with a contiguous dummy argument
call assumedsize(c(::2))
!ERROR: ASYNCHRONOUS or VOLATILE effective argument that is not simply contiguous cannot be associated with a contiguous dummy argument
call contiguous(c(::2))
!ERROR: ASYNCHRONOUS or VOLATILE effective argument that is not simply contiguous cannot be associated with a contiguous dummy argument
call assumedsize(d(::2))
!ERROR: ASYNCHRONOUS or VOLATILE effective argument that is not simply contiguous cannot be associated with a contiguous dummy argument
call contiguous(d(::2))
!ERROR: ASYNCHRONOUS or VOLATILE actual argument that is not simply contiguous may not be associated with a contiguous dummy argument
call volatileassumedsize(b(::2))
!ERROR: ASYNCHRONOUS or VOLATILE actual argument that is not simply contiguous may not be associated with a contiguous dummy argument
call volatilecontiguous(b(::2))
!ERROR: ASYNCHRONOUS or VOLATILE actual argument that is not simply contiguous may not be associated with a contiguous dummy argument
call volatileassumedsize(c(::2))
!ERROR: ASYNCHRONOUS or VOLATILE actual argument that is not simply contiguous may not be associated with a contiguous dummy argument
call volatilecontiguous(c(::2))
!ERROR: ASYNCHRONOUS or VOLATILE actual argument that is not simply contiguous may not be associated with a contiguous dummy argument
call volatileassumedsize(d(::2))
!ERROR: ASYNCHRONOUS or VOLATILE actual argument that is not simply contiguous may not be associated with a contiguous dummy argument
call volatilecontiguous(d(::2))
end subroutine
subroutine test16() ! C1540
@ -300,18 +309,18 @@ module m01
call valueassumedsize(b) ! ok
call valueassumedsize(c) ! ok
call valueassumedsize(d) ! ok
!ERROR: ASYNCHRONOUS or VOLATILE effective argument that is not simply contiguous cannot be associated with a contiguous dummy argument
call assumedsize(b)
!ERROR: ASYNCHRONOUS or VOLATILE effective argument that is not simply contiguous cannot be associated with a contiguous dummy argument
call contiguous(b)
!ERROR: ASYNCHRONOUS or VOLATILE effective argument that is not simply contiguous cannot be associated with a contiguous dummy argument
call assumedsize(c)
!ERROR: ASYNCHRONOUS or VOLATILE effective argument that is not simply contiguous cannot be associated with a contiguous dummy argument
call contiguous(c)
!ERROR: ASYNCHRONOUS or VOLATILE effective argument that is not simply contiguous cannot be associated with a contiguous dummy argument
call assumedsize(d)
!ERROR: ASYNCHRONOUS or VOLATILE effective argument that is not simply contiguous cannot be associated with a contiguous dummy argument
call contiguous(d)
!ERROR: ASYNCHRONOUS or VOLATILE actual argument that is not simply contiguous may not be associated with a contiguous dummy argument
call volatileassumedsize(b)
!ERROR: ASYNCHRONOUS or VOLATILE actual argument that is not simply contiguous may not be associated with a contiguous dummy argument
call volatilecontiguous(b)
!ERROR: ASYNCHRONOUS or VOLATILE actual argument that is not simply contiguous may not be associated with a contiguous dummy argument
call volatileassumedsize(c)
!ERROR: ASYNCHRONOUS or VOLATILE actual argument that is not simply contiguous may not be associated with a contiguous dummy argument
call volatilecontiguous(c)
!ERROR: ASYNCHRONOUS or VOLATILE actual argument that is not simply contiguous may not be associated with a contiguous dummy argument
call volatileassumedsize(d)
!ERROR: ASYNCHRONOUS or VOLATILE actual argument that is not simply contiguous may not be associated with a contiguous dummy argument
call volatilecontiguous(d)
end subroutine
end module

View File

@ -31,7 +31,7 @@ subroutine s(assumedRank, coarray, class, classStar, typeStar)
!ERROR: Invalid specification expression: reference to impure function 'implicit01'
real :: array(implicit01()) ! 15.4.2.2(2)
!ERROR: Keyword 'keyword=' cannot appear in a reference to a procedure with an implicit interface
!ERROR: Keyword 'keyword=' may not appear in a reference to a procedure with an implicit interface
call implicit10(1, 2, keyword=3) ! 15.4.2.2(1)
!ERROR: Assumed rank argument requires an explicit interface
call implicit11(assumedRank) ! 15.4.2.2(3)(c)

View File

@ -74,10 +74,10 @@ subroutine test
dt0x = dt0(ip0=null())
dt0x = dt0(ip0=null(ip0))
dt0x = dt0(ip0=null(mold=ip0))
!ERROR: Target type 'Real(4)' is not compatible with 'Integer(4)'
!ERROR: TARGET type 'Real(4)' is not compatible with POINTER type 'Integer(4)'
!ERROR: Pointer 'ip0' was assigned the result of a reference to function 'null' whose pointer result has an incompatible type or shape
dt0x = dt0(ip0=null(mold=rp0))
!ERROR: Target type 'Real(4)' is not compatible with 'Integer(4)'
!ERROR: TARGET type 'Real(4)' is not compatible with POINTER type 'Integer(4)'
!ERROR: Pointer 'ip1' was assigned the result of a reference to function 'null' whose pointer result has an incompatible type or shape
dt1x = dt1(ip1=null(mold=rp1))
dt2x = dt2(pps0=null())