Skip to content

Conversation

@tbaederr
Copy link
Contributor

No description provided.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:bytecode Issues for the clang bytecode constexpr interpreter labels Apr 28, 2025
@llvmbot
Copy link
Member

llvmbot commented Apr 28, 2025

@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/137679.diff

5 Files Affected:

  • (modified) clang/lib/AST/ByteCode/Compiler.cpp (+7-4)
  • (modified) clang/lib/AST/ByteCode/Interp.h (+19)
  • (modified) clang/lib/AST/ByteCode/InterpBuiltin.cpp (+3)
  • (modified) clang/lib/AST/ByteCode/Opcodes.td (+2)
  • (added) clang/test/AST/ByteCode/dynalloc-limits.cpp (+73)
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 9a1e61b54b8be..fe8d05c001a31 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -1862,6 +1862,13 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
     if (Inits.size() == 1 && QT == Inits[0]->getType())
       return this->delegate(Inits[0]);
 
+    const ConstantArrayType *CAT =
+        Ctx.getASTContext().getAsConstantArrayType(QT);
+    uint64_t NumElems = CAT->getZExtSize();
+
+    if (!this->emitCheckArraySize(NumElems, E))
+      return false;
+
     unsigned ElementIndex = 0;
     for (const Expr *Init : Inits) {
       if (const auto *EmbedS =
@@ -1890,10 +1897,6 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
     // Expand the filler expression.
     // FIXME: This should go away.
     if (ArrayFiller) {
-      const ConstantArrayType *CAT =
-          Ctx.getASTContext().getAsConstantArrayType(QT);
-      uint64_t NumElems = CAT->getZExtSize();
-
       for (; ElementIndex != NumElems; ++ElementIndex) {
         if (!this->visitArrayElemInit(ElementIndex, ArrayFiller))
           return false;
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 6cd995279029a..80488b5fa3f46 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -175,6 +175,8 @@ bool handleFixedPointOverflow(InterpState &S, CodePtr OpPC,
 
 bool isConstexprUnknown(const Pointer &P);
 
+inline bool CheckArraySize(InterpState &S, CodePtr OpPC, uint64_t NumElems);
+
 enum class ShiftDir { Left, Right };
 
 /// Checks if the shift operation is legal.
@@ -3110,6 +3112,9 @@ inline bool AllocN(InterpState &S, CodePtr OpPC, PrimType T, const Expr *Source,
   }
   assert(NumElements.isPositive());
 
+  if (!CheckArraySize(S, OpPC, static_cast<uint64_t>(NumElements)))
+    return false;
+
   DynamicAllocator &Allocator = S.getAllocator();
   Block *B =
       Allocator.allocate(Source, T, static_cast<size_t>(NumElements),
@@ -3140,6 +3145,9 @@ inline bool AllocCN(InterpState &S, CodePtr OpPC, const Descriptor *ElementDesc,
   }
   assert(NumElements.isPositive());
 
+  if (!CheckArraySize(S, OpPC, static_cast<uint64_t>(NumElements)))
+    return false;
+
   DynamicAllocator &Allocator = S.getAllocator();
   Block *B =
       Allocator.allocate(ElementDesc, static_cast<size_t>(NumElements),
@@ -3246,6 +3254,17 @@ inline bool CheckDestruction(InterpState &S, CodePtr OpPC) {
   return CheckDestructor(S, OpPC, Ptr);
 }
 
+inline bool CheckArraySize(InterpState &S, CodePtr OpPC, uint64_t NumElems) {
+  uint64_t Limit = S.getLangOpts().ConstexprStepLimit;
+  if (NumElems > Limit) {
+    S.FFDiag(S.Current->getSource(OpPC),
+             diag::note_constexpr_new_exceeds_limits)
+        << NumElems << Limit;
+    return false;
+  }
+  return true;
+}
+
 //===----------------------------------------------------------------------===//
 // Read opcode arguments
 //===----------------------------------------------------------------------===//
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 34baae1986c35..b82188a956a14 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -1531,6 +1531,9 @@ static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC,
     return false;
   }
 
+  if (!CheckArraySize(S, OpPC, NumElems.getZExtValue()))
+    return false;
+
   bool IsArray = NumElems.ugt(1);
   std::optional<PrimType> ElemT = S.getContext().classify(ElemType);
   DynamicAllocator &Allocator = S.getAllocator();
diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td
index e71790211293a..65a9a0cdad022 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -414,6 +414,8 @@ def CheckLiteralType : Opcode {
   let Args = [ArgTypePtr];
 }
 
+def CheckArraySize : Opcode { let Args = [ArgUint64]; }
+
 // [] -> [Value]
 def GetGlobal : AccessOpcode;
 def GetGlobalUnchecked : AccessOpcode;
diff --git a/clang/test/AST/ByteCode/dynalloc-limits.cpp b/clang/test/AST/ByteCode/dynalloc-limits.cpp
new file mode 100644
index 0000000000000..ed2d4faf974b1
--- /dev/null
+++ b/clang/test/AST/ByteCode/dynalloc-limits.cpp
@@ -0,0 +1,73 @@
+// RUN: %clang_cc1 -std=c++20 -verify=ref,both      -fconstexpr-steps=1024 -Wvla %s
+// RUN: %clang_cc1 -std=c++20 -verify=both,both -fconstexpr-steps=1024 -Wvla %s -fexperimental-new-constant-interpreter
+
+
+
+
+namespace std {
+  using size_t = decltype(sizeof(0));
+}
+
+void *operator new(std::size_t, void *p) { return p; }
+
+namespace std {
+  template<typename T> struct allocator {
+    constexpr T *allocate(size_t N) {
+      return (T*)operator new(sizeof(T) * N); // #alloc
+    }
+    constexpr void deallocate(void *p) {
+      operator delete(p);
+    }
+  };
+  template<typename T, typename ...Args>
+  constexpr void construct_at(void *p, Args &&...args) { // #construct
+    new (p) T((Args&&)args...);
+  }
+}
+
+template <typename T>
+struct S {
+    constexpr S(unsigned long long N)
+    : data(nullptr){
+        data = alloc.allocate(N);  // #call
+        for(std::size_t i = 0; i < N; i ++)
+            std::construct_at<T>(data + i, i); // #construct_call
+    }
+    constexpr T operator[](std::size_t i) const {
+      return data[i];
+    }
+
+    constexpr ~S() {
+        alloc.deallocate(data);
+    }
+    std::allocator<T> alloc;
+    T* data;
+};
+
+#if __LP64__
+constexpr std::size_t s = S<std::size_t>(~0UL)[42]; // both-error {{constexpr variable 's' must be initialized by a constant expression}} \
+                                           // both-note-re@#call {{in call to 'this->alloc.allocate({{.*}})'}} \
+                                           // both-note-re@#alloc {{cannot allocate array; evaluated array bound {{.*}} is too large}} \
+                                           // both-note-re {{in call to 'S({{.*}})'}}
+#endif
+
+constexpr std::size_t ssmall = S<std::size_t>(100)[42];
+
+constexpr std::size_t s5 = S<std::size_t>(1025)[42]; // both-error {{constexpr variable 's5' must be initialized by a constant expression}} \
+                                   // both-note@#alloc {{cannot allocate array; evaluated array bound 1025 exceeds the limit (1024); use '-fconstexpr-steps' to increase this limit}} \
+                                   // both-note@#call {{in call to 'this->alloc.allocate(1025)'}} \
+                                   // both-note {{in call}}
+
+
+
+template <auto N>
+constexpr int stack_array() {
+    [[maybe_unused]] char BIG[N] = {1};  // both-note {{cannot allocate array; evaluated array bound 1025 exceeds the limit (1024)}}
+    return BIG[N-1];
+}
+
+int c = stack_array<1024>();
+int d = stack_array<1025>();
+constexpr int e = stack_array<1024>();
+constexpr int f = stack_array<1025>(); // both-error {{constexpr variable 'f' must be initialized by a constant expression}} \
+                                       // both-note {{in call}}

@tbaederr tbaederr merged commit 15579a8 into llvm:main Apr 29, 2025
15 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented Apr 29, 2025

LLVM Buildbot has detected a new failure on builder flang-aarch64-latest-gcc running on linaro-flang-aarch64-latest-gcc while building clang at step 5 "build-unified-tree".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/130/builds/12900

Here is the relevant piece of the build log for the reference
Step 5 (build-unified-tree) failure: build (failure)
...
781.428 [679/111/6601] Building CXX object tools/clang/lib/AST/CMakeFiles/obj.clangAST.dir/ByteCode/Disasm.cpp.o
783.466 [679/110/6602] Building CXX object tools/flang/lib/Lower/CMakeFiles/FortranLower.dir/ComponentPath.cpp.o
787.081 [679/109/6603] Building CXX object tools/flang/lib/Parser/CMakeFiles/FortranParser.dir/expr-parsers.cpp.o
787.149 [679/108/6604] Building CXX object tools/flang/lib/Semantics/CMakeFiles/FortranSemantics.dir/dump-expr.cpp.o
789.997 [679/107/6605] Building CXX object tools/flang/lib/Optimizer/Builder/CMakeFiles/FIRBuilder.dir/Runtime/Transformational.cpp.o
793.893 [679/106/6606] Building CXX object tools/flang/lib/Semantics/CMakeFiles/FortranSemantics.dir/check-return.cpp.o
794.377 [679/105/6607] Building CXX object tools/flang/lib/Lower/CMakeFiles/FortranLower.dir/HlfirIntrinsics.cpp.o
795.957 [679/104/6608] Building CXX object tools/flang/lib/Semantics/CMakeFiles/FortranSemantics.dir/openmp-modifiers.cpp.o
796.470 [679/103/6609] Building CXX object tools/flang/lib/Parser/CMakeFiles/FortranParser.dir/io-parsers.cpp.o
846.799 [679/102/6610] Building CXX object tools/flang/lib/Lower/CMakeFiles/FortranLower.dir/OpenMP/PrivateReductionUtils.cpp.o
FAILED: tools/flang/lib/Lower/CMakeFiles/FortranLower.dir/OpenMP/PrivateReductionUtils.cpp.o 
/usr/local/bin/c++ -DFLANG_INCLUDE_TESTS=1 -DGTEST_HAS_RTTI=0 -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/home/tcwg-buildbot/worker/flang-aarch64-latest-gcc/build/tools/flang/lib/Lower -I/home/tcwg-buildbot/worker/flang-aarch64-latest-gcc/llvm-project/flang/lib/Lower -I/home/tcwg-buildbot/worker/flang-aarch64-latest-gcc/llvm-project/flang/include -I/home/tcwg-buildbot/worker/flang-aarch64-latest-gcc/build/tools/flang/include -I/home/tcwg-buildbot/worker/flang-aarch64-latest-gcc/build/include -I/home/tcwg-buildbot/worker/flang-aarch64-latest-gcc/llvm-project/llvm/include -isystem /home/tcwg-buildbot/worker/flang-aarch64-latest-gcc/llvm-project/flang/../mlir/include -isystem /home/tcwg-buildbot/worker/flang-aarch64-latest-gcc/build/tools/mlir/include -isystem /home/tcwg-buildbot/worker/flang-aarch64-latest-gcc/build/tools/clang/include -isystem /home/tcwg-buildbot/worker/flang-aarch64-latest-gcc/llvm-project/llvm/../clang/include -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -pedantic -Wno-long-long -Wimplicit-fallthrough -Wno-maybe-uninitialized -Wno-nonnull -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wdelete-non-virtual-dtor -Wsuggest-override -Wno-comment -Wno-misleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -Wno-deprecated-copy -Wno-ctad-maybe-unsupported -fno-strict-aliasing -fno-semantic-interposition -fpch-preprocess -O3 -DNDEBUG -fno-semantic-interposition -std=c++17 -fPIC  -fno-exceptions -funwind-tables -fno-rtti -UNDEBUG -MD -MT tools/flang/lib/Lower/CMakeFiles/FortranLower.dir/OpenMP/PrivateReductionUtils.cpp.o -MF tools/flang/lib/Lower/CMakeFiles/FortranLower.dir/OpenMP/PrivateReductionUtils.cpp.o.d -o tools/flang/lib/Lower/CMakeFiles/FortranLower.dir/OpenMP/PrivateReductionUtils.cpp.o -c /home/tcwg-buildbot/worker/flang-aarch64-latest-gcc/llvm-project/flang/lib/Lower/OpenMP/PrivateReductionUtils.cpp
g++-latest: fatal error: Killed signal terminated program cc1plus
compilation terminated.
847.614 [679/101/6611] Building CXX object tools/flang/lib/Semantics/CMakeFiles/FortranSemantics.dir/check-nullify.cpp.o
848.986 [679/100/6612] Building CXX object tools/flang/lib/Semantics/CMakeFiles/FortranSemantics.dir/check-if-stmt.cpp.o
961.309 [679/99/6613] Building CXX object tools/flang/lib/Semantics/CMakeFiles/FortranSemantics.dir/canonicalize-omp.cpp.o
961.378 [679/98/6614] Building CXX object tools/flang/lib/Lower/CMakeFiles/FortranLower.dir/Allocatable.cpp.o
FAILED: tools/flang/lib/Lower/CMakeFiles/FortranLower.dir/Allocatable.cpp.o 
/usr/local/bin/c++ -DFLANG_INCLUDE_TESTS=1 -DGTEST_HAS_RTTI=0 -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/home/tcwg-buildbot/worker/flang-aarch64-latest-gcc/build/tools/flang/lib/Lower -I/home/tcwg-buildbot/worker/flang-aarch64-latest-gcc/llvm-project/flang/lib/Lower -I/home/tcwg-buildbot/worker/flang-aarch64-latest-gcc/llvm-project/flang/include -I/home/tcwg-buildbot/worker/flang-aarch64-latest-gcc/build/tools/flang/include -I/home/tcwg-buildbot/worker/flang-aarch64-latest-gcc/build/include -I/home/tcwg-buildbot/worker/flang-aarch64-latest-gcc/llvm-project/llvm/include -isystem /home/tcwg-buildbot/worker/flang-aarch64-latest-gcc/llvm-project/flang/../mlir/include -isystem /home/tcwg-buildbot/worker/flang-aarch64-latest-gcc/build/tools/mlir/include -isystem /home/tcwg-buildbot/worker/flang-aarch64-latest-gcc/build/tools/clang/include -isystem /home/tcwg-buildbot/worker/flang-aarch64-latest-gcc/llvm-project/llvm/../clang/include -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -pedantic -Wno-long-long -Wimplicit-fallthrough -Wno-maybe-uninitialized -Wno-nonnull -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wdelete-non-virtual-dtor -Wsuggest-override -Wno-comment -Wno-misleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -Wno-deprecated-copy -Wno-ctad-maybe-unsupported -fno-strict-aliasing -fno-semantic-interposition -fpch-preprocess -O3 -DNDEBUG -fno-semantic-interposition -std=c++17 -fPIC  -fno-exceptions -funwind-tables -fno-rtti -UNDEBUG -MD -MT tools/flang/lib/Lower/CMakeFiles/FortranLower.dir/Allocatable.cpp.o -MF tools/flang/lib/Lower/CMakeFiles/FortranLower.dir/Allocatable.cpp.o.d -o tools/flang/lib/Lower/CMakeFiles/FortranLower.dir/Allocatable.cpp.o -c /home/tcwg-buildbot/worker/flang-aarch64-latest-gcc/llvm-project/flang/lib/Lower/Allocatable.cpp
g++-latest: fatal error: Killed signal terminated program cc1plus
compilation terminated.
963.182 [679/97/6615] Building CXX object tools/flang/lib/Semantics/CMakeFiles/FortranSemantics.dir/check-stop.cpp.o
963.219 [679/96/6616] Building CXX object tools/flang/lib/Frontend/CMakeFiles/flangFrontend.dir/CompilerInvocation.cpp.o
964.343 [679/95/6617] Building CXX object tools/flang/lib/Lower/CMakeFiles/FortranLower.dir/Coarray.cpp.o
964.567 [679/94/6618] Building CXX object tools/flang/lib/Semantics/CMakeFiles/FortranSemantics.dir/check-namelist.cpp.o
966.327 [679/93/6619] Building CXX object tools/flang/lib/Semantics/CMakeFiles/FortranSemantics.dir/compute-offsets.cpp.o
967.972 [679/92/6620] Building CXX object tools/flang/lib/Frontend/CMakeFiles/flangFrontend.dir/FrontendAction.cpp.o
968.117 [679/91/6621] Building CXX object tools/flang/lib/Semantics/CMakeFiles/FortranSemantics.dir/check-purity.cpp.o
968.223 [679/90/6622] Building CXX object tools/flang/lib/Frontend/CMakeFiles/flangFrontend.dir/CompilerInstance.cpp.o
968.984 [679/89/6623] Building CXX object tools/flang/lib/Parser/CMakeFiles/FortranParser.dir/openacc-parsers.cpp.o
970.082 [679/88/6624] Building CXX object tools/flang/lib/Semantics/CMakeFiles/FortranSemantics.dir/program-tree.cpp.o
970.815 [679/87/6625] Building CXX object tools/flang/lib/Optimizer/Builder/CMakeFiles/FIRBuilder.dir/PPCIntrinsicCall.cpp.o
970.859 [679/86/6626] Building CXX object tools/flang/lib/Semantics/CMakeFiles/FortranSemantics.dir/canonicalize-do.cpp.o
972.459 [679/85/6627] Building CXX object tools/flang/lib/Semantics/CMakeFiles/FortranSemantics.dir/check-arithmeticif.cpp.o
974.064 [679/84/6628] Building CXX object tools/flang/lib/Semantics/CMakeFiles/FortranSemantics.dir/check-select-type.cpp.o
975.333 [679/83/6629] Building CXX object tools/flang/lib/Optimizer/Builder/CMakeFiles/FIRBuilder.dir/Runtime/Intrinsics.cpp.o
975.505 [679/82/6630] Building CXX object tools/flang/lib/Semantics/CMakeFiles/FortranSemantics.dir/check-allocate.cpp.o
978.477 [679/81/6631] Building CXX object tools/flang/lib/Parser/CMakeFiles/FortranParser.dir/unparse.cpp.o
979.485 [679/80/6632] Building CXX object tools/clang/lib/AST/CMakeFiles/obj.clangAST.dir/ByteCode/EvalEmitter.cpp.o
In file included from ../llvm-project/clang/lib/AST/ByteCode/EvalEmitter.cpp:12:
../llvm-project/clang/lib/AST/ByteCode/Interp.h: In instantiation of ‘bool clang::interp::Divc(InterpState&, CodePtr) [with PrimType Name = clang::interp::PT_Sint8; T = Integral<8, true>]’:
tools/clang/lib/AST/Opcodes.inc:11530:24:   required from here
../llvm-project/clang/lib/AST/ByteCode/Interp.h:551:14: warning: possibly dangling reference to a temporary [-Wdangling-reference]
  551 |     const T &LHSR = LHS.atIndex(0).deref<T>();
      |              ^~~~
../llvm-project/clang/lib/AST/ByteCode/Interp.h:551:44: note: the temporary was destroyed at the end of the full expression ‘clang::interp::Pointer::atIndex(uint64_t) const(0).clang::interp::Pointer::deref<clang::interp::Integral<8, true> >()’
  551 |     const T &LHSR = LHS.atIndex(0).deref<T>();
      |                     ~~~~~~~~~~~~~~~~~~~~~~~^~

IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
GeorgeARM pushed a commit to GeorgeARM/llvm-project that referenced this pull request May 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:bytecode Issues for the clang bytecode constexpr interpreter clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants