tbaeder created this revision.
tbaeder added reviewers: aaron.ballman, erichkeane, shafik, cor3ntin.
Herald added a project: All.
tbaeder requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D156042

Files:
  clang/lib/AST/Interp/InterpBuiltin.cpp
  clang/test/AST/Interp/builtin-functions.cpp

Index: clang/test/AST/Interp/builtin-functions.cpp
===================================================================
--- clang/test/AST/Interp/builtin-functions.cpp
+++ clang/test/AST/Interp/builtin-functions.cpp
@@ -1,7 +1,7 @@
-// RUN: %clang_cc1 -fexperimental-new-constant-interpreter %s -verify
-// RUN: %clang_cc1 -verify=ref %s -Wno-constant-evaluated
-// RUN: %clang_cc1 -std=c++20 -fexperimental-new-constant-interpreter %s -verify
-// RUN: %clang_cc1 -std=c++20 -verify=ref %s -Wno-constant-evaluated
+// RUN: %clang_cc1 -Wno-string-plus-int -fexperimental-new-constant-interpreter %s -verify
+// RUN: %clang_cc1 -Wno-string-plus-int -verify=ref %s -Wno-constant-evaluated
+// RUN: %clang_cc1 -std=c++20 -Wno-string-plus-int -fexperimental-new-constant-interpreter %s -verify
+// RUN: %clang_cc1 -std=c++20 -Wno-string-plus-int -verify=ref %s -Wno-constant-evaluated
 
 
 namespace strcmp {
@@ -38,6 +38,70 @@
                                                                         // ref-note {{dereferenced one-past-the-end}}
 }
 
+/// Copied from constant-expression-cxx11.cpp
+namespace strlen {
+constexpr const char *a = "foo\0quux";
+  constexpr char b[] = "foo\0quux";
+  constexpr int f() { return 'u'; }
+  constexpr char c[] = { 'f', 'o', 'o', 0, 'q', f(), 'u', 'x', 0 };
+
+  static_assert(__builtin_strlen("foo") == 3, "");
+  static_assert(__builtin_strlen("foo\0quux") == 3, "");
+  static_assert(__builtin_strlen("foo\0quux" + 4) == 4, "");
+
+  constexpr bool check(const char *p) {
+    return __builtin_strlen(p) == 3 &&
+           __builtin_strlen(p + 1) == 2 &&
+           __builtin_strlen(p + 2) == 1 &&
+           __builtin_strlen(p + 3) == 0 &&
+           __builtin_strlen(p + 4) == 4 &&
+           __builtin_strlen(p + 5) == 3 &&
+           __builtin_strlen(p + 6) == 2 &&
+           __builtin_strlen(p + 7) == 1 &&
+           __builtin_strlen(p + 8) == 0;
+  }
+
+  static_assert(check(a), "");
+  static_assert(check(b), "");
+  static_assert(check(c), "");
+
+  constexpr int over1 = __builtin_strlen(a + 9); // expected-error {{constant expression}} \
+                                                 // expected-note {{one-past-the-end}} \
+                                                 // expected-note {{in call to}} \
+                                                 // ref-error {{constant expression}} \
+                                                 // ref-note {{one-past-the-end}}
+  constexpr int over2 = __builtin_strlen(b + 9); // expected-error {{constant expression}} \
+                                                 // expected-note {{one-past-the-end}} \
+                                                 // expected-note {{in call to}} \
+                                                 // ref-error {{constant expression}} \
+                                                 // ref-note {{one-past-the-end}}
+  constexpr int over3 = __builtin_strlen(c + 9); // expected-error {{constant expression}} \
+                                                 // expected-note {{one-past-the-end}} \
+                                                 // expected-note {{in call to}} \
+                                                 // ref-error {{constant expression}} \
+                                                 // ref-note {{one-past-the-end}}
+
+  constexpr int under1 = __builtin_strlen(a - 1); // expected-error {{constant expression}} \
+                                                  // expected-note {{cannot refer to element -1}} \
+                                                  // ref-error {{constant expression}} \
+                                                  // ref-note {{cannot refer to element -1}}
+  constexpr int under2 = __builtin_strlen(b - 1); // expected-error {{constant expression}} \
+                                                  // expected-note {{cannot refer to element -1}} \
+                                                  // ref-error {{constant expression}} \
+                                                  // ref-note {{cannot refer to element -1}}
+  constexpr int under3 = __builtin_strlen(c - 1); // expected-error {{constant expression}} \
+                                                  // expected-note {{cannot refer to element -1}} \
+                                                  // ref-error {{constant expression}} \
+                                                  // ref-note {{cannot refer to element -1}}
+
+  constexpr char d[] = { 'f', 'o', 'o' }; // no nul terminator.
+  constexpr int bad = __builtin_strlen(d); // expected-error {{constant expression}} \
+                                           // expected-note {{one-past-the-end}} \
+                                           // expected-note {{in call to}} \
+                                           // ref-error {{constant expression}} \
+                                           // ref-note {{one-past-the-end}}
+}
+
 namespace nan {
   constexpr double NaN1 = __builtin_nan("");
 
Index: clang/lib/AST/Interp/InterpBuiltin.cpp
===================================================================
--- clang/lib/AST/Interp/InterpBuiltin.cpp
+++ clang/lib/AST/Interp/InterpBuiltin.cpp
@@ -84,6 +84,38 @@
   return true;
 }
 
+static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC,
+                                   const InterpFrame *Frame) {
+  const Pointer &StrPtr = getParam<Pointer>(Frame, 0);
+
+  if (!CheckArray(S, OpPC, StrPtr))
+    return false;
+
+  if (!CheckLive(S, OpPC, StrPtr, AK_Read))
+    return false;
+
+  assert(StrPtr.getFieldDesc()->isPrimitiveArray());
+
+  size_t I = StrPtr.getIndex();
+  size_t Len = 0;
+  for (;;) {
+    const Pointer &ElemPtr = StrPtr.atIndex(I);
+
+    if (!CheckRange(S, OpPC, ElemPtr, AK_Read))
+      return false;
+
+    uint8_t Val = ElemPtr.deref<uint8_t>();
+    if (Val == 0)
+      break;
+    ++I;
+    ++Len;
+  }
+
+  // TODO: Push platform-dependent size_t.
+  S.Stk.push<Integral<64, false>>(Integral<64, false>::from(Len));
+  return true;
+}
+
 static bool interp__builtin_nan(InterpState &S, CodePtr OpPC,
                                 const InterpFrame *Frame, const Function *F,
                                 bool Signaling) {
@@ -342,6 +374,10 @@
     if (interp__builtin_strcmp(S, OpPC, Frame))
       return Ret<PT_Sint32>(S, OpPC, Dummy);
     break;
+  case Builtin::BI__builtin_strlen:
+    if (interp__builtin_strlen(S, OpPC, Frame))
+      return Ret<PT_Uint64>(S, OpPC, Dummy);
+    break;
   case Builtin::BI__builtin_nan:
   case Builtin::BI__builtin_nanf:
   case Builtin::BI__builtin_nanl:
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to