diff options
author | Timm Baeder <tbaeder@redhat.com> | 2024-12-09 16:17:39 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-12-09 16:17:39 +0100 |
commit | d17e51f306cb3522af7587bf1f3a2f4956ab3a19 (patch) | |
tree | fed5d3614a873ef6804e1550ff1a36de33bd065d /clang | |
parent | d1cf86fe53bd89e107f8348a117754b59b4ffca5 (diff) | |
download | llvm-d17e51f306cb3522af7587bf1f3a2f4956ab3a19.zip llvm-d17e51f306cb3522af7587bf1f3a2f4956ab3a19.tar.gz llvm-d17e51f306cb3522af7587bf1f3a2f4956ab3a19.tar.bz2 |
[clang][bytecode] Handle __builtin_strncmp (#119208)
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/AST/ByteCode/InterpBuiltin.cpp | 20 | ||||
-rw-r--r-- | clang/test/AST/ByteCode/builtin-functions.cpp | 9 |
2 files changed, 27 insertions, 2 deletions
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index f816373..9f2e64b 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -197,9 +197,19 @@ 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) + if (ID == Builtin::BIstrcmp || ID == Builtin::BIstrncmp) diagnoseNonConstexprBuiltin(S, OpPC, ID); + uint64_t Limit = ~static_cast<uint64_t>(0); + if (ID == Builtin::BIstrncmp || ID == Builtin::BI__builtin_strncmp) + Limit = peekToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(2))) + .getZExtValue(); + + if (Limit == 0) { + pushInteger(S, 0, Call->getType()); + return true; + } + if (!CheckLive(S, OpPC, A, AK_Read) || !CheckLive(S, OpPC, B, AK_Read)) return false; @@ -212,7 +222,11 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC, unsigned IndexA = A.getIndex(); unsigned IndexB = B.getIndex(); int32_t Result = 0; - for (;; ++IndexA, ++IndexB) { + uint64_t Steps = 0; + for (;; ++IndexA, ++IndexB, ++Steps) { + + if (Steps >= Limit) + break; const Pointer &PA = A.atIndex(IndexA); const Pointer &PB = B.atIndex(IndexB); if (!CheckRange(S, OpPC, PA, AK_Read) || @@ -1873,6 +1887,8 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, break; case Builtin::BI__builtin_strcmp: case Builtin::BIstrcmp: + case Builtin::BI__builtin_strncmp: + case Builtin::BIstrncmp: 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 4c21496..bd453d6 100644 --- a/clang/test/AST/ByteCode/builtin-functions.cpp +++ b/clang/test/AST/ByteCode/builtin-functions.cpp @@ -51,6 +51,15 @@ namespace strcmp { return __builtin_strcmp(buffer, "mutable") == 0; } static_assert(char_memchr_mutable(), ""); + + static_assert(__builtin_strncmp("abaa", "abba", 5) == -1); + static_assert(__builtin_strncmp("abaa", "abba", 4) == -1); + static_assert(__builtin_strncmp("abaa", "abba", 3) == -1); + static_assert(__builtin_strncmp("abaa", "abba", 2) == 0); + static_assert(__builtin_strncmp("abaa", "abba", 1) == 0); + static_assert(__builtin_strncmp("abaa", "abba", 0) == 0); + static_assert(__builtin_strncmp(0, 0, 0) == 0); + static_assert(__builtin_strncmp("abab\0banana", "abab\0canada", 100) == 0); } /// Copied from constant-expression-cxx11.cpp |