diff options
author | Timm Baeder <tbaeder@redhat.com> | 2025-06-03 16:26:31 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-06-03 16:26:31 +0200 |
commit | 2e70da3fba14f9ff0b29f65fed174f075d94d9a4 (patch) | |
tree | b3d6e69b1cfc30930bc69980b354ff0073820dae /clang/lib/AST/ByteCode/Interp.cpp | |
parent | d9df71045441e02d33cd01fad203862c7efd637e (diff) | |
download | llvm-2e70da3fba14f9ff0b29f65fed174f075d94d9a4.zip llvm-2e70da3fba14f9ff0b29f65fed174f075d94d9a4.tar.gz llvm-2e70da3fba14f9ff0b29f65fed174f075d94d9a4.tar.bz2 |
[clang][bytecode] Partially address string literal uniqueness (#142555)
This still leaves the case of the
constexpr auto b3 = name1() == name1();
test from cxx20.cpp broken.
Diffstat (limited to 'clang/lib/AST/ByteCode/Interp.cpp')
-rw-r--r-- | clang/lib/AST/ByteCode/Interp.cpp | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index 4d1e5c6..db91e5e 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -2008,6 +2008,51 @@ bool DiagTypeid(InterpState &S, CodePtr OpPC) { return false; } +bool arePotentiallyOverlappingStringLiterals(const Pointer &LHS, + const Pointer &RHS) { + unsigned LHSOffset = LHS.getIndex(); + unsigned RHSOffset = RHS.getIndex(); + unsigned LHSLength = (LHS.getNumElems() - 1) * LHS.elemSize(); + unsigned RHSLength = (RHS.getNumElems() - 1) * RHS.elemSize(); + + StringRef LHSStr((const char *)LHS.atIndex(0).getRawAddress(), LHSLength); + StringRef RHSStr((const char *)RHS.atIndex(0).getRawAddress(), RHSLength); + int32_t IndexDiff = RHSOffset - LHSOffset; + if (IndexDiff < 0) { + if (static_cast<int32_t>(LHSLength) < -IndexDiff) + return false; + LHSStr = LHSStr.drop_front(-IndexDiff); + } else { + if (static_cast<int32_t>(RHSLength) < IndexDiff) + return false; + RHSStr = RHSStr.drop_front(IndexDiff); + } + + unsigned ShorterCharWidth; + StringRef Shorter; + StringRef Longer; + if (LHSLength < RHSLength) { + ShorterCharWidth = LHS.elemSize(); + Shorter = LHSStr; + Longer = RHSStr; + } else { + ShorterCharWidth = RHS.elemSize(); + Shorter = RHSStr; + Longer = LHSStr; + } + + // The null terminator isn't included in the string data, so check for it + // manually. If the longer string doesn't have a null terminator where the + // shorter string ends, they aren't potentially overlapping. + for (unsigned NullByte : llvm::seq(ShorterCharWidth)) { + if (Shorter.size() + NullByte >= Longer.size()) + break; + if (Longer[Shorter.size() + NullByte]) + return false; + } + return Shorter == Longer.take_front(Shorter.size()); +} + // https://github.com/llvm/llvm-project/issues/102513 #if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG) #pragma optimize("", off) |