17
17
#include " clang/Basic/Builtins.h"
18
18
#include " clang/Basic/TargetBuiltins.h"
19
19
#include " clang/Basic/TargetInfo.h"
20
+ #include " llvm/ADT/StringExtras.h"
20
21
#include " llvm/Support/SipHash.h"
21
22
22
23
namespace clang {
@@ -1837,6 +1838,7 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
1837
1838
assert (Call->getNumArgs () == 3 );
1838
1839
unsigned ID = Func->getBuiltinID ();
1839
1840
Pointer DestPtr = getParam<Pointer>(Frame, 0 );
1841
+ const ASTContext &ASTCtx = S.getASTContext ();
1840
1842
const Pointer &SrcPtr = getParam<Pointer>(Frame, 1 );
1841
1843
const APSInt &Size =
1842
1844
peekToAPSInt (S.Stk , *S.getContext ().classify (Call->getArg (2 )));
@@ -1857,34 +1859,55 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
1857
1859
Pointer DiagPtr = (SrcPtr.isZero () ? SrcPtr : DestPtr);
1858
1860
S.FFDiag (S.Current ->getSource (OpPC), diag::note_constexpr_memcpy_null)
1859
1861
<< /* IsMove=*/ Move << /* IsWchar=*/ false << !SrcPtr.isZero ()
1860
- << DiagPtr.toDiagnosticString (S. getASTContext () );
1862
+ << DiagPtr.toDiagnosticString (ASTCtx );
1861
1863
return false ;
1862
1864
}
1863
1865
1864
- QualType ElemType;
1865
- if (DestPtr.getFieldDesc ()->isArray ())
1866
- ElemType = DestPtr.getFieldDesc ()->getElemQualType ();
1867
- else
1868
- ElemType = DestPtr.getType ();
1866
+ QualType DestElemType;
1867
+ size_t RemainingDestElems;
1868
+ if (DestPtr.getFieldDesc ()->isArray ()) {
1869
+ DestElemType = DestPtr.getFieldDesc ()->getElemQualType ();
1870
+ RemainingDestElems = (DestPtr.getNumElems () - DestPtr.getIndex ());
1871
+ } else {
1872
+ DestElemType = DestPtr.getType ();
1873
+ RemainingDestElems = 1 ;
1874
+ }
1875
+ unsigned DestElemSize = ASTCtx.getTypeSizeInChars (DestElemType).getQuantity ();
1869
1876
1870
- unsigned ElemSize =
1871
- S.getASTContext ().getTypeSizeInChars (ElemType).getQuantity ();
1872
- if (Size.urem (ElemSize) != 0 ) {
1877
+ if (Size.urem (DestElemSize) != 0 ) {
1873
1878
S.FFDiag (S.Current ->getSource (OpPC),
1874
1879
diag::note_constexpr_memcpy_unsupported)
1875
- << Move << /* IsWchar=*/ false << 0 << ElemType << Size << ElemSize;
1880
+ << Move << /* IsWchar=*/ false << 0 << DestElemType << Size
1881
+ << DestElemSize;
1876
1882
return false ;
1877
1883
}
1878
1884
1879
1885
QualType SrcElemType;
1880
- if (SrcPtr.getFieldDesc ()->isArray ())
1886
+ size_t RemainingSrcElems;
1887
+ if (SrcPtr.getFieldDesc ()->isArray ()) {
1881
1888
SrcElemType = SrcPtr.getFieldDesc ()->getElemQualType ();
1882
- else
1889
+ RemainingSrcElems = (SrcPtr.getNumElems () - SrcPtr.getIndex ());
1890
+ } else {
1883
1891
SrcElemType = SrcPtr.getType ();
1892
+ RemainingSrcElems = 1 ;
1893
+ }
1894
+ unsigned SrcElemSize = ASTCtx.getTypeSizeInChars (SrcElemType).getQuantity ();
1884
1895
1885
- if (!S. getASTContext (). hasSameUnqualifiedType (ElemType , SrcElemType)) {
1896
+ if (!ASTCtx. hasSameUnqualifiedType (DestElemType , SrcElemType)) {
1886
1897
S.FFDiag (S.Current ->getSource (OpPC), diag::note_constexpr_memcpy_type_pun)
1887
- << Move << SrcElemType << ElemType;
1898
+ << Move << SrcElemType << DestElemType;
1899
+ return false ;
1900
+ }
1901
+
1902
+ // Check if we have enough elements to read from and write to/
1903
+ size_t RemainingDestBytes = RemainingDestElems * DestElemSize;
1904
+ size_t RemainingSrcBytes = RemainingSrcElems * SrcElemSize;
1905
+ if (Size.ugt (RemainingDestBytes) || Size.ugt (RemainingSrcBytes)) {
1906
+ APInt N = Size.udiv (DestElemSize);
1907
+ S.FFDiag (S.Current ->getSource (OpPC),
1908
+ diag::note_constexpr_memcpy_unsupported)
1909
+ << Move << /* IsWChar*/ false << (Size.ugt (RemainingSrcBytes) ? 1 : 2 )
1910
+ << DestElemType << toString (N, 10 , /* Signed=*/ false );
1888
1911
return false ;
1889
1912
}
1890
1913
@@ -1905,7 +1928,7 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
1905
1928
// As a last resort, reject dummy pointers.
1906
1929
if (DestPtr.isDummy () || SrcPtr.isDummy ())
1907
1930
return false ;
1908
- assert (Size.getZExtValue () % ElemSize == 0 );
1931
+ assert (Size.getZExtValue () % DestElemSize == 0 );
1909
1932
if (!DoMemcpy (S, OpPC, SrcPtr, DestPtr, Bytes (Size.getZExtValue ()).toBits ()))
1910
1933
return false ;
1911
1934
0 commit comments