diff --git a/flang/include/flang/Evaluate/tools.h b/flang/include/flang/Evaluate/tools.h
--- a/flang/include/flang/Evaluate/tools.h
+++ b/flang/include/flang/Evaluate/tools.h
@@ -873,33 +873,34 @@
     const std::optional<characteristics::Procedure> &lhsProcedure,
     const characteristics::Procedure *rhsProcedure);
 
-// Scalar constant expansion
-class ScalarConstantExpander {
+// Constant array creation.  It creates a constant array by expanding a
+// constant or by changing the lower bounds of an existing array
+class ArrayConstantMaker {
 public:
-  explicit ScalarConstantExpander(ConstantSubscripts &&extents)
+  explicit ArrayConstantMaker(ConstantSubscripts &&extents)
       : extents_{std::move(extents)} {}
-  ScalarConstantExpander(
+  ArrayConstantMaker(
       ConstantSubscripts &&extents, std::optional<ConstantSubscripts> &&lbounds)
       : extents_{std::move(extents)}, lbounds_{std::move(lbounds)} {}
-  ScalarConstantExpander(
-      ConstantSubscripts &&extents, ConstantSubscripts &&lbounds)
+  ArrayConstantMaker(ConstantSubscripts &&extents, ConstantSubscripts &&lbounds)
       : extents_{std::move(extents)}, lbounds_{std::move(lbounds)} {}
 
-  template <typename A> A Expand(A &&x) const {
+  template <typename A> A MakeArray(A &&x) const {
     return std::move(x); // default case
   }
-  template <typename T> Constant<T> Expand(Constant<T> &&x) {
-    auto expanded{x.Reshape(std::move(extents_))};
+  template <typename T> Constant<T> MakeArray(Constant<T> &&x) {
+    auto array{x.Reshape(std::move(extents_))};
     if (lbounds_) {
-      expanded.set_lbounds(std::move(*lbounds_));
+      array.set_lbounds(std::move(*lbounds_));
     }
-    return expanded;
+    return array;
   }
-  template <typename T> Constant<T> Expand(Parentheses<T> &&x) {
-    return Expand(std::move(x)); // Constant<> can be parenthesized
+  template <typename T> Constant<T> MakeArray(Parentheses<T> &&x) {
+    return MakeArray(std::move(x)); // Constant<> can be parenthesized
   }
-  template <typename T> Expr<T> Expand(Expr<T> &&x) {
-    return std::visit([&](auto &&x) { return Expr<T>{Expand(std::move(x))}; },
+  template <typename T> Expr<T> MakeArray(Expr<T> &&x) {
+    return std::visit(
+        [&](auto &&x) { return Expr<T>{MakeArray(std::move(x))}; },
         std::move(x.u));
   }
 
diff --git a/flang/lib/Evaluate/check-expression.cpp b/flang/lib/Evaluate/check-expression.cpp
--- a/flang/lib/Evaluate/check-expression.cpp
+++ b/flang/lib/Evaluate/check-expression.cpp
@@ -351,16 +351,24 @@
                 symbol.name(), symRank, folded.Rank());
           }
         } else if (auto extents{AsConstantExtents(context, symTS->shape())}) {
-          if (folded.Rank() == 0 && symRank > 0) {
-            return ScalarConstantExpander{std::move(*extents),
+          if (folded.Rank() == 0 && symRank == 0) {
+            // symbol and constant are both scalars
+            return {std::move(folded)};
+          } else if (folded.Rank() == 0 && symRank > 0) {
+            // expand the scalar constant to an array
+            return ArrayConstantMaker{std::move(*extents),
                 AsConstantExtents(
                     context, GetLowerBounds(context, NamedEntity{symbol}))}
-                .Expand(std::move(folded));
+                .MakeArray(std::move(folded));
           } else if (auto resultShape{GetShape(context, folded)}) {
             if (CheckConformance(context.messages(), symTS->shape(),
                     *resultShape, "initialized object",
                     "initialization expression", false, false)) {
-              return {std::move(folded)};
+              // make an array with adjusted lower bounds
+              return ArrayConstantMaker{std::move(*extents),
+                  AsConstantExtents(
+                      context, GetLowerBounds(context, NamedEntity{symbol}))}
+                  .MakeArray(std::move(folded));
             }
           }
         } else if (IsNamedConstant(symbol)) {
diff --git a/flang/lib/Evaluate/fold.cpp b/flang/lib/Evaluate/fold.cpp
--- a/flang/lib/Evaluate/fold.cpp
+++ b/flang/lib/Evaluate/fold.cpp
@@ -73,7 +73,7 @@
       if (auto valueShape{GetConstantExtents(context, expr)}) {
         if (auto componentShape{GetConstantExtents(context, symbol)}) {
           if (GetRank(*componentShape) > 0 && GetRank(*valueShape) == 0) {
-            expr = ScalarConstantExpander{std::move(*componentShape)}.Expand(
+            expr = ArrayConstantMaker{std::move(*componentShape)}.MakeArray(
                 std::move(expr));
             ok = expr.Rank() > 0;
           } else {
diff --git a/flang/lib/Evaluate/shape.cpp b/flang/lib/Evaluate/shape.cpp
--- a/flang/lib/Evaluate/shape.cpp
+++ b/flang/lib/Evaluate/shape.cpp
@@ -373,7 +373,7 @@
 MaybeExtentExpr ComputeUpperBound(
     ExtentExpr &&lower, MaybeExtentExpr &&extent) {
   if (extent) {
-    return std::move(*extent) - std::move(lower) + ExtentExpr{1};
+    return std::move(*extent) + std::move(lower) - ExtentExpr{1};
   } else {
     return std::nullopt;
   }
diff --git a/flang/test/Evaluate/folding16.f90 b/flang/test/Evaluate/folding16.f90
--- a/flang/test/Evaluate/folding16.f90
+++ b/flang/test/Evaluate/folding16.f90
@@ -3,6 +3,9 @@
 ! this is a regression test for a bug in which they were not
 real, parameter :: a(-1:-1) = 1.
 real, parameter :: b(-1:-1) = log(a)
+integer, parameter :: c(-1:1) = [33, 22, 11]
+integer, parameter :: d(1:3) = [33, 22, 11]
 logical, parameter :: test = lbound(a,1)==-1 .and. lbound(b,1)==-1 .and. &
                              lbound(log(a),1)==1 .and. all(b==0)
+logical, parameter :: test2 = all(c .eq. d)
 end
diff --git a/flang/test/Semantics/array-constr-values.f90 b/flang/test/Semantics/array-constr-values.f90
--- a/flang/test/Semantics/array-constr-values.f90
+++ b/flang/test/Semantics/array-constr-values.f90
@@ -54,12 +54,26 @@
 subroutine checkC7115()
   real, dimension(10), parameter :: good1 = [(99.9, i = 1, 10)]
   real, dimension(100), parameter :: good2 = [((88.8, i = 1, 10), j = 1, 10)]
+  real, dimension(-1:0), parameter :: good3 = [77.7, 66.6]
   !ERROR: Implied DO index is active in surrounding implied DO loop and may not have the same name
   real, dimension(100), parameter :: bad = [((88.8, i = 1, 10), i = 1, 10)]
 
   !ERROR: Value of named constant 'bad2' ([INTEGER(4)::(int(j,kind=4),INTEGER(8)::j=1_8,1_8,0_8)]) cannot be computed as a constant value
   !ERROR: The stride of an implied DO loop must not be zero
   integer, parameter :: bad2(*) = [(j, j=1,1,0)]
+  integer, parameter, dimension(-1:0) :: negLower = (/343,512/)
+
+  real :: local
+
+  local = good3(0)
+  !ERROR: Subscript value (2) is out of range on dimension 1 in reference to a constant array value
+  local = good3(2)
+  call inner(negLower(:)) ! OK
+
+  contains
+    subroutine inner(arg)
+      integer :: arg(:)
+    end subroutine inner
 end subroutine checkC7115
 subroutine checkOkDuplicates
   real :: realArray(21) = &