Skip to content

Commit 1c579a5

Browse files
committed
rebased
Created using spr 1.3.6-beta.1
2 parents b0bacf7 + ab0f76e commit 1c579a5

File tree

63 files changed

+663
-239
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+663
-239
lines changed

clang/include/clang/Basic/DiagnosticIDs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ namespace clang {
3737
DIAG_SIZE_DRIVER = 400,
3838
DIAG_SIZE_FRONTEND = 200,
3939
DIAG_SIZE_SERIALIZATION = 120,
40-
DIAG_SIZE_LEX = 400,
40+
DIAG_SIZE_LEX = 500,
4141
DIAG_SIZE_PARSE = 700,
4242
DIAG_SIZE_AST = 300,
4343
DIAG_SIZE_COMMENT = 100,

clang/lib/CodeGen/CGOpenMPRuntime.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1847,7 +1847,6 @@ void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
18471847
auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc,
18481848
this](CodeGenFunction &CGF, PrePostActionTy &) {
18491849
// Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
1850-
CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
18511850
llvm::Value *Args[] = {
18521851
RTLoc,
18531852
CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars

flang/include/flang/Evaluate/characteristics.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,8 +349,8 @@ struct FunctionResult {
349349

350350
// 15.3.1
351351
struct Procedure {
352-
ENUM_CLASS(
353-
Attr, Pure, Elemental, BindC, ImplicitInterface, NullPointer, Subroutine)
352+
ENUM_CLASS(Attr, Pure, Elemental, BindC, ImplicitInterface, NullPointer,
353+
NullAllocatable, Subroutine)
354354
using Attrs = common::EnumSet<Attr, Attr_enumSize>;
355355
Procedure(){};
356356
Procedure(FunctionResult &&, DummyArguments &&, Attrs);

flang/include/flang/Evaluate/tools.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,9 +1059,11 @@ bool IsProcedurePointer(const Expr<SomeType> &);
10591059
bool IsProcedure(const Expr<SomeType> &);
10601060
bool IsProcedurePointerTarget(const Expr<SomeType> &);
10611061
bool IsBareNullPointer(const Expr<SomeType> *); // NULL() w/o MOLD= or type
1062-
bool IsNullObjectPointer(const Expr<SomeType> &);
1063-
bool IsNullProcedurePointer(const Expr<SomeType> &);
1064-
bool IsNullPointer(const Expr<SomeType> &);
1062+
bool IsNullObjectPointer(const Expr<SomeType> *); // NULL() or NULL(objptr)
1063+
bool IsNullProcedurePointer(const Expr<SomeType> *); // NULL() or NULL(procptr)
1064+
bool IsNullPointer(const Expr<SomeType> *); // NULL() or NULL(pointer)
1065+
bool IsNullAllocatable(const Expr<SomeType> *); // NULL(allocatable)
1066+
bool IsNullPointerOrAllocatable(const Expr<SomeType> *); // NULL of any form
10651067
bool IsObjectPointer(const Expr<SomeType> &);
10661068

10671069
// Can Expr be passed as absent to an optional dummy argument.

flang/lib/Evaluate/check-expression.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,9 @@ template <bool INVARIANT>
100100
bool IsConstantExprHelper<INVARIANT>::IsConstantStructureConstructorComponent(
101101
const Symbol &component, const Expr<SomeType> &expr) const {
102102
if (IsAllocatable(component)) {
103-
return IsNullObjectPointer(expr);
103+
return IsNullObjectPointer(&expr);
104104
} else if (IsPointer(component)) {
105-
return IsNullPointer(expr) || IsInitialDataTarget(expr) ||
105+
return IsNullPointerOrAllocatable(&expr) || IsInitialDataTarget(expr) ||
106106
IsInitialProcedureTarget(expr);
107107
} else {
108108
return (*this)(expr);
@@ -194,7 +194,7 @@ struct IsActuallyConstantHelper {
194194
const bool compIsConstant{(*this)(y)};
195195
// If an allocatable component is initialized by a constant,
196196
// the structure constructor is not a constant.
197-
if ((!compIsConstant && !IsNullPointer(y)) ||
197+
if ((!compIsConstant && !IsNullPointerOrAllocatable(&y)) ||
198198
(compIsConstant && IsAllocatable(sym))) {
199199
return false;
200200
}
@@ -311,7 +311,9 @@ class IsInitialDataTargetHelper
311311
bool operator()(const ProcedureRef &x) const {
312312
if (const SpecificIntrinsic * intrinsic{x.proc().GetSpecificIntrinsic()}) {
313313
return intrinsic->characteristics.value().attrs.test(
314-
characteristics::Procedure::Attr::NullPointer);
314+
characteristics::Procedure::Attr::NullPointer) ||
315+
intrinsic->characteristics.value().attrs.test(
316+
characteristics::Procedure::Attr::NullAllocatable);
315317
}
316318
return false;
317319
}
@@ -388,7 +390,7 @@ bool IsInitialProcedureTarget(const Expr<SomeType> &expr) {
388390
if (const auto *proc{std::get_if<ProcedureDesignator>(&expr.u)}) {
389391
return IsInitialProcedureTarget(*proc);
390392
} else {
391-
return IsNullProcedurePointer(expr);
393+
return IsNullProcedurePointer(&expr);
392394
}
393395
}
394396

flang/lib/Evaluate/fold-logical.cpp

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -652,21 +652,18 @@ Expr<Type<TypeCategory::Logical, KIND>> FoldIntrinsicFunction(
652652
if (name == "all") {
653653
return FoldAllAnyParity(
654654
context, std::move(funcRef), &Scalar<T>::AND, Scalar<T>{true});
655+
} else if (name == "allocated") {
656+
if (IsNullAllocatable(args[0]->UnwrapExpr())) {
657+
return Expr<T>{false};
658+
}
655659
} else if (name == "any") {
656660
return FoldAllAnyParity(
657661
context, std::move(funcRef), &Scalar<T>::OR, Scalar<T>{false});
658662
} else if (name == "associated") {
659-
bool gotConstant{true};
660-
const Expr<SomeType> *firstArgExpr{args[0]->UnwrapExpr()};
661-
if (!firstArgExpr || !IsNullPointer(*firstArgExpr)) {
662-
gotConstant = false;
663-
} else if (args[1]) { // There's a second argument
664-
const Expr<SomeType> *secondArgExpr{args[1]->UnwrapExpr()};
665-
if (!secondArgExpr || !IsNullPointer(*secondArgExpr)) {
666-
gotConstant = false;
667-
}
663+
if (IsNullPointer(args[0]->UnwrapExpr()) ||
664+
(args[1] && IsNullPointer(args[1]->UnwrapExpr()))) {
665+
return Expr<T>{false};
668666
}
669-
return gotConstant ? Expr<T>{false} : Expr<T>{std::move(funcRef)};
670667
} else if (name == "bge" || name == "bgt" || name == "ble" || name == "blt") {
671668
static_assert(std::is_same_v<Scalar<LargestInt>, BOZLiteralConstant>);
672669

flang/lib/Evaluate/fold.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ Expr<SomeDerived> FoldOperation(
7373
for (auto &&[symbol, value] : std::move(structure)) {
7474
auto expr{Fold(context, std::move(value.value()))};
7575
if (IsPointer(symbol)) {
76-
if (IsNullPointer(expr)) {
76+
if (IsNullPointer(&expr)) {
7777
// Handle x%c when x designates a named constant of derived
7878
// type and %c is NULL() in that constant.
7979
expr = Expr<SomeType>{NullPointer{}};
@@ -86,9 +86,10 @@ Expr<SomeDerived> FoldOperation(
8686
// F2023: 10.1.12 (3)(a)
8787
// If comp-spec is not null() for the allocatable component the
8888
// structure constructor is not a constant expression.
89-
isConstant &= IsNullPointer(expr);
89+
isConstant &= IsNullAllocatable(&expr) || IsBareNullPointer(&expr);
9090
} else {
91-
isConstant &= IsActuallyConstant(expr) || IsNullPointer(expr);
91+
isConstant &=
92+
IsActuallyConstant(expr) || IsNullPointerOrAllocatable(&expr);
9293
if (auto valueShape{GetConstantExtents(context, expr)}) {
9394
if (auto componentShape{GetConstantExtents(context, symbol)}) {
9495
if (GetRank(*componentShape) > 0 && GetRank(*valueShape) == 0) {

flang/lib/Evaluate/intrinsics.cpp

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -247,8 +247,10 @@ ENUM_CLASS(Optionality, required,
247247
)
248248

249249
ENUM_CLASS(ArgFlag, none,
250-
canBeNull, // actual argument can be NULL(with or without MOLD=)
251-
canBeMoldNull, // actual argument can be NULL(with MOLD=)
250+
canBeNullPointer, // actual argument can be NULL(with or without
251+
// MOLD=pointer)
252+
canBeMoldNull, // actual argument can be NULL(MOLD=any)
253+
canBeNullAllocatable, // actual argument can be NULL(MOLD=allocatable)
252254
defaultsToSameKind, // for MatchingDefaultKIND
253255
defaultsToSizeKind, // for SizeDefaultKIND
254256
defaultsToDefaultForResult, // for DefaultingKIND
@@ -343,8 +345,10 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
343345
Rank::dimReduced, IntrinsicClass::transformationalFunction},
344346
{"allocated", {{"scalar", AnyData, Rank::scalar}}, DefaultLogical,
345347
Rank::elemental, IntrinsicClass::inquiryFunction},
346-
{"allocated", {{"array", AnyData, Rank::anyOrAssumedRank}}, DefaultLogical,
347-
Rank::elemental, IntrinsicClass::inquiryFunction},
348+
{"allocated",
349+
{{"array", AnyData, Rank::anyOrAssumedRank, Optionality::required,
350+
common::Intent::In, {ArgFlag::canBeNullAllocatable}}},
351+
DefaultLogical, Rank::elemental, IntrinsicClass::inquiryFunction},
348352
{"anint", {{"a", SameReal}, MatchingDefaultKIND}, KINDReal},
349353
{"any", {{"mask", SameLogical, Rank::array}, OptionalDIM}, SameLogical,
350354
Rank::dimReduced, IntrinsicClass::transformationalFunction},
@@ -353,10 +357,10 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
353357
{"asinh", {{"x", SameFloating}}, SameFloating},
354358
{"associated",
355359
{{"pointer", AnyPointer, Rank::anyOrAssumedRank, Optionality::required,
356-
common::Intent::In, {ArgFlag::canBeNull}},
360+
common::Intent::In, {ArgFlag::canBeNullPointer}},
357361
{"target", Addressable, Rank::anyOrAssumedRank,
358362
Optionality::optional, common::Intent::In,
359-
{ArgFlag::canBeNull}}},
363+
{ArgFlag::canBeNullPointer}}},
360364
DefaultLogical, Rank::elemental, IntrinsicClass::inquiryFunction},
361365
{"atan", {{"x", SameFloating}}, SameFloating},
362366
{"atan", {{"y", OperandReal}, {"x", OperandReal}}, OperandReal},
@@ -1892,9 +1896,9 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
18921896
d.keyword);
18931897
return std::nullopt;
18941898
}
1895-
if (!d.flags.test(ArgFlag::canBeNull)) {
1896-
if (const auto *expr{arg->UnwrapExpr()}; expr && IsNullPointer(*expr)) {
1897-
if (!IsBareNullPointer(expr) && IsNullObjectPointer(*expr) &&
1899+
if (!d.flags.test(ArgFlag::canBeNullPointer)) {
1900+
if (const auto *expr{arg->UnwrapExpr()}; IsNullPointer(expr)) {
1901+
if (!IsBareNullPointer(expr) && IsNullObjectPointer(expr) &&
18981902
d.flags.test(ArgFlag::canBeMoldNull)) {
18991903
// ok
19001904
} else {
@@ -1905,6 +1909,14 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
19051909
}
19061910
}
19071911
}
1912+
if (!d.flags.test(ArgFlag::canBeNullAllocatable) &&
1913+
IsNullAllocatable(arg->UnwrapExpr()) &&
1914+
!d.flags.test(ArgFlag::canBeMoldNull)) {
1915+
messages.Say(arg->sourceLocation(),
1916+
"A NULL() allocatable is not allowed for '%s=' intrinsic argument"_err_en_US,
1917+
d.keyword);
1918+
return std::nullopt;
1919+
}
19081920
if (d.flags.test(ArgFlag::notAssumedSize)) {
19091921
if (auto named{ExtractNamedEntity(*arg)}) {
19101922
if (semantics::IsAssumedSizeArray(named->GetLastSymbol())) {
@@ -2862,14 +2874,15 @@ SpecificCall IntrinsicProcTable::Implementation::HandleNull(
28622874
"MOLD= argument to NULL() must not be assumed-rank"_err_en_US);
28632875
}
28642876
bool isProcPtrTarget{
2865-
IsProcedurePointerTarget(*mold) && !IsNullObjectPointer(*mold)};
2877+
IsProcedurePointerTarget(*mold) && !IsNullObjectPointer(mold)};
28662878
if (isProcPtrTarget || IsAllocatableOrPointerObject(*mold)) {
28672879
characteristics::DummyArguments args;
28682880
std::optional<characteristics::FunctionResult> fResult;
2881+
bool isAllocatableMold{false};
28692882
if (isProcPtrTarget) {
28702883
// MOLD= procedure pointer
28712884
std::optional<characteristics::Procedure> procPointer;
2872-
if (IsNullProcedurePointer(*mold)) {
2885+
if (IsNullProcedurePointer(mold)) {
28732886
procPointer =
28742887
characteristics::Procedure::Characterize(*mold, context);
28752888
} else {
@@ -2885,20 +2898,23 @@ SpecificCall IntrinsicProcTable::Implementation::HandleNull(
28852898
fResult.emplace(std::move(*procPointer));
28862899
}
28872900
} else if (auto type{mold->GetType()}) {
2888-
// MOLD= object pointer
2901+
// MOLD= object pointer or allocatable
28892902
characteristics::TypeAndShape typeAndShape{
28902903
*type, GetShape(context, *mold)};
28912904
args.emplace_back(
28922905
"mold"s, characteristics::DummyDataObject{typeAndShape});
28932906
fResult.emplace(std::move(typeAndShape));
2907+
isAllocatableMold = IsAllocatableDesignator(*mold);
28942908
} else {
28952909
context.messages().Say(arguments[0]->sourceLocation(),
28962910
"MOLD= argument to NULL() lacks type"_err_en_US);
28972911
}
28982912
if (fResult) {
28992913
fResult->attrs.set(characteristics::FunctionResult::Attr::Pointer);
29002914
characteristics::Procedure::Attrs attrs;
2901-
attrs.set(characteristics::Procedure::Attr::NullPointer);
2915+
attrs.set(isAllocatableMold
2916+
? characteristics::Procedure::Attr::NullAllocatable
2917+
: characteristics::Procedure::Attr::NullPointer);
29022918
characteristics::Procedure chars{
29032919
std::move(*fResult), std::move(args), attrs};
29042920
return SpecificCall{SpecificIntrinsic{"null"s, std::move(chars)},
@@ -3257,7 +3273,7 @@ static bool ApplySpecificChecks(SpecificCall &call, FoldingContext &context) {
32573273
const auto &arg{call.arguments[0]};
32583274
if (arg) {
32593275
if (const auto *expr{arg->UnwrapExpr()}) {
3260-
ok = evaluate::IsAllocatableDesignator(*expr);
3276+
ok = IsAllocatableDesignator(*expr) || IsNullAllocatable(expr);
32613277
}
32623278
}
32633279
if (!ok) {

flang/lib/Evaluate/shape.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1173,8 +1173,10 @@ auto GetShapeHelper::operator()(const ProcedureRef &call) const -> Result {
11731173
if (call.arguments().size() >= 2) {
11741174
return (*this)(call.arguments()[1]); // MASK=
11751175
}
1176-
} else if (intrinsic->characteristics.value().attrs.test(characteristics::
1177-
Procedure::Attr::NullPointer)) { // NULL(MOLD=)
1176+
} else if (intrinsic->characteristics.value().attrs.test(
1177+
characteristics::Procedure::Attr::NullPointer) ||
1178+
intrinsic->characteristics.value().attrs.test(
1179+
characteristics::Procedure::Attr::NullAllocatable)) { // NULL(MOLD=)
11781180
return (*this)(call.arguments());
11791181
} else {
11801182
// TODO: shapes of other non-elemental intrinsic results

flang/lib/Evaluate/tools.cpp

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -929,7 +929,7 @@ bool IsPointer(const Expr<SomeType> &expr) {
929929
}
930930

931931
bool IsProcedurePointer(const Expr<SomeType> &expr) {
932-
if (IsNullProcedurePointer(expr)) {
932+
if (IsNullProcedurePointer(&expr)) {
933933
return true;
934934
} else if (const auto *funcRef{UnwrapProcedureRef(expr)}) {
935935
if (const Symbol * proc{funcRef->proc().GetSymbol()}) {
@@ -963,7 +963,7 @@ bool IsProcedurePointerTarget(const Expr<SomeType> &expr) {
963963
}
964964

965965
bool IsObjectPointer(const Expr<SomeType> &expr) {
966-
if (IsNullObjectPointer(expr)) {
966+
if (IsNullObjectPointer(&expr)) {
967967
return true;
968968
} else if (IsProcedurePointerTarget(expr)) {
969969
return false;
@@ -1030,22 +1030,46 @@ template <bool IS_PROC_PTR> struct IsNullPointerHelper {
10301030
}
10311031
};
10321032

1033-
bool IsNullObjectPointer(const Expr<SomeType> &expr) {
1034-
return IsNullPointerHelper<false>{}(expr);
1033+
bool IsNullObjectPointer(const Expr<SomeType> *expr) {
1034+
return expr && IsNullPointerHelper<false>{}(*expr);
10351035
}
10361036

1037-
bool IsNullProcedurePointer(const Expr<SomeType> &expr) {
1038-
return IsNullPointerHelper<true>{}(expr);
1037+
bool IsNullProcedurePointer(const Expr<SomeType> *expr) {
1038+
return expr && IsNullPointerHelper<true>{}(*expr);
10391039
}
10401040

1041-
bool IsNullPointer(const Expr<SomeType> &expr) {
1041+
bool IsNullPointer(const Expr<SomeType> *expr) {
10421042
return IsNullObjectPointer(expr) || IsNullProcedurePointer(expr);
10431043
}
10441044

10451045
bool IsBareNullPointer(const Expr<SomeType> *expr) {
10461046
return expr && std::holds_alternative<NullPointer>(expr->u);
10471047
}
10481048

1049+
struct IsNullAllocatableHelper {
1050+
template <typename A> bool operator()(const A &) const { return false; }
1051+
template <typename T> bool operator()(const FunctionRef<T> &call) const {
1052+
const auto *intrinsic{call.proc().GetSpecificIntrinsic()};
1053+
return intrinsic &&
1054+
intrinsic->characteristics.value().attrs.test(
1055+
characteristics::Procedure::Attr::NullAllocatable);
1056+
}
1057+
template <typename T> bool operator()(const Parentheses<T> &x) const {
1058+
return (*this)(x.left());
1059+
}
1060+
template <typename T> bool operator()(const Expr<T> &x) const {
1061+
return common::visit(*this, x.u);
1062+
}
1063+
};
1064+
1065+
bool IsNullAllocatable(const Expr<SomeType> *x) {
1066+
return x && IsNullAllocatableHelper{}(*x);
1067+
}
1068+
1069+
bool IsNullPointerOrAllocatable(const Expr<SomeType> *x) {
1070+
return IsNullPointer(x) || IsNullAllocatable(x);
1071+
}
1072+
10491073
// GetSymbolVector()
10501074
auto GetSymbolVectorHelper::operator()(const Symbol &x) const -> Result {
10511075
if (const auto *details{x.detailsIf<semantics::AssocEntityDetails>()}) {
@@ -1393,7 +1417,7 @@ bool IsAllocatableOrPointerObject(const Expr<SomeType> &expr) {
13931417
const semantics::Symbol *sym{UnwrapWholeSymbolOrComponentDataRef(expr)};
13941418
return (sym &&
13951419
semantics::IsAllocatableOrObjectPointer(&sym->GetUltimate())) ||
1396-
evaluate::IsObjectPointer(expr);
1420+
evaluate::IsObjectPointer(expr) || evaluate::IsNullAllocatable(&expr);
13971421
}
13981422

13991423
bool IsAllocatableDesignator(const Expr<SomeType> &expr) {

0 commit comments

Comments
 (0)