When an array constructor has an explicit type-spec, all elements must
be converted to that type and character elements must be
padded/truncated to the specified length.  This was working for simple
cases but failing when:

1. Elements were parenthesized: [integer :: ([1.0])]
2. Constructors were nested: [[integer :: [1.0]]]
3. Character constructors were used with concatenation operators:
   [character(16) :: 'a', 'b'] // '|'
4. Nested character constructors with concatenation:
   [character(16) :: ['a', 'b']] // '|'
5. Outer constructor without type-spec wrapping inner with type-spec:
   [[character(16) :: ['a', 'b']]] // '|'
6. Nested character constructors with different type-specs:
   [character(16) :: [character(2) :: 'abcd']]

The root cause was twofold:

First, parenthesized expressions like ([1.0]) create EXPR_OP nodes that
were not being simplified before type conversion in
check_constructor_type(), so type conversion was applied to the EXPR_OP
rather than its contents.

Second, character array constructors with explicit type-spec were not
being resolved before CONCAT operations in eval_intrinsic(), so
elements retained their original lengths instead of being padded to the
type-spec length. Additionally, nested array constructors needed their
type-spec propagated from the outer constructor.

The fix adds:
- Simplification of non-constant expressions in check_constructor_type()
  before attempting type conversion
- Call to gfc_check_constructor_type() in eval_intrinsic() to ensure
  type-spec conversion happens before any operations on array
constructors
- Character array constructor resolution before CONCAT operations
- Recursive type-spec propagation for nested array constructors.
  When a nested array constructor has its own explicit type-spec, it is
  resolved first to enforce its own length (truncation/padding) before
  propagating the outer type-spec and resolving again.
- Detection of nested character constructors with explicit type-spec
  (via length_from_typespec) when the outer constructor has no type-spec

        PR fortran/107721
        PR fortran/102417

gcc/fortran/ChangeLog:

        * arith.cc (eval_intrinsic): Call gfc_check_constructor_type on
        array constructor operands with explicit type-spec to ensure
        element type conversion before operations.  Resolve character
        array constructors before CONCAT operations.
        (reduce_binary_ac, reduce_binary_ca, reduce_binary_aa): Preserve
        character length info in result arrays.
        * array.cc (check_constructor_type): Simplify non-constant
        expressions before type checking to handle parenthesized
          elements. Handle nested character array constructors with
          explicit type-spec when outer constructor has no type-spec.
        (gfc_resolve_character_array_constructor): Recursively propagate
        type-spec to nested array constructors.  If the nested
          constructor has an explicit type-spec, resolve it first
          before propagating the outer type-spec.

gcc/testsuite/ChangeLog:

        * gfortran.dg/array_constructor_typespec_1.f90: New test.
>From 7c91cc5ab8a3529fdd62335d7c0464bdd9bf00ca Mon Sep 17 00:00:00 2001
From: Christopher Albert <[email protected]>
Date: Tue, 25 Nov 2025 00:13:03 +0100
Subject: [PATCH] fortran: Honor array constructor type-spec during folding
 [PR107721]

When an array constructor has an explicit type-spec, all elements must be
converted to that type and character elements must be padded/truncated to
the specified length.  This was working for simple cases but failing when:

1. Elements were parenthesized: [integer :: ([1.0])]
2. Constructors were nested: [[integer :: [1.0]]]
3. Character constructors were used with concatenation operators:
   [character(16) :: 'a', 'b'] // '|'
4. Nested character constructors with concatenation:
   [character(16) :: ['a', 'b']] // '|'
5. Outer constructor without type-spec wrapping inner with type-spec:
   [[character(16) :: ['a', 'b']]] // '|'
6. Nested character constructors with different type-specs:
   [character(16) :: [character(2) :: 'abcd']]

The root cause was twofold:

First, parenthesized expressions like ([1.0]) create EXPR_OP nodes that were
not being simplified before type conversion in check_constructor_type(),
so type conversion was applied to the EXPR_OP rather than its contents.

