tbaeder updated this revision to Diff 543414.
tbaeder marked an inline comment as done.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156042/new/

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,9 @@
-// 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 -fexperimental-new-constant-interpreter -triple i686 %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 -fexperimental-new-constant-interpreter -triple i686 %s -verify
+// RUN: %clang_cc1 -std=c++20 -Wno-string-plus-int -verify=ref %s -Wno-constant-evaluated
 
 
 namespace strcmp {
@@ -38,6 +40,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
@@ -56,6 +56,30 @@
   llvm_unreachable("Int isn't 16 or 32 bit?");
 }
 
+static void pushSizeT(InterpState &S, uint64_t Val) {
+  const TargetInfo &TI = S.getCtx().getTargetInfo();
+  unsigned SizeTWidth = TI.getTypeWidth(TI.getSizeType());
+
+  if (SizeTWidth == 64)
+    S.Stk.push<Integral<64, false>>(Integral<64, false>::from(Val));
+  else if (SizeTWidth == 32)
+    S.Stk.push<Integral<32, false>>(Integral<32, false>::from(Val));
+  else
+    llvm_unreachable("size_t isn't 64 or 32 bit?");
+}
+
+static bool retSizeT(InterpState &S, CodePtr OpPC, APValue &Result) {
+  const TargetInfo &TI = S.getCtx().getTargetInfo();
+  unsigned SizeTWidth = TI.getTypeWidth(TI.getSizeType());
+
+  if (SizeTWidth == 64)
+    return Ret<PT_Uint64>(S, OpPC, Result);
+  else if (SizeTWidth == 32)
+    return Ret<PT_Uint32>(S, OpPC, Result);
+
+  llvm_unreachable("size_t isn't 64 or 32 bit?");
+}
+
 static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
                                    const InterpFrame *Frame) {
   const Pointer &A = getParam<Pointer>(Frame, 0);
@@ -95,6 +119,34 @@
   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 Len = 0;
+  for (size_t I = StrPtr.getIndex();; ++I, ++Len) {
+    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;
+  }
+
+  pushSizeT(S, Len);
+  return true;
+}
+
 static bool interp__builtin_nan(InterpState &S, CodePtr OpPC,
                                 const InterpFrame *Frame, const Function *F,
                                 bool Signaling) {
@@ -353,6 +405,10 @@
     if (interp__builtin_strcmp(S, OpPC, Frame))
       return retInt(S, OpPC, Dummy);
     break;
+  case Builtin::BI__builtin_strlen:
+    if (interp__builtin_strlen(S, OpPC, Frame))
+      return retSizeT(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