aboutsummaryrefslogtreecommitdiff
path: root/clang
diff options
context:
space:
mode:
authorTimm Baeder <tbaeder@redhat.com>2024-12-09 16:17:39 +0100
committerGitHub <noreply@github.com>2024-12-09 16:17:39 +0100
commitd17e51f306cb3522af7587bf1f3a2f4956ab3a19 (patch)
treefed5d3614a873ef6804e1550ff1a36de33bd065d /clang
parentd1cf86fe53bd89e107f8348a117754b59b4ffca5 (diff)
downloadllvm-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.cpp20
-rw-r--r--clang/test/AST/ByteCode/builtin-functions.cpp9
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