Second, character array constructors with explicit type-spec were not being
resolved before CONCAT operations in eval_intrinsic(), so elements retained
their original lengths instead of being padded to the type-spec length.
Additionally, nested array constructors needed their type-spec propagated
from the outer constructor.

The fix adds:
- Simplification of non-constant expressions in check_constructor_type()
  before attempting type conversion
- Call to gfc_check_constructor_type() in eval_intrinsic() to ensure
  type-spec conversion happens before any operations on array constructors
- Character array constructor resolution before CONCAT operations
- Recursive type-spec propagation for nested array constructors.
  When a nested array constructor has its own explicit type-spec, it is
  resolved first to enforce its own length (truncation/padding) before
  propagating the outer type-spec and resolving again.
- Detection of nested character constructors with explicit type-spec
  (via length_from_typespec) when the outer constructor has no type-spec

	PR fortran/107721
	PR fortran/102417

gcc/fortran/ChangeLog:

	* arith.cc (eval_intrinsic): Call gfc_check_constructor_type on
	array constructor operands with explicit type-spec to ensure
	element type conversion before operations.  Resolve character
	array constructors before CONCAT operations.
	(reduce_binary_ac, reduce_binary_ca, reduce_binary_aa): Preserve
	character length info in result arrays.
	* array.cc (check_constructor_type): Simplify non-constant
	expressions before type checking to handle parenthesized elements.
	Handle nested character array constructors with explicit type-spec
	when outer constructor has no type-spec.
	(gfc_resolve_character_array_constructor): Recursively propagate
	type-spec to nested array constructors.  If the nested constructor
	has an explicit type-spec, resolve it first before propagating
	the outer type-spec.

gcc/testsuite/ChangeLog:

	* gfortran.dg/array_constructor_typespec_1.f90: New test.

Co-authored-by: Harald Anlauf <[email protected]>
Signed-off-by: Christopher Albert <[email protected]>
---
 gcc/fortran/arith.cc                          |  35 ++
 gcc/fortran/array.cc                          | 100 ++++--
 .../array_constructor_typespec_1.f90          | 324 ++++++++++++++++++
 3 files changed, 438 insertions(+), 21 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/array_constructor_typespec_1.f90

