Skip to content

Conversation

@tbaederr
Copy link
Contributor

…723)"

This reverts commit 1e2ad67.

Fix the previous commit on big-endian hosts by not falling through to the uint8_t code path.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Mar 25, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 25, 2025

@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)

Changes

…723)"

This reverts commit 1e2ad67.

Fix the previous commit on big-endian hosts by not falling through to the uint8_t code path.


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

2 Files Affected:

  • (modified) clang/lib/AST/ByteCode/InterpBuiltin.cpp (+40-13)
  • (modified) clang/test/AST/ByteCode/builtin-functions.cpp (+46)
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index d7de4c09e2614..4d125e4c202d2 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -212,11 +212,13 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
   const Pointer &A = getParam<Pointer>(Frame, 0);
   const Pointer &B = getParam<Pointer>(Frame, 1);
 
-  if (ID == Builtin::BIstrcmp || ID == Builtin::BIstrncmp)
+  if (ID == Builtin::BIstrcmp || ID == Builtin::BIstrncmp ||
+      ID == Builtin::BIwcscmp || ID == Builtin::BIwcsncmp)
     diagnoseNonConstexprBuiltin(S, OpPC, ID);
 
   uint64_t Limit = ~static_cast<uint64_t>(0);
-  if (ID == Builtin::BIstrncmp || ID == Builtin::BI__builtin_strncmp)
+  if (ID == Builtin::BIstrncmp || ID == Builtin::BI__builtin_strncmp ||
+      ID == Builtin::BIwcsncmp || ID == Builtin::BI__builtin_wcsncmp)
     Limit = peekToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(2)))
                 .getZExtValue();
 
@@ -231,12 +233,22 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
   if (A.isDummy() || B.isDummy())
     return false;
 
+  bool IsWide = ID == Builtin::BIwcscmp || ID == Builtin::BIwcsncmp ||
+                ID == Builtin::BI__builtin_wcscmp ||
+                ID == Builtin::BI__builtin_wcsncmp;
   assert(A.getFieldDesc()->isPrimitiveArray());
   assert(B.getFieldDesc()->isPrimitiveArray());
 
+  assert(getElemType(A).getTypePtr() == getElemType(B).getTypePtr());
+  PrimType ElemT = *S.getContext().classify(getElemType(A));
+
+  auto returnResult = [&](int V) -> bool {
+    pushInteger(S, V, Call->getType());
+    return true;
+  };
+
   unsigned IndexA = A.getIndex();
   unsigned IndexB = B.getIndex();
-  int32_t Result = 0;
   uint64_t Steps = 0;
   for (;; ++IndexA, ++IndexB, ++Steps) {
 
@@ -248,22 +260,33 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
         !CheckRange(S, OpPC, PB, AK_Read)) {
       return false;
     }
+
+    if (IsWide) {
+      INT_TYPE_SWITCH(ElemT, {
+        T CA = PA.deref<T>();
+        T CB = PB.deref<T>();
+        if (CA > CB)
+          return returnResult(1);
+        else if (CA < CB)
+          return returnResult(-1);
+        else if (CA.isZero() || CB.isZero())
+          return returnResult(0);
+      });
+      continue;
+    }
+
     uint8_t CA = PA.deref<uint8_t>();
     uint8_t CB = PB.deref<uint8_t>();
 
-    if (CA > CB) {
-      Result = 1;
-      break;
-    } else if (CA < CB) {
-      Result = -1;
-      break;
-    }
+    if (CA > CB)
+      return returnResult(1);
+    else if (CA < CB)
+      return returnResult(-1);
     if (CA == 0 || CB == 0)
-      break;
+      return returnResult(0);
   }
 
-  pushInteger(S, Result, Call->getType());
-  return true;
+  return returnResult(0);
 }
 
 static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC,
@@ -2120,6 +2143,10 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
   case Builtin::BIstrcmp:
   case Builtin::BI__builtin_strncmp:
   case Builtin::BIstrncmp:
+  case Builtin::BI__builtin_wcsncmp:
+  case Builtin::BIwcsncmp:
+  case Builtin::BI__builtin_wcscmp:
+  case Builtin::BIwcscmp:
     if (!interp__builtin_strcmp(S, OpPC, Frame, F, Call))
       return false;
     break;
diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp
index 828822375e95e..8408286314bb8 100644
--- a/clang/test/AST/ByteCode/builtin-functions.cpp
+++ b/clang/test/AST/ByteCode/builtin-functions.cpp
@@ -28,6 +28,8 @@ extern "C" {
   extern char *strchr(const char *s, int c);
   extern wchar_t *wmemchr(const wchar_t *s, wchar_t c, size_t n);
   extern wchar_t *wcschr(const wchar_t *s, wchar_t c);
+  extern int wcscmp(const wchar_t *s1, const wchar_t *s2);
+  extern int wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n);
 }
 
 namespace strcmp {
@@ -72,6 +74,50 @@ namespace strcmp {
   static_assert(__builtin_strncmp("abab\0banana", "abab\0canada", 100) == 0);
 }
 
+namespace WcsCmp {
+  constexpr wchar_t kFoobar[6] = {L'f',L'o',L'o',L'b',L'a',L'r'};
+  constexpr wchar_t kFoobazfoobar[12] = {L'f',L'o',L'o',L'b',L'a',L'z',L'f',L'o',L'o',L'b',L'a',L'r'};
+
+  static_assert(__builtin_wcscmp(L"abab", L"abab") == 0);
+  static_assert(__builtin_wcscmp(L"abab", L"abba") == -1);
+  static_assert(__builtin_wcscmp(L"abab", L"abaa") == 1);
+  static_assert(__builtin_wcscmp(L"ababa", L"abab") == 1);
+  static_assert(__builtin_wcscmp(L"abab", L"ababa") == -1);
+  static_assert(__builtin_wcscmp(L"abab\0banana", L"abab") == 0);
+  static_assert(__builtin_wcscmp(L"abab", L"abab\0banana") == 0);
+  static_assert(__builtin_wcscmp(L"abab\0banana", L"abab\0canada") == 0);
+#if __WCHAR_WIDTH__ == 32
+  static_assert(__builtin_wcscmp(L"a\x83838383", L"a") == (wchar_t)-1U >> 31);
+#endif
+  static_assert(__builtin_wcscmp(0, L"abab") == 0); // both-error {{not an integral constant}} \
+                                                    // both-note {{dereferenced null}}
+  static_assert(__builtin_wcscmp(L"abab", 0) == 0); // both-error {{not an integral constant}} \
+                                                    // both-note {{dereferenced null}}
+
+  static_assert(__builtin_wcscmp(kFoobar, kFoobazfoobar) == -1);
+  static_assert(__builtin_wcscmp(kFoobar, kFoobazfoobar + 6) == 0); // both-error {{not an integral constant}} \
+                                                                    // both-note {{dereferenced one-past-the-end}}
+
+  static_assert(__builtin_wcsncmp(L"abaa", L"abba", 5) == -1);
+  static_assert(__builtin_wcsncmp(L"abaa", L"abba", 4) == -1);
+  static_assert(__builtin_wcsncmp(L"abaa", L"abba", 3) == -1);
+  static_assert(__builtin_wcsncmp(L"abaa", L"abba", 2) == 0);
+  static_assert(__builtin_wcsncmp(L"abaa", L"abba", 1) == 0);
+  static_assert(__builtin_wcsncmp(L"abaa", L"abba", 0) == 0);
+  static_assert(__builtin_wcsncmp(0, 0, 0) == 0);
+  static_assert(__builtin_wcsncmp(L"abab\0banana", L"abab\0canada", 100) == 0);
+#if __WCHAR_WIDTH__ == 32
+  static_assert(__builtin_wcsncmp(L"a\x83838383", L"aa", 2) ==
+                (wchar_t)-1U >> 31);
+#endif
+
+  static_assert(__builtin_wcsncmp(kFoobar, kFoobazfoobar, 6) == -1);
+  static_assert(__builtin_wcsncmp(kFoobar, kFoobazfoobar, 7) == -1);
+  static_assert(__builtin_wcsncmp(kFoobar, kFoobazfoobar + 6, 6) == 0);
+  static_assert(__builtin_wcsncmp(kFoobar, kFoobazfoobar + 6, 7) == 0); // both-error {{not an integral constant}} \
+                                                                        // both-note {{dereferenced one-past-the-end}}
+}
+
 /// Copied from constant-expression-cxx11.cpp
 namespace strlen {
 constexpr const char *a = "foo\0quux";

@tbaederr tbaederr merged commit 0bc2c5b into llvm:main Mar 26, 2025
14 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented Mar 26, 2025

LLVM Buildbot has detected a new failure on builder lldb-aarch64-ubuntu running on linaro-lldb-aarch64-ubuntu while building clang at step 6 "test".

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

Here is the relevant piece of the build log for the reference
Step 6 (test) failure: build (failure)
...
PASS: lldb-api :: commands/disassemble/basic/TestFrameDisassemble.py (29 of 2110)
UNSUPPORTED: lldb-api :: commands/dwim-print/objc/TestDWIMPrintObjC.py (30 of 2110)
PASS: lldb-api :: commands/expression/calculator_mode/TestCalculatorMode.py (31 of 2110)
PASS: lldb-api :: commands/expression/anonymous-struct/TestCallUserAnonTypedef.py (32 of 2110)
PASS: lldb-api :: commands/expression/argument_passing_restrictions/TestArgumentPassingRestrictions.py (33 of 2110)
PASS: lldb-api :: commands/expression/bitfield_enums/TestBitfieldEnums.py (34 of 2110)
PASS: lldb-api :: api/listeners/TestListener.py (35 of 2110)
PASS: lldb-api :: commands/expression/call-function/TestCallBuiltinFunction.py (36 of 2110)
UNSUPPORTED: lldb-api :: commands/expression/call-throws/TestCallThatThrows.py (37 of 2110)
PASS: lldb-api :: commands/command/script/TestCommandScript.py (38 of 2110)
FAIL: lldb-api :: commands/expression/call-function/TestCallStdStringFunction.py (39 of 2110)
******************** TEST 'lldb-api :: commands/expression/call-function/TestCallStdStringFunction.py' FAILED ********************
Script:
--
/usr/bin/python3.10 /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./lib --env LLVM_INCLUDE_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/include --env LLVM_TOOLS_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin --arch aarch64 --build-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex --lldb-module-cache-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex/module-cache-lldb/lldb-api --clang-module-cache-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex/module-cache-clang/lldb-api --executable /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/lldb --compiler /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/clang --dsymutil /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/dsymutil --make /usr/bin/gmake --llvm-tools-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin --lldb-obj-root /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/tools/lldb --lldb-libs-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./lib /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/llvm-project/lldb/test/API/commands/expression/call-function -p TestCallStdStringFunction.py
--
Exit Code: -11

Command Output (stdout):
--
lldb version 21.0.0git (https://github.com/llvm/llvm-project.git revision 0bc2c5b2a4ca49011db27f7e8632d5d5ebc0ef5d)
  clang revision 0bc2c5b2a4ca49011db27f7e8632d5d5ebc0ef5d
  llvm revision 0bc2c5b2a4ca49011db27f7e8632d5d5ebc0ef5d
Skipping the following test categories: ['libc++', 'dsym', 'gmodules', 'debugserver', 'objc']

--
Command Output (stderr):
--
UNSUPPORTED: LLDB (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/clang-aarch64) :: test_with_dsym (TestCallStdStringFunction.ExprCommandCallFunctionTestCase) (test case does not fall in any category of interest for this run) 
PASS: LLDB (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/clang-aarch64) :: test_with_dwarf (TestCallStdStringFunction.ExprCommandCallFunctionTestCase)
PASS: LLDB (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/clang-aarch64) :: test_with_dwo (TestCallStdStringFunction.ExprCommandCallFunctionTestCase)
----------------------------------------------------------------------
Ran 3 tests in 1.014s

OK (skipped=1)

--

********************
PASS: lldb-api :: commands/expression/call-restarts/TestCallThatRestarts.py (40 of 2110)
PASS: lldb-api :: commands/expression/call-function/TestCallStopAndContinue.py (41 of 2110)
PASS: lldb-api :: commands/expression/cast_int_to_anonymous_enum/TestCastIntToAnonymousEnum.py (42 of 2110)
PASS: lldb-api :: commands/expression/call-function/TestCallUserDefinedFunction.py (43 of 2110)
UNSUPPORTED: lldb-api :: commands/expression/completion-crash-invalid-iterator/TestInvalidIteratorCompletionCrash.py (44 of 2110)
PASS: lldb-api :: commands/expression/class_template_specialization_empty_pack/TestClassTemplateSpecializationParametersHandling.py (45 of 2110)
PASS: lldb-api :: commands/expression/codegen-crash-import-def-arraytype-element/TestImportDefinitionArrayType.py (46 of 2110)
PASS: lldb-api :: commands/expression/codegen-crash-typedefdecl-not-in_declcontext/TestCodegenCrashTypedefDeclNotInDeclContext.py (47 of 2110)
PASS: lldb-api :: commands/expression/completion-crash-incomplete-record/TestCompletionCrashIncompleteRecord.py (48 of 2110)
UNSUPPORTED: lldb-api :: commands/expression/context-object-objc/TestContextObjectObjc.py (49 of 2110)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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