[flang-commits] [flang] 6bd72fa - [flang] Allow extension cases of EQUIVALENCE with optional warnings

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Tue Feb 15 10:21:46 PST 2022


Author: Peter Klausler
Date: 2022-02-15T10:21:38-08:00
New Revision: 6bd72fa661a892ebd3bafa46817f281b091138aa

URL: https://github.com/llvm/llvm-project/commit/6bd72fa661a892ebd3bafa46817f281b091138aa
DIFF: https://github.com/llvm/llvm-project/commit/6bd72fa661a892ebd3bafa46817f281b091138aa.diff

LOG: [flang] Allow extension cases of EQUIVALENCE with optional warnings

EQUIVALENCE storage association of objects whose types are not
both default-kind numeric storage sequences, or not both default-kind
character storage sequences, are not standard conformant.
However, most Fortran compilers admit such usage, with warnings
in strict conformance mode.  This patch allos EQUIVALENCE of objects
that have sequence types that are either identical, both numeric
sequences (of default kind or not), or both character sequences.
Non-sequence types, and sequences types that are not homogeneously
numeric or character, remain errors.

Differential Revision: https://reviews.llvm.org/D119848

Added: 
    

Modified: 
    flang/docs/Extensions.md
    flang/include/flang/Common/Fortran-features.h
    flang/include/flang/Evaluate/tools.h
    flang/lib/Evaluate/tools.cpp
    flang/lib/Parser/Fortran-parsers.cpp
    flang/lib/Parser/basic-parsers.h
    flang/lib/Semantics/resolve-names-utils.cpp
    flang/lib/Semantics/resolve-names-utils.h
    flang/test/Semantics/equivalence01.f90

Removed: 
    


################################################################################
diff  --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md
index 270ec2dfd93c7..4953186c71127 100644
--- a/flang/docs/Extensions.md
+++ b/flang/docs/Extensions.md
@@ -141,7 +141,9 @@ end
   not be known (e.g., `IAND(X'1',X'2')`).
 * BOZ literals can also be used as REAL values in some contexts where the
   type is unambiguous, such as initializations of REAL parameters.
-* EQUIVALENCE of numeric and character sequences (a ubiquitous extension)
+* EQUIVALENCE of numeric and character sequences (a ubiquitous extension),
+  as well as of sequences of non-default kinds of numeric types
+  with each other.
 * Values for whole anonymous parent components in structure constructors
   (e.g., `EXTENDEDTYPE(PARENTTYPE(1,2,3))` rather than `EXTENDEDTYPE(1,2,3)`
    or `EXTENDEDTYPE(PARENTTYPE=PARENTTYPE(1,2,3))`).

diff  --git a/flang/include/flang/Common/Fortran-features.h b/flang/include/flang/Common/Fortran-features.h
index 7e64b2adfdf44..2a09579183542 100644
--- a/flang/include/flang/Common/Fortran-features.h
+++ b/flang/include/flang/Common/Fortran-features.h
@@ -27,7 +27,8 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines,
     OmitFunctionDummies, CrayPointer, Hollerith, ArithmeticIF, Assign,
     AssignedGOTO, Pause, OpenACC, OpenMP, CruftAfterAmpersand, ClassicCComments,
     AdditionalFormats, BigIntLiterals, RealDoControls,
-    EquivalenceNumericWithCharacter, AdditionalIntrinsics, AnonymousParents,
+    EquivalenceNumericWithCharacter, EquivalenceNonDefaultNumeric,
+    EquivalenceSameNonSequence, AdditionalIntrinsics, AnonymousParents,
     OldLabelDoEndStatements, LogicalIntegerAssignment, EmptySourceFile,
     ProgramReturn, ImplicitNoneTypeNever, ImplicitNoneTypeAlways,
     ForwardRefDummyImplicitNone, OpenAccessAppend, BOZAsDefaultInteger,

diff  --git a/flang/include/flang/Evaluate/tools.h b/flang/include/flang/Evaluate/tools.h
index 703cc335275eb..ae6772a871070 100644
--- a/flang/include/flang/Evaluate/tools.h
+++ b/flang/include/flang/Evaluate/tools.h
@@ -1106,6 +1106,11 @@ bool AreTypeParamCompatible(
 const Symbol &GetUsedModule(const UseDetails &);
 const Symbol *FindFunctionResult(const Symbol &);
 
+// Type compatibility predicate: are x and y effectively the same type?
+// Uses DynamicType::IsTkCompatible(), which handles the case of distinct
+// but identical derived types.
+bool AreTkCompatibleTypes(const DeclTypeSpec *x, const DeclTypeSpec *y);
+
 } // namespace Fortran::semantics
 
 #endif // FORTRAN_EVALUATE_TOOLS_H_