diff --git a/gcc/fortran/arith.cc b/gcc/fortran/arith.cc
index 82a8b6fb995..142f1b09284 100644
--- a/gcc/fortran/arith.cc
+++ b/gcc/fortran/arith.cc
@@ -1565,6 +1565,8 @@ reduce_binary_ac (arith (*eval) (gfc_expr *, gfc_expr *, gfc_expr **),
 	  r = gfc_get_array_expr (c->expr->ts.type, c->expr->ts.kind,
 				  &op1->where);
 	  r->shape = gfc_copy_shape (op1->shape, op1->rank);
+	  if (c->expr->ts.type == BT_CHARACTER)
+	    r->ts.u.cl = c->expr->ts.u.cl;
 	}
       else
 	{
@@ -1572,6 +1574,8 @@ reduce_binary_ac (arith (*eval) (gfc_expr *, gfc_expr *, gfc_expr **),
 	  r = gfc_get_array_expr (op1->ts.type, op1->ts.kind,
 				  &op1->where);
 	  r->shape = gfc_get_shape (op1->rank);
+	  if (op1->ts.type == BT_CHARACTER)
+	    r->ts.u.cl = op1->ts.u.cl;
 	}
       r->rank = op1->rank;
       r->corank = op1->corank;
@@ -1629,6 +1633,8 @@ reduce_binary_ca (arith (*eval) (gfc_expr *, gfc_expr *, gfc_expr **),
 	  r = gfc_get_array_expr (c->expr->ts.type, c->expr->ts.kind,
 				  &op2->where);
 	  r->shape = gfc_copy_shape (op2->shape, op2->rank);
+	  if (c->expr->ts.type == BT_CHARACTER)
+	    r->ts.u.cl = c->expr->ts.u.cl;
 	}
       else
 	{
@@ -1636,6 +1642,8 @@ reduce_binary_ca (arith (*eval) (gfc_expr *, gfc_expr *, gfc_expr **),
 	  r = gfc_get_array_expr (op2->ts.type, op2->ts.kind,
 				  &op2->where);
 	  r->shape = gfc_get_shape (op2->rank);
+	  if (op2->ts.type == BT_CHARACTER)
+	    r->ts.u.cl = op2->ts.u.cl;
 	}
       r->rank = op2->rank;
       r->corank = op2->corank;
@@ -1697,11 +1705,15 @@ reduce_binary_aa (arith (*eval) (gfc_expr *, gfc_expr *, gfc_expr **),
 	{
 	  /* Handle zero-sized arrays.  */
 	  r = gfc_get_array_expr (op1->ts.type, op1->ts.kind, &op1->where);
+	  if (op1->ts.type == BT_CHARACTER)
+	    r->ts.u.cl = op1->ts.u.cl;
 	}
       else
 	{
 	  r = gfc_get_array_expr (c->expr->ts.type, c->expr->ts.kind,
 				  &op1->where);
+	  if (c->expr->ts.type == BT_CHARACTER)
+	    r->ts.u.cl = c->expr->ts.u.cl;
 	}
       r->shape = gfc_copy_shape (op1->shape, op1->rank);
       r->rank = op1->rank;
@@ -1921,6 +1933,29 @@ eval_intrinsic (gfc_intrinsic_op op,
 	     || !gfc_is_constant_expr (op2) || !gfc_expanded_ac (op2)))
     goto runtime;
 
+  /* For array constructors with explicit type-spec, ensure elements are
+     converted to the specified type before any operations.  This handles
+     cases like [integer :: ([1.0])] ** 2 where parentheses would otherwise
+     cause the type-spec to be lost during constant folding.  */
+  if (op1->expr_type == EXPR_ARRAY && op1->ts.type != BT_UNKNOWN)
+    gfc_check_constructor_type (op1);
+  if (op2 != NULL && op2->expr_type == EXPR_ARRAY && op2->ts.type != BT_UNKNOWN)
+    gfc_check_constructor_type (op2);
+
+  /* For CONCAT operations, also resolve character array constructors to
+     ensure elements are padded to the specified length before concatenation.
+     This ensures [character(16):: 'a','b'] // '|' pads to 16 chars first.  */
+  if (op == INTRINSIC_CONCAT)
+    {
+      if (op1->expr_type == EXPR_ARRAY && op1->ts.type == BT_CHARACTER
+	  && op1->ts.u.cl && op1->ts.u.cl->length_from_typespec)
+	gfc_resolve_character_array_constructor (op1);
+      if (op2 != NULL && op2->expr_type == EXPR_ARRAY
+	  && op2->ts.type == BT_CHARACTER
+	  && op2->ts.u.cl && op2->ts.u.cl->length_from_typespec)
+	gfc_resolve_character_array_constructor (op2);
+    }
+
   if (unary)
     rc = reduce_unary (eval.f2, op1, &result);
   else
diff --git a/gcc/fortran/array.cc b/gcc/fortran/array.cc
index 57a7b134e4c..7df7394cac6 100644
--- a/gcc/fortran/array.cc
+++ b/gcc/fortran/array.cc
@@ -1549,10 +1549,37 @@ check_constructor_type (gfc_constructor_base base, bool convert)
     {
       e = c->expr;
 
+      /* Simplify non-constant expressions (like parenthesized arrays) so type
+	 conversion can work on the simplified result.  This handles cases like
+	 [integer :: ([1.0])] where ([1.0]) is an EXPR_OP that needs to be
+	 simplified to an EXPR_ARRAY before type conversion.  */
+      if (convert && e->expr_type != EXPR_CONSTANT
+	  && e->expr_type != EXPR_ARRAY)
+	gfc_simplify_expr (e, 0);
+
       if (e->expr_type == EXPR_ARRAY)
 	{
-	  if (!check_constructor_type (e->value.constructor, convert))
-	    return false;
+	  /* If the outer constructor has no type-spec (convert=false) and
+	     the nested array has an explicit type-spec, process it separately
+	     so its elements get converted according to its type-spec.  This
+	     handles cases like [[character(16) :: ['a','b']]] where the outer
+	     constructor has no type-spec but the inner one does.
+	     gfc_check_constructor_type will also update the global
+	     constructor_ts and cons_state which propagates the type info
+	     to the outer constructor.
+	     For character types, length_from_typespec indicates an explicit
+	     type-spec was provided.  */
+	  if (!convert && e->ts.type == BT_CHARACTER
+	      && e->ts.u.cl && e->ts.u.cl->length_from_typespec)
+	    {
+	      if (!gfc_check_constructor_type (e))
+		return false;
+	    }
+	  else
+	    {
+	      if (!check_constructor_type (e->value.constructor, convert))
+		return false;
+	    }
 
 	  continue;
 	}
@@ -2261,10 +2288,14 @@ gfc_resolve_character_array_constructor (gfc_expr *expr)
 {
   gfc_constructor *p;
   HOST_WIDE_INT found_length;
+  bool has_ts;
 
   gcc_assert (expr->expr_type == EXPR_ARRAY);
   gcc_assert (expr->ts.type == BT_CHARACTER);
 
+  /* Check if we have an explicit type-spec with length.  */
+  has_ts = expr->ts.u.cl && expr->ts.u.cl->length_from_typespec;
+
   if (expr->ts.u.cl == NULL)
     {
       for (p = gfc_constructor_first (expr->value.constructor);
@@ -2367,28 +2398,55 @@ got_charlen:
       if (found_length != -1)
 	for (p = gfc_constructor_first (expr->value.constructor);
 	     p; p = gfc_constructor_next (p))
-	  if (p->expr->expr_type == EXPR_CONSTANT)
-	    {
-	      gfc_expr *cl = NULL;
-	      HOST_WIDE_INT current_length = -1;
-	      bool has_ts;
+	  {
+	    /* For non-constant expressions (like EXPR_OP from concatenation),
+	       try to simplify them first so we can then pad/truncate.  */
+	    if (p->expr->expr_type != EXPR_CONSTANT
+		&& p->expr->ts.type == BT_CHARACTER)
+	      gfc_simplify_expr (p->expr, 0);
 
-	      if (p->expr->ts.u.cl && p->expr->ts.u.cl->length)
+	    if (p->expr->expr_type == EXPR_CONSTANT)
 	      {
-		cl = p->expr->ts.u.cl->length;
-		gfc_extract_hwi (cl, &current_length);
+		gfc_expr *cl = NULL;
+		HOST_WIDE_INT current_length = -1;
+
+		if (p->expr->ts.u.cl && p->expr->ts.u.cl->length)
+		  {
+		    cl = p->expr->ts.u.cl->length;
+		    gfc_extract_hwi (cl, &current_length);
+		  }
+
+		/* If gfc_extract_int above set current_length, we implicitly
+		   know the type is BT_INTEGER and it's EXPR_CONSTANT.  */
+
+		if (! cl
+		    || (current_length != -1 && current_length != found_length))
+		  gfc_set_constant_character_len (found_length, p->expr,
+						  has_ts ? -1 : found_length);
 	      }
-
-	      /* If gfc_extract_int above set current_length, we implicitly
-		 know the type is BT_INTEGER and it's EXPR_CONSTANT.  */
-
-	      has_ts = expr->ts.u.cl->length_from_typespec;
-
-	      if (! cl
-		  || (current_length != -1 && current_length != found_length))
-		gfc_set_constant_character_len (found_length, p->expr,
-						has_ts ? -1 : found_length);
-	    }
+	                else if (p->expr->expr_type == EXPR_ARRAY)
+	                  {
+	                    /* For nested array constructors, propagate the type-spec and
+	                       recursively resolve.  This handles cases like
+	                       [character(16) :: ['a','b']] // "|".  The inner constructor
+	                       may have BT_UNKNOWN type initially.  */
+	                    if (p->expr->ts.type == BT_UNKNOWN
+	                        || p->expr->ts.type == BT_CHARACTER)
+	                      {
+	                        if (p->expr->ts.type == BT_CHARACTER
+	                            && p->expr->ts.u.cl
+	                            && p->expr->ts.u.cl->length_from_typespec)
+	                          {
+	                            /* If the inner array has an explicit type-spec, we must
+	                               honor it first (e.g. truncate/pad to its length),
+	                               before coercing it to the outer length.  */
+	                            gfc_resolve_character_array_constructor (p->expr);
+	                          }
+	    
+	                        p->expr->ts = expr->ts;
+	                        gfc_resolve_character_array_constructor (p->expr);
+	                      }
+	                  }	  }
     }
 
   return true;
diff --git a/gcc/testsuite/gfortran.dg/array_constructor_typespec_1.f90 b/gcc/testsuite/gfortran.dg/array_constructor_typespec_1.f90
new file mode 100644
index 00000000000..90840b5587c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/array_constructor_typespec_1.f90
@@ -0,0 +1,324 @@
+! { dg-do run }
+! PR fortran/107721 - array constructor type-spec lost with parentheses
+! PR fortran/102417 - character array constructor type-spec lost
+!
+! Tests type-spec preservation in array constructors with parentheses,
+! nested constructors, and CLASS(*) type verification for all intrinsic types.
+
+program array_constructor_typespec_1
+    implicit none
+    integer :: i, iscalar
+    integer, dimension(2) :: iarr
+    real, dimension(2) :: rarr
+    real :: rscalar
+    complex, dimension(2) :: carr
+    complex :: cscalar
+    logical, dimension(2) :: larr
+    character(4), dimension(3) :: charr
+    character(8), dimension(2) :: charr8
+    character(16), dimension(3) :: charr16
+    character(16), dimension(2) :: charr16_2
+    character(17), dimension(2) :: charr17
+    character :: x = 'a', y = 'b'
+    class(*), allocatable :: res(:)
+    character(10), dimension(1) :: charr10
+    character(4), dimension(1) :: charr4_1
+    character(0), dimension(1) :: charr0
+    character(4), dimension(0) :: empty4
+
+    ! INTEGER - runtime value checks
+    iarr = [integer :: [1.0], [2.0]]
+    if (any(iarr /= [1, 2])) stop 1
+    iarr = [integer :: ([1.0]), ([2.0])]
+    if (any(iarr /= [1, 2])) stop 2
+    iarr = [integer :: ((([1.0]))), [2.0]]
+    if (any(iarr /= [1, 2])) stop 3
+
+    ! REAL - runtime value checks
+    rarr = [real :: [2], [3]]
+    if (any(rarr /= [2.0, 3.0])) stop 4
+    rarr = [real :: ([2]), ([3])]
+    if (any(rarr /= [2.0, 3.0])) stop 5
+    rarr = [real :: ((([2]))), [3]]
+    if (any(rarr /= [2.0, 3.0])) stop 6
+
+    ! COMPLEX - runtime value checks
+    carr = [complex :: [3], [4]]
+    if (any(carr /= [(3.0, 0.0), (4.0, 0.0)])) stop 7
+    carr = [complex :: ([3]), ([4])]
+    if (any(carr /= [(3.0, 0.0), (4.0, 0.0)])) stop 8
+    carr = [complex :: ((([3]))), [4]]
+    if (any(carr /= [(3.0, 0.0), (4.0, 0.0)])) stop 9
+
+    ! LOGICAL - runtime value checks
+    larr = [logical :: [.true.], [.false.]]
+    if (any(larr .neqv. [.true., .false.])) stop 10
+    larr = [logical :: ([.true.]), ([.false.])]
+    if (any(larr .neqv. [.true., .false.])) stop 11
+
+    ! CHARACTER - runtime value checks (PR 102417)
+    charr = [character(4) :: 'a', 'b', 'c']
+    if (any(charr /= ['a   ', 'b   ', 'c   '])) stop 12
+    charr = [character(4) :: ('a'), 'b', 'c']
+    if (any(charr /= ['a   ', 'b   ', 'c   '])) stop 13
+    charr = [[character(4) :: 'a', 'b', 'c']]
+    if (any(charr /= ['a   ', 'b   ', 'c   '])) stop 14
+
+    ! CHARACTER with nested constructors - length 8
+    charr8 = [character(8) :: 'x', 'y']
+    if (charr8(1) /= 'x       ') stop 15
+    if (charr8(2) /= 'y       ') stop 16
+
+    charr8 = [character(8) :: ['a', 'b']]
+    if (charr8(1) /= 'a       ') stop 17
+    if (charr8(2) /= 'b       ') stop 18
+
+    ! Outer constructor without type-spec, inner with type-spec.
+    ! With proper type-spec propagation, no length mismatch warning is needed.
+    charr8 = [[character(8) :: ['a', 'b']]]
+    if (charr8(1) /= 'a       ') stop 19
+    if (charr8(2) /= 'b       ') stop 20
+
+    ! Triple-nested constructor with type-spec in middle.
+    charr8 = [[[character(8) :: ['a', 'b']]]]
+    if (charr8(1) /= 'a       ') stop 21
+    if (charr8(2) /= 'b       ') stop 22
+
+    charr8 = [character(8) :: (x), (y)]
+    if (charr8(1) /= 'a       ') stop 23
+    if (charr8(2) /= 'b       ') stop 24
+
+    charr8 = [[character(8) :: (x), (y)]]
+    if (charr8(1) /= 'a       ') stop 25
+    if (charr8(2) /= 'b       ') stop 26
+
+    ! CHARACTER concatenation with parentheses (PR 107721 comment 14)
+    charr16_2 = [character(16) :: 'a' // 'c', 'b' // 'de']
+    if (charr16_2(1) /= 'ac              ') stop 101
+    if (charr16_2(2) /= 'bde             ') stop 102
+
+    charr16_2 = [character(16) :: 'a' // 'c', ('b' // 'de')]
+    if (charr16_2(1) /= 'ac              ') stop 103
+    if (charr16_2(2) /= 'bde             ') stop 104
+
+    charr16_2 = [character(16) :: ('a' // 'c'), 'b' // 'de']
+    if (charr16_2(1) /= 'ac              ') stop 105
+    if (charr16_2(2) /= 'bde             ') stop 106
+
+    ! CHARACTER concatenation after constructor - verify length 17
+    charr17 = [character(16) :: 'a' // 'c', 'b' // 'de'] // '|'
+    if (len(charr17) /= 17) stop 107
+    if (charr17(1) /= 'ac              |') stop 108
+    if (charr17(2) /= 'bde             |') stop 109
+
+    charr17 = [character(16) :: 'a' // 'c', ('b' // 'de')] // '|'
+    if (len(charr17) /= 17) stop 110
+    if (charr17(1) /= 'ac              |') stop 111
+    if (charr17(2) /= 'bde             |') stop 112
+
+    charr17 = [character(16) :: ('a' // 'c'), 'b' // 'de'] // '|'
+    if (len(charr17) /= 17) stop 113
+    if (charr17(1) /= 'ac              |') stop 114
+    if (charr17(2) /= 'bde             |') stop 115
+
+    ! CHARACTER - longer length 16
+    charr16 = [character(16) :: 'a', 'b', 'c']
+    if (charr16(1) /= 'a               ') stop 27
+    if (charr16(2) /= 'b               ') stop 28
+    if (charr16(3) /= 'c               ') stop 29
+
+    charr16 = [[character(16) :: 'a', 'b', 'c']]
+    if (charr16(1) /= 'a               ') stop 30
+    if (charr16(2) /= 'b               ') stop 31
+    if (charr16(3) /= 'c               ') stop 32
+
+    ! CHARACTER - truncation cases
+    charr8 = [character(8) :: 'abcdefghij', 'klmnopqrst']
+    if (charr8(1) /= 'abcdefgh') stop 33
+    if (charr8(2) /= 'klmnopqr') stop 34
+
+    charr8 = [[character(8) :: 'abcdefghij', 'klmnopqrst']]
+    if (charr8(1) /= 'abcdefgh') stop 35
+    if (charr8(2) /= 'klmnopqr') stop 36
+
+    ! Implied-do with parentheses
+    iarr = [integer :: (/(1.0*i, i=1, 2)/)]
+    if (any(iarr /= [1, 2])) stop 37
+    iarr = [integer :: ((/(1.0*i, i=1, 2)/))]
+    if (any(iarr /= [1, 2])) stop 38
+
+    ! Type verification with CLASS(*) - ensure types are actually converted
+    res = [integer :: ([1.0])]
+    call verify_integer (res, 42)
+    deallocate (res)
+
+    res = [integer :: ([1.0]), ([2.0])]
+    call verify_integer (res, 43)
+    deallocate (res)
+
+    res = [real :: ([2]), [3]]
+    call verify_real (res, 44)
+    deallocate (res)
+
+    res = [complex :: ([3])]
+    call verify_complex (res, 45)
+    deallocate (res)
+
+    res = [logical :: ([.true.]), [.false.]]
+    call verify_logical (res, 46)
+    deallocate (res)
+
+    ! Parenthesized constructors - verify result TYPE not just value
+    res = [integer :: ([1.0])] ** 2
+    call verify_integer (res, 47)
+    deallocate (res)
+
+    res = [real :: ([2]), [3]] ** 2
+    call verify_real (res, 48)
+    deallocate (res)
+
+    res = [complex :: ([3])] ** 2
+    call verify_complex (res, 49)
+    deallocate (res)
+
+    ! Harald's test cases from Comment #17 - scalar // constructor patterns
+    charr17 = '|' // [character(16) :: 'a' // 'c', 'b' // 'de']
+    if (len(charr17) /= 17) stop 116
+    if (charr17(1) /= '|ac              ') stop 117
+    if (charr17(2) /= '|bde             ') stop 118
+
+    charr17 = '|' // [character(16) :: 'a' // 'c', ('b' // 'de')]
+    if (len(charr17) /= 17) stop 119
+    if (charr17(1) /= '|ac              ') stop 120
+    if (charr17(2) /= '|bde             ') stop 121
+
+    charr17 = '|' // [character(16) :: ('a' // 'c'), 'b' // 'de']
+    if (len(charr17) /= 17) stop 122
+    if (charr17(1) /= '|ac              ') stop 123
+    if (charr17(2) /= '|bde             ') stop 124
+
+    ! Comment #11: Nested array constructor with concatenation
+    ! The inner ['a','b'] must be padded to length 16 before concat
+    charr17 = [character(16) :: ['a', 'b']] // '|'
+    if (len(charr17) /= 17) stop 125
+    if (charr17(1) /= 'a               |') stop 126
+    if (charr17(2) /= 'b               |') stop 127
+
+    ! Comment #18: Outer constructor without type-spec wrapping inner with
+    ! type-spec.  The type-spec must be propagated when flattening.
+    charr17 = [[character(16) :: ['a', 'b']]] // '|'
+    if (len(charr17) /= 17) stop 128
+    if (charr17(1) /= 'a               |') stop 129
+    if (charr17(2) /= 'b               |') stop 130
+
+    charr17 = '|' // [[character(16) :: ['a', 'b']]]
+    if (len(charr17) /= 17) stop 131
+    if (charr17(1) /= '|a               ') stop 132
+    if (charr17(2) /= '|b               ') stop 133
+
+    ! Harald's new test cases from Comment #22 - nested truncation and padding
+    ! [ character(2) :: ['abcd','efgh'] ] should truncate to 'ab', 'ef'
+    ! Then [ character(16) :: ... ] should pad to 'ab              ', 'ef              '
+
+    charr16_2 = [ character(16) ::  [ character(2) :: ['abcd','efgh'] ] ]
+    if (charr16_2(1) /= 'ab              ') stop 134
+    if (charr16_2(2) /= 'ef              ') stop 135
+
+    charr17 = [ character(16) ::  [ character(2) :: ['abcd','efgh'] ] ] // "|"
+    if (len(charr17) /= 17) stop 136
+    if (charr17(1) /= 'ab              |') stop 137
+    if (charr17(2) /= 'ef              |') stop 138
+
+    charr17 = "|" // [ character(16) ::  [ character(2) :: ['abcd','efgh'] ] ]
+    if (len(charr17) /= 17) stop 139
+    if (charr17(1) /= '|ab              ') stop 140
+    if (charr17(2) /= '|ef              ') stop 141
+
+    charr16_2 = [ character(16) :: ([ character(2) :: ['abcd','efgh'] ])]
+    if (charr16_2(1) /= 'ab              ') stop 142
+    if (charr16_2(2) /= 'ef              ') stop 143
+
+    charr17 = [ character(16) :: ([ character(2) :: ['abcd','efgh'] ])] // "|"
+    if (len(charr17) /= 17) stop 144
+    if (charr17(1) /= 'ab              |') stop 145
+    if (charr17(2) /= 'ef              |') stop 146
+
+    charr17 = "|" // [ character(16) :: ([ character(2) :: ['abcd','efgh'] ])]
+    if (len(charr17) /= 17) stop 147
+    if (charr17(1) /= '|ab              ') stop 148
+    if (charr17(2) /= '|ef              ') stop 149
+
+    ! Additional torture tests
+    ! Triple nesting with explicit types: 'abcde'(5) -> 'ab'(2) -> 'ab        '(10)
+    charr10 = [character(10) :: [character(2) :: [character(5) :: 'abcde']]]
+    if (charr10(1) /= 'ab        ') stop 150
+
+    ! Concatenation of constructors
+    ! 'a'(2) // 'b'(3) -> 'a b  '(5) -> 'a b '(4)
+    charr4_1 = [character(4) :: [character(2) :: 'a'] // [character(3) :: 'b']]
+    if (charr4_1(1) /= 'a b ') stop 151
+
+    ! Zero length strings
+    ! Inner zero length: 'abc' -> ''(0) -> '    '(4)
+    charr4_1 = [character(4) :: [character(0) :: 'abc']]
+    if (charr4_1(1) /= '    ') stop 152
+
+    ! Outer zero length: 'abc' -> 'abc '(4) -> ''(0)
+    charr0 = [character(0) :: [character(4) :: 'abc']]
+    if (len(charr0) /= 0) stop 153
+    if (charr0(1) /= '') stop 154
+
+    ! Empty array constructors
+    empty4 = [character(4) :: ]
+    if (size(empty4) /= 0) stop 155
+    
+    empty4 = [character(4) :: [character(2) :: ]]
+    if (size(empty4) /= 0) stop 156
+
+contains
+
+    subroutine verify_integer (x, stopcode)
+        class(*), intent(in) :: x(:)
+        integer,  intent(in) :: stopcode
+        select type (x)
+        type is (integer)
+            ! Correct type
+        class default
+            stop stopcode
+        end select
+    end subroutine verify_integer
+
+    subroutine verify_real (x, stopcode)
+        class(*), intent(in) :: x(:)
+        integer,  intent(in) :: stopcode
+        select type (x)
+        type is (real)
+            ! Correct type
+        class default
+            stop stopcode
+        end select
+    end subroutine verify_real
+
+    subroutine verify_complex (x, stopcode)
+        class(*), intent(in) :: x(:)
+        integer,  intent(in) :: stopcode
+        select type (x)
+        type is (complex)
+            ! Correct type
+        class default
+            stop stopcode
+        end select
+    end subroutine verify_complex
+
+    subroutine verify_logical (x, stopcode)
+        class(*), intent(in) :: x(:)
+        integer,  intent(in) :: stopcode
+        select type (x)
+        type is (logical)
+            ! Correct type
+        class default
+            stop stopcode
+        end select
+    end subroutine verify_logical
+
+end program array_constructor_typespec_1
-- 
2.52.0

Reply via email to