aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ByteCode/InterpBuiltin.cpp
diff options
context:
space:
mode:
authorNAKAMURA Takumi <geek4civic@gmail.com>2025-01-09 18:31:57 +0900
committerNAKAMURA Takumi <geek4civic@gmail.com>2025-01-09 18:33:27 +0900
commitdf025ebf872052c0761d44a3ef9b65e9675af8a8 (patch)
tree9b4e94583e2536546d6606270bcdf846c95e1ba2 /clang/lib/AST/ByteCode/InterpBuiltin.cpp
parent4428c9d0b1344179f85a72e183a44796976521e3 (diff)
parentbdcf47e4bcb92889665825654bb80a8bbe30379e (diff)
downloadllvm-users/chapuni/cov/single/loop.zip
llvm-users/chapuni/cov/single/loop.tar.gz
llvm-users/chapuni/cov/single/loop.tar.bz2
Merge branch 'users/chapuni/cov/single/base' into users/chapuni/cov/single/loopusers/chapuni/cov/single/loop
Conflicts: clang/lib/CodeGen/CoverageMappingGen.cpp
Diffstat (limited to 'clang/lib/AST/ByteCode/InterpBuiltin.cpp')
-rw-r--r--clang/lib/AST/ByteCode/InterpBuiltin.cpp71
1 files changed, 50 insertions, 21 deletions
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 2ae91fe..0d52083 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -17,6 +17,7 @@
#include "clang/Basic/Builtins.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/SipHash.h"
namespace clang {
@@ -154,7 +155,7 @@ static void diagnoseNonConstexprBuiltin(InterpState &S, CodePtr OpPC,
if (S.getLangOpts().CPlusPlus11)
S.CCEDiag(Loc, diag::note_constexpr_invalid_function)
<< /*isConstexpr=*/0 << /*isConstructor=*/0
- << ("'" + S.getASTContext().BuiltinInfo.getName(ID) + "'").str();
+ << S.getASTContext().BuiltinInfo.getQuotedName(ID);
else
S.CCEDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
}
@@ -1543,9 +1544,10 @@ static bool interp__builtin_constant_p(InterpState &S, CodePtr OpPC,
if (Res.isInvalid()) {
C.cleanup();
Stk.clear();
+ return returnInt(false);
}
- if (!Res.isInvalid() && !Res.empty()) {
+ if (!Res.empty()) {
const APValue &LV = Res.toAPValue();
if (LV.isLValue()) {
APValue::LValueBase Base = LV.getLValueBase();
@@ -1837,6 +1839,7 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
assert(Call->getNumArgs() == 3);
unsigned ID = Func->getBuiltinID();
Pointer DestPtr = getParam<Pointer>(Frame, 0);
+ const ASTContext &ASTCtx = S.getASTContext();
const Pointer &SrcPtr = getParam<Pointer>(Frame, 1);
const APSInt &Size =
peekToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(2)));
@@ -1857,34 +1860,63 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
Pointer DiagPtr = (SrcPtr.isZero() ? SrcPtr : DestPtr);
S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_null)
<< /*IsMove=*/Move << /*IsWchar=*/false << !SrcPtr.isZero()
- << DiagPtr.toDiagnosticString(S.getASTContext());
+ << DiagPtr.toDiagnosticString(ASTCtx);
return false;
}
- QualType ElemType;
- if (DestPtr.getFieldDesc()->isArray())
- ElemType = DestPtr.getFieldDesc()->getElemQualType();
- else
- ElemType = DestPtr.getType();
+ // Can't read from dummy pointers.
+ if (DestPtr.isDummy() || SrcPtr.isDummy())
+ return false;
- unsigned ElemSize =
- S.getASTContext().getTypeSizeInChars(ElemType).getQuantity();
- if (Size.urem(ElemSize) != 0) {
+ QualType DestElemType;
+ size_t RemainingDestElems;
+ if (DestPtr.getFieldDesc()->isArray()) {
+ DestElemType = DestPtr.getFieldDesc()->getElemQualType();
+ RemainingDestElems = DestPtr.isUnknownSizeArray()
+ ? 0
+ : (DestPtr.getNumElems() - DestPtr.getIndex());
+ } else {
+ DestElemType = DestPtr.getType();
+ RemainingDestElems = 1;
+ }
+ unsigned DestElemSize = ASTCtx.getTypeSizeInChars(DestElemType).getQuantity();
+
+ if (Size.urem(DestElemSize) != 0) {
S.FFDiag(S.Current->getSource(OpPC),
diag::note_constexpr_memcpy_unsupported)
- << Move << /*IsWchar=*/false << 0 << ElemType << Size << ElemSize;
+ << Move << /*IsWchar=*/false << 0 << DestElemType << Size
+ << DestElemSize;
return false;
}
QualType SrcElemType;
- if (SrcPtr.getFieldDesc()->isArray())
+ size_t RemainingSrcElems;
+ if (SrcPtr.getFieldDesc()->isArray()) {
SrcElemType = SrcPtr.getFieldDesc()->getElemQualType();
- else
+ RemainingSrcElems = SrcPtr.isUnknownSizeArray()
+ ? 0
+ : (SrcPtr.getNumElems() - SrcPtr.getIndex());
+ } else {
SrcElemType = SrcPtr.getType();
+ RemainingSrcElems = 1;
+ }
+ unsigned SrcElemSize = ASTCtx.getTypeSizeInChars(SrcElemType).getQuantity();
- if (!S.getASTContext().hasSameUnqualifiedType(ElemType, SrcElemType)) {
+ if (!ASTCtx.hasSameUnqualifiedType(DestElemType, SrcElemType)) {
S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_type_pun)
- << Move << SrcElemType << ElemType;
+ << Move << SrcElemType << DestElemType;
+ return false;
+ }
+
+ // Check if we have enough elements to read from and write to/
+ size_t RemainingDestBytes = RemainingDestElems * DestElemSize;
+ size_t RemainingSrcBytes = RemainingSrcElems * SrcElemSize;
+ if (Size.ugt(RemainingDestBytes) || Size.ugt(RemainingSrcBytes)) {
+ APInt N = Size.udiv(DestElemSize);
+ S.FFDiag(S.Current->getSource(OpPC),
+ diag::note_constexpr_memcpy_unsupported)
+ << Move << /*IsWChar*/ false << (Size.ugt(RemainingSrcBytes) ? 1 : 2)
+ << DestElemType << toString(N, 10, /*Signed=*/false);
return false;
}
@@ -1902,10 +1934,7 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
}
}
- // As a last resort, reject dummy pointers.
- if (DestPtr.isDummy() || SrcPtr.isDummy())
- return false;
- assert(Size.getZExtValue() % ElemSize == 0);
+ assert(Size.getZExtValue() % DestElemSize == 0);
if (!DoMemcpy(S, OpPC, SrcPtr, DestPtr, Bytes(Size.getZExtValue()).toBits()))
return false;
@@ -1948,7 +1977,7 @@ static bool interp__builtin_memcmp(InterpState &S, CodePtr OpPC,
!isOneByteCharacterType(PtrB.getType()))) {
S.FFDiag(S.Current->getSource(OpPC),
diag::note_constexpr_memcmp_unsupported)
- << ("'" + ASTCtx.BuiltinInfo.getName(ID) + "'").str() << PtrA.getType()
+ << ASTCtx.BuiltinInfo.getQuotedName(ID) << PtrA.getType()
<< PtrB.getType();
return false;
}