diff  --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp
index 65dd5e938d07d..965e5d43c8b20 100644
--- a/flang/lib/Evaluate/tools.cpp
+++ b/flang/lib/Evaluate/tools.cpp
@@ -1518,4 +1518,15 @@ SemanticsContext &Symbol::GetSemanticsContext() const {
   return DEREF(owner_).context();
 }
 
+bool AreTkCompatibleTypes(const DeclTypeSpec *x, const DeclTypeSpec *y) {
+  if (x && y) {
+    if (auto xDt{evaluate::DynamicType::From(*x)}) {
+      if (auto yDt{evaluate::DynamicType::From(*y)}) {
+        return xDt->IsTkCompatibleWith(*yDt);
+      }
+    }
+  }
+  return false;
+}
+
 } // namespace Fortran::semantics

diff  --git a/flang/lib/Parser/Fortran-parsers.cpp b/flang/lib/Parser/Fortran-parsers.cpp
index a7d57954c6f70..4e5555ea1f64d 100644
--- a/flang/lib/Parser/Fortran-parsers.cpp
+++ b/flang/lib/Parser/Fortran-parsers.cpp
@@ -202,9 +202,8 @@ TYPE_CONTEXT_PARSER("intrinsic type spec"_en_US,
             "CHARACTER" >> maybe(Parser<CharSelector>{}))),
         construct<IntrinsicTypeSpec>(construct<IntrinsicTypeSpec::Logical>(
             "LOGICAL" >> maybe(kindSelector))),
-        construct<IntrinsicTypeSpec>("DOUBLE COMPLEX" >>
-            extension<LanguageFeature::DoubleComplex>(
-                construct<IntrinsicTypeSpec::DoubleComplex>())),
+        extension<LanguageFeature::DoubleComplex>(construct<IntrinsicTypeSpec>(
+            "DOUBLE COMPLEX" >> construct<IntrinsicTypeSpec::DoubleComplex>())),
         extension<LanguageFeature::Byte>(
             construct<IntrinsicTypeSpec>(construct<IntegerTypeSpec>(
                 "BYTE" >> construct<std::optional<KindSelector>>(pure(1)))))))

diff  --git a/flang/lib/Parser/basic-parsers.h b/flang/lib/Parser/basic-parsers.h
index 03238b5b4b3fb..720d53c9e6e29 100644
--- a/flang/lib/Parser/basic-parsers.h
+++ b/flang/lib/Parser/basic-parsers.h
@@ -855,8 +855,8 @@ template <LanguageFeature LF, typename PA> class NonstandardParser {
     auto at{state.GetLocation()};
     auto result{parser_.Parse(state)};
     if (result) {
-      state.Nonstandard(
-          CharBlock{at, state.GetLocation()}, LF, "nonstandard usage"_en_US);
+      state.Nonstandard(CharBlock{at, std::max(state.GetLocation(), at + 1)},
+          LF, "nonstandard usage"_en_US);
     }
     return result;
   }

diff  --git a/flang/lib/Semantics/resolve-names-utils.cpp b/flang/lib/Semantics/resolve-names-utils.cpp
index fd3af9b3356ce..da33359e29614 100644
--- a/flang/lib/Semantics/resolve-names-utils.cpp
+++ b/flang/lib/Semantics/resolve-names-utils.cpp
@@ -8,6 +8,7 @@
 
 #include "resolve-names-utils.h"
 #include "flang/Common/Fortran-features.h"
+#include "flang/Common/Fortran.h"
 #include "flang/Common/idioms.h"
 #include "flang/Common/indirection.h"
 #include "flang/Evaluate/fold.h"
@@ -412,45 +413,58 @@ void EquivalenceSets::FinishSet(const parser::CharBlock &source) {
   currSet_.clear();
 }
 
-// Report an error if sym1 and sym2 cannot be in the same equivalence set.
+// Report an error or warning if sym1 and sym2 cannot be in the same equivalence
+// set.
 bool EquivalenceSets::CheckCanEquivalence(
     const parser::CharBlock &source, const Symbol &sym1, const Symbol &sym2) {
   std::optional<parser::MessageFixedText> msg;
   const DeclTypeSpec *type1{sym1.GetType()};
   const DeclTypeSpec *type2{sym2.GetType()};
-  bool isNum1{IsNumericSequenceType(type1)};
-  bool isNum2{IsNumericSequenceType(type2)};
+  bool isDefaultNum1{IsDefaultNumericSequenceType(type1)};
+  bool isAnyNum1{IsAnyNumericSequenceType(type1)};
+  bool isDefaultNum2{IsDefaultNumericSequenceType(type2)};
+  bool isAnyNum2{IsAnyNumericSequenceType(type2)};
   bool isChar1{IsCharacterSequenceType(type1)};
   bool isChar2{IsCharacterSequenceType(type2)};
   if (sym1.attrs().test(Attr::PROTECTED) &&
       !sym2.attrs().test(Attr::PROTECTED)) { // C8114
     msg = "Equivalence set cannot contain '%s'"
           " with PROTECTED attribute and '%s' without"_err_en_US;
-  } else if (isNum1) {
+  } else if ((isDefaultNum1 && isDefaultNum2) || (isChar1 && isChar2)) {
+    // ok & standard conforming
+  } else if (!(isAnyNum1 || isChar1) &&
+      !(isAnyNum2 || isChar2)) { // C8110 - C8113
+    if (AreTkCompatibleTypes(type1, type2)) {
+      if (context_.ShouldWarn(LanguageFeature::EquivalenceSameNonSequence)) {
+        msg = "nonstandard: Equivalence set contains '%s' and '%s' with same "
+              "type "
+              "that is neither numeric nor character sequence type"_en_US;
+      }
+    } else {
+      msg = "Equivalence set cannot contain '%s' and '%s' with distinct types "
+            "that are not both numeric or character sequence types"_err_en_US;
+    }
+  } else if (isAnyNum1) {
     if (isChar2) {
       if (context_.ShouldWarn(
               LanguageFeature::EquivalenceNumericWithCharacter)) {
-        msg = "Equivalence set contains '%s' that is numeric sequence "
+        msg = "nonstandard: Equivalence set contains '%s' that is numeric "
+              "sequence "
               "type and '%s' that is character"_en_US;
       }
-    } else if (!isNum2) { // C8110
-      msg = "Equivalence set cannot contain '%s'"
-            " that is numeric sequence type and '%s' that is not"_err_en_US;
-    }
-  } else if (isChar1) {
-    if (isNum2) {
-      if (context_.ShouldWarn(
-              LanguageFeature::EquivalenceNumericWithCharacter)) {
-        msg = "Equivalence set contains '%s' that is character sequence "
-              "type and '%s' that is numeric"_en_US;
+    } else if (isAnyNum2 &&
+        context_.ShouldWarn(LanguageFeature::EquivalenceNonDefaultNumeric)) {
+      if (isDefaultNum1) {
+        msg =
+            "nonstandard: Equivalence set contains '%s' that is a default "
+            "numeric "
+            "sequence type and '%s' that is numeric with non-default kind"_en_US;
+      } else if (!isDefaultNum2) {
+        msg = "nonstandard: Equivalence set contains '%s' and '%s' that are "
+              "numeric "
+              "sequence types with non-default kinds"_en_US;
       }
-    } else if (!isChar2) { // C8111
-      msg = "Equivalence set cannot contain '%s'"
-            " that is character sequence type and '%s' that is not"_err_en_US;
     }
-  } else if (!isNum2 && !isChar2 && *type1 != *type2) { // C8112, C8113
-    msg = "Equivalence set cannot contain '%s' and '%s' with 
diff erent types"
-          " that are neither numeric nor character sequence types"_err_en_US;
   }
   if (msg) {
     context_.Say(source, std::move(*msg), sym1.name(), sym2.name());
@@ -678,15 +692,14 @@ bool EquivalenceSets::IsCharacterSequenceType(const DeclTypeSpec *type) {
 // Numeric or logical type of default kind or DOUBLE PRECISION or DOUBLE COMPLEX
 bool EquivalenceSets::IsDefaultKindNumericType(const IntrinsicTypeSpec &type) {
   if (auto kind{evaluate::ToInt64(type.kind())}) {
-    auto category{type.category()};
-    auto defaultKind{context_.GetDefaultKind(category)};
-    switch (category) {
+    switch (type.category()) {
     case TypeCategory::Integer:
     case TypeCategory::Logical:
-      return *kind == defaultKind;
+      return *kind == context_.GetDefaultKind(TypeCategory::Integer);
     case TypeCategory::Real:
     case TypeCategory::Complex:
-      return *kind == defaultKind || *kind == context_.doublePrecisionKind();
+      return *kind == context_.GetDefaultKind(TypeCategory::Real) ||
+          *kind == context_.doublePrecisionKind();
     default:
       return false;
     }
@@ -694,12 +707,19 @@ bool EquivalenceSets::IsDefaultKindNumericType(const IntrinsicTypeSpec &type) {
   return false;
 }
 
-bool EquivalenceSets::IsNumericSequenceType(const DeclTypeSpec *type) {
+bool EquivalenceSets::IsDefaultNumericSequenceType(const DeclTypeSpec *type) {
   return IsSequenceType(type, [&](const IntrinsicTypeSpec &type) {
     return IsDefaultKindNumericType(type);
   });
 }
 
+bool EquivalenceSets::IsAnyNumericSequenceType(const DeclTypeSpec *type) {
+  return IsSequenceType(type, [&](const IntrinsicTypeSpec &type) {
+    return type.category() == TypeCategory::Logical ||
+        common::IsNumericTypeCategory(type.category());
+  });
+}
+
 // Is type an intrinsic type that satisfies predicate or a sequence type
 // whose components do.
 bool EquivalenceSets::IsSequenceType(const DeclTypeSpec *type,

diff  --git a/flang/lib/Semantics/resolve-names-utils.h b/flang/lib/Semantics/resolve-names-utils.h
index f77145a841bef..032aa1943cb61 100644
--- a/flang/lib/Semantics/resolve-names-utils.h
+++ b/flang/lib/Semantics/resolve-names-utils.h
@@ -128,8 +128,9 @@ class EquivalenceSets {
   bool CheckSubstringBound(const parser::Expr &, bool);
   bool IsCharacterSequenceType(const DeclTypeSpec *);
   bool IsDefaultKindNumericType(const IntrinsicTypeSpec &);
-  bool IsNumericSequenceType(const DeclTypeSpec *);
-  bool IsSequenceType(
+  bool IsDefaultNumericSequenceType(const DeclTypeSpec *);
+  static bool IsAnyNumericSequenceType(const DeclTypeSpec *);
+  static bool IsSequenceType(
       const DeclTypeSpec *, std::function<bool(const IntrinsicTypeSpec &)>);
 
   SemanticsContext &context_;

diff  --git a/flang/test/Semantics/equivalence01.f90 b/flang/test/Semantics/equivalence01.f90
index d69113ac258e8..66f183c489258 100644
--- a/flang/test/Semantics/equivalence01.f90
+++ b/flang/test/Semantics/equivalence01.f90
@@ -1,8 +1,8 @@
-!RUN: %python %S/test_errors.py %s %flang_fc1
+!RUN: not %flang_fc1 -pedantic %s 2>&1 | FileCheck %s
 subroutine s1
   integer i, j
   real r(2)
-  !ERROR: Equivalence set must have more than one object
+  !CHECK: error: Equivalence set must have more than one object
   equivalence(i, j),(r(1))
 end
 
@@ -13,24 +13,24 @@ subroutine s2
     integer :: b(10)
   end type
   type(t) :: x
-  !ERROR: Derived type component 'x%a' is not allowed in an equivalence set
+  !CHECK: error: Derived type component 'x%a' is not allowed in an equivalence set
   equivalence(x%a, i)
-  !ERROR: Derived type component 'x%b(2)' is not allowed in an equivalence set
+  !CHECK: error: Derived type component 'x%b(2)' is not allowed in an equivalence set
   equivalence(i, x%b(2))
 end
 
 integer function f3(x)
   real x
-  !ERROR: Dummy argument 'x' is not allowed in an equivalence set
+  !CHECK: error: Dummy argument 'x' is not allowed in an equivalence set
   equivalence(i, x)
-  !ERROR: Function result 'f3' is not allow in an equivalence set
+  !CHECK: error: Function result 'f3' is not allow in an equivalence set
   equivalence(f3, i)
 end
 
 subroutine s4
   integer :: y
-  !ERROR: Pointer 'x' is not allowed in an equivalence set
-  !ERROR: Allocatable variable 'y' is not allowed in an equivalence set
+  !CHECK: error: Pointer 'x' is not allowed in an equivalence set
+  !CHECK: error: Allocatable variable 'y' is not allowed in an equivalence set
   equivalence(x, y)
   real, pointer :: x
   allocatable :: y
@@ -40,22 +40,22 @@ subroutine s5
   integer, parameter :: k = 123
   real :: x(10)
   real, save :: y[1:*]
-  !ERROR: Coarray 'y' is not allowed in an equivalence set
+  !CHECK: error: Coarray 'y' is not allowed in an equivalence set
   equivalence(x, y)
-  !ERROR: Variable 'z' with BIND attribute is not allowed in an equivalence set
+  !CHECK: error: Variable 'z' with BIND attribute is not allowed in an equivalence set
   equivalence(x, z)
-  !ERROR: Variable 'z' with BIND attribute is not allowed in an equivalence set
+  !CHECK: error: Variable 'z' with BIND attribute is not allowed in an equivalence set
   equivalence(x(2), z(3))
   real, bind(C) :: z(10)
-  !ERROR: Named constant 'k' is not allowed in an equivalence set
+  !CHECK: error: Named constant 'k' is not allowed in an equivalence set
   equivalence(x(2), k)
-  !ERROR: Variable 'w' in common block with BIND attribute is not allowed in an equivalence set
+  !CHECK: error: Variable 'w' in common block with BIND attribute is not allowed in an equivalence set
   equivalence(x(10), w)
   logical :: w(10)
   bind(C, name="c") /c/
   common /c/ w
   integer, target :: u
-  !ERROR: Variable 'u' with TARGET attribute is not allowed in an equivalence set
+  !CHECK: error: Variable 'u' with TARGET attribute is not allowed in an equivalence set
   equivalence(x(1), u)
 end
 
@@ -71,9 +71,9 @@ subroutine s6
   real :: x0
   type(t1) :: x1
   type(t2) :: x2
-  !ERROR: Derived type object 'x1' with pointer ultimate component is not allowed in an equivalence set
+  !CHECK: error: Derived type object 'x1' with pointer ultimate component is not allowed in an equivalence set
   equivalence(x0, x1)
-  !ERROR: Derived type object 'x2' with pointer ultimate component is not allowed in an equivalence set
+  !CHECK: error: Derived type object 'x2' with pointer ultimate component is not allowed in an equivalence set
   equivalence(x0, x2)
 end
 
@@ -82,7 +82,7 @@ subroutine s7
   end type
   real :: x0
   type(t1) :: x1
-  !ERROR: Nonsequence derived type object 'x1' is not allowed in an equivalence set
+  !CHECK: error: Nonsequence derived type object 'x1' is not allowed in an equivalence set
   equivalence(x0, x1)
 end
 
@@ -92,9 +92,9 @@ module m8
 end
 subroutine s8
   use m8
-  !ERROR: Use-associated variable 'x' is not allowed in an equivalence set
+  !CHECK: error: Use-associated variable 'x' is not allowed in an equivalence set
   equivalence(x, z)
-  !ERROR: Use-associated variable 'y' is not allowed in an equivalence set
+  !CHECK: error: Use-associated variable 'y' is not allowed in an equivalence set
   equivalence(y(1), z)
 end
 
@@ -103,17 +103,17 @@ subroutine s9
   real :: d(10)
   integer, parameter :: n = 2
   integer :: i, j
-  !ERROR: Substring with nonconstant bound 'n+j' is not allowed in an equivalence set
+  !CHECK: error: Substring with nonconstant bound 'n+j' is not allowed in an equivalence set
   equivalence(c(n+1:n+j), i)
-  !ERROR: Substring with zero length is not allowed in an equivalence set
+  !CHECK: error: Substring with zero length is not allowed in an equivalence set
   equivalence(c(n:1), i)
-  !ERROR: Array with nonconstant subscript 'j-1' is not allowed in an equivalence set
+  !CHECK: error: Array with nonconstant subscript 'j-1' is not allowed in an equivalence set
   equivalence(d(j-1), i)
-  !ERROR: Array section 'd(1:n)' is not allowed in an equivalence set
+  !CHECK: error: Array section 'd(1:n)' is not allowed in an equivalence set
   equivalence(d(1:n), i)
   character(4) :: a(10)
   equivalence(c, a(10)(1:2))
-  !ERROR: 'a(10_8)(2_8:2_8)' and 'a(10_8)(1_8:1_8)' cannot have the same first storage unit
+  !CHECK: error: 'a(10_8)(2_8:2_8)' and 'a(10_8)(1_8:1_8)' cannot have the same first storage unit
   equivalence(c, a(10)(2:3))
 end
 
@@ -121,23 +121,23 @@ subroutine s10
   integer, parameter :: i(4) = [1, 2, 3, 4]
   real :: x(10)
   real :: y(4)
-  !ERROR: Array with vector subscript 'i' is not allowed in an equivalence set
+  !CHECK: error: Array with vector subscript 'i' is not allowed in an equivalence set
   equivalence(x(i), y)
 end
 
 subroutine s11(n)
   integer :: n
   real :: x(n), y
-  !ERROR: Automatic object 'x' is not allowed in an equivalence set
+  !CHECK: error: Automatic object 'x' is not allowed in an equivalence set
   equivalence(x(1), y)
 end
 
 module s12
   real, protected :: a
   integer :: b
-  !ERROR: Equivalence set cannot contain 'a' with PROTECTED attribute and 'b' without
+  !CHECK: error: Equivalence set cannot contain 'a' with PROTECTED attribute and 'b' without
   equivalence(a, b)
-  !ERROR: Equivalence set cannot contain 'a' with PROTECTED attribute and 'b' without
+  !CHECK: error: Equivalence set cannot contain 'a' with PROTECTED attribute and 'b' without
   equivalence(b, a)
 end
 
@@ -153,25 +153,41 @@ module s13
     type(t1) :: w
   end type
   type(t2) :: c
-  !ERROR: Equivalence set cannot contain 'b' that is character sequence type and 'a' that is not
+  !CHECK: nonstandard: Equivalence set contains 'a' that is numeric sequence type and 'b' that is character
   equivalence(a, b)
-  !ERROR: Equivalence set cannot contain 'c' that is numeric sequence type and 'a' that is not
+  !CHECK: nonstandard: Equivalence set contains 'c' that is a default numeric sequence type and 'a' that is numeric with non-default kind
   equivalence(c, a)
   double precision :: d
   double complex :: e
   !OK: d and e are considered to be a default kind numeric type
   equivalence(c, d, e)
+  type :: t3
+    sequence
+    real :: x
+    character :: ch
+  end type t3
+  type(t3) :: s, r
+  type :: t4
+    sequence
+    character :: ch
+    real :: x
+  end type t4
+  type(t4) :: t
+  !CHECK: nonstandard: Equivalence set contains 's' and 'r' with same type that is neither numeric nor character sequence type
+  equivalence(s, r)
+  !CHECK: error: Equivalence set cannot contain 's' and 't' with distinct types that are not both numeric or character sequence types
+  equivalence(s, t)
 end
 
 module s14
   real :: a(10), b, c, d
-  !ERROR: 'a(2_8)' and 'a(1_8)' cannot have the same first storage unit
+  !CHECK: error: 'a(2_8)' and 'a(1_8)' cannot have the same first storage unit
   equivalence(a(1), a(2))
   equivalence(b, a(3))
-  !ERROR: 'a(4_8)' and 'a(3_8)' cannot have the same first storage unit
+  !CHECK: error: 'a(4_8)' and 'a(3_8)' cannot have the same first storage unit
   equivalence(a(4), b)
   equivalence(c, a(5))
-  !ERROR: 'a(6_8)' and 'a(5_8)' cannot have the same first storage unit
+  !CHECK: error: 'a(6_8)' and 'a(5_8)' cannot have the same first storage unit
   equivalence(a(6), d)
   equivalence(c, d)
 end
@@ -179,7 +195,7 @@ module s14
 module s15
   real :: a(2), b(2)
   equivalence(a(2),b(1))
-  !ERROR: 'a(3_8)' and 'a(1_8)' cannot have the same first storage unit
+  !CHECK: error: 'a(3_8)' and 'a(1_8)' cannot have the same first storage unit
   equivalence(b(2),a(1))
 end module
 
@@ -204,13 +220,13 @@ module m17
   real function f17a()
     implicit none
     real :: y
-    !ERROR: No explicit type declared for 'dupname'
-    equivalence (dupName, y) 
+    !CHECK: error: No explicit type declared for 'dupname'
+    equivalence (dupName, y)
   end function f17a
   real function f17b()
     real :: y
-    ! The following implicitly declares an object called "dupName" local to 
+    ! The following implicitly declares an object called "dupName" local to
     ! the function f17b().  OK since there's no "implicit none
-    equivalence (dupName, y) 
+    equivalence (dupName, y)
   end function f17b
 end module m17


        


More information about the flang-commits mailing list