diff options
Diffstat (limited to 'flang/lib/Semantics/check-allocate.cpp')
| -rw-r--r-- | flang/lib/Semantics/check-allocate.cpp | 33 | 
1 files changed, 32 insertions, 1 deletions
diff --git a/flang/lib/Semantics/check-allocate.cpp b/flang/lib/Semantics/check-allocate.cpp index e019bbd..a411e20 100644 --- a/flang/lib/Semantics/check-allocate.cpp +++ b/flang/lib/Semantics/check-allocate.cpp @@ -26,6 +26,10 @@ struct AllocateCheckerInfo {    std::optional<evaluate::DynamicType> sourceExprType;    std::optional<parser::CharBlock> sourceExprLoc;    std::optional<parser::CharBlock> typeSpecLoc; +  std::optional<parser::CharBlock> statSource; +  std::optional<parser::CharBlock> msgSource; +  const SomeExpr *statVar{nullptr}; +  const SomeExpr *msgVar{nullptr};    int sourceExprRank{0}; // only valid if gotMold || gotSource    bool gotStat{false};    bool gotMsg{false}; @@ -141,12 +145,15 @@ static std::optional<AllocateCheckerInfo> CheckAllocateOptions(              [&](const parser::StatOrErrmsg &statOrErr) {                common::visit(                    common::visitors{ -                      [&](const parser::StatVariable &) { +                      [&](const parser::StatVariable &var) {                          if (info.gotStat) { // C943                            context.Say(                                "STAT may not be duplicated in a ALLOCATE statement"_err_en_US);                          }                          info.gotStat = true; +                        info.statVar = GetExpr(context, var); +                        info.statSource = +                            parser::Unwrap<parser::Variable>(var)->GetSource();                        },                        [&](const parser::MsgVariable &var) {                          WarnOnDeferredLengthCharacterScalar(context, @@ -159,6 +166,9 @@ static std::optional<AllocateCheckerInfo> CheckAllocateOptions(                                "ERRMSG may not be duplicated in a ALLOCATE statement"_err_en_US);                          }                          info.gotMsg = true; +                        info.msgVar = GetExpr(context, var); +                        info.msgSource = +                            parser::Unwrap<parser::Variable>(var)->GetSource();                        },                    },                    statOrErr.u); @@ -460,6 +470,16 @@ static bool HaveCompatibleLengths(    }  } +bool AreSameAllocation(const SomeExpr *root, const SomeExpr *path) { +  if (root && path) { +    // For now we just use equality of expressions. If we implement a more +    // sophisticated alias analysis we should use it here. +    return *root == *path; +  } else { +    return false; +  } +} +  bool AllocationCheckerHelper::RunChecks(SemanticsContext &context) {    if (!ultimate_) {      CHECK(context.AnyFatalError()); @@ -690,6 +710,17 @@ bool AllocationCheckerHelper::RunChecks(SemanticsContext &context) {            "Object in ALLOCATE must have DEVICE attribute when STREAM option is specified"_err_en_US);      }    } + +  if (const SomeExpr *allocObj{GetExpr(context, allocateObject_)}) { +    if (AreSameAllocation(allocObj, allocateInfo_.statVar)) { +      context.Say(allocateInfo_.statSource.value_or(name_.source), +          "STAT variable in ALLOCATE must not be the variable being allocated"_err_en_US); +    } +    if (AreSameAllocation(allocObj, allocateInfo_.msgVar)) { +      context.Say(allocateInfo_.msgSource.value_or(name_.source), +          "ERRMSG variable in ALLOCATE must not be the variable being allocated"_err_en_US); +    } +  }    return RunCoarrayRelatedChecks(context);  }  | 
