1717#include " clang/Basic/Builtins.h"
1818#include " clang/Basic/TargetBuiltins.h"
1919#include " clang/Basic/TargetInfo.h"
20+ #include " llvm/ADT/StringExtras.h"
2021#include " llvm/Support/SipHash.h"
2122
2223namespace clang {
@@ -1837,6 +1838,7 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
18371838 assert (Call->getNumArgs () == 3 );
18381839 unsigned ID = Func->getBuiltinID ();
18391840 Pointer DestPtr = getParam<Pointer>(Frame, 0 );
1841+ const ASTContext &ASTCtx = S.getASTContext ();
18401842 const Pointer &SrcPtr = getParam<Pointer>(Frame, 1 );
18411843 const APSInt &Size =
18421844 peekToAPSInt (S.Stk , *S.getContext ().classify (Call->getArg (2 )));
@@ -1857,34 +1859,55 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
18571859 Pointer DiagPtr = (SrcPtr.isZero () ? SrcPtr : DestPtr);
18581860 S.FFDiag (S.Current ->getSource (OpPC), diag::note_constexpr_memcpy_null)
18591861 << /* IsMove=*/ Move << /* IsWchar=*/ false << !SrcPtr.isZero ()
1860- << DiagPtr.toDiagnosticString (S. getASTContext () );
1862+ << DiagPtr.toDiagnosticString (ASTCtx );
18611863 return false ;
18621864 }
18631865
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 ();
18691876
1870- unsigned ElemSize =
1871- S.getASTContext ().getTypeSizeInChars (ElemType).getQuantity ();
1872- if (Size.urem (ElemSize) != 0 ) {
1877+ if (Size.urem (DestElemSize) != 0 ) {
18731878 S.FFDiag (S.Current ->getSource (OpPC),
18741879 diag::note_constexpr_memcpy_unsupported)
1875- << Move << /* IsWchar=*/ false << 0 << ElemType << Size << ElemSize;
1880+ << Move << /* IsWchar=*/ false << 0 << DestElemType << Size
1881+ << DestElemSize;
18761882 return false ;
18771883 }
18781884
18791885 QualType SrcElemType;
1880- if (SrcPtr.getFieldDesc ()->isArray ())
1886+ size_t RemainingSrcElems;
1887+ if (SrcPtr.getFieldDesc ()->isArray ()) {
18811888 SrcElemType = SrcPtr.getFieldDesc ()->getElemQualType ();
1882- else
1889+ RemainingSrcElems = (SrcPtr.getNumElems () - SrcPtr.getIndex ());
1890+ } else {
18831891 SrcElemType = SrcPtr.getType ();
1892+ RemainingSrcElems = 1 ;
1893+ }
1894+ unsigned SrcElemSize = ASTCtx.getTypeSizeInChars (SrcElemType).getQuantity ();
18841895
1885- if (!S. getASTContext (). hasSameUnqualifiedType (ElemType , SrcElemType)) {
1896+ if (!ASTCtx. hasSameUnqualifiedType (DestElemType , SrcElemType)) {
18861897 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 );
18881911 return false ;
18891912 }
18901913
@@ -1905,7 +1928,7 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
19051928 // As a last resort, reject dummy pointers.
19061929 if (DestPtr.isDummy () || SrcPtr.isDummy ())
19071930 return false ;
1908- assert (Size.getZExtValue () % ElemSize == 0 );
1931+ assert (Size.getZExtValue () % DestElemSize == 0 );
19091932 if (!DoMemcpy (S, OpPC, SrcPtr, DestPtr, Bytes (Size.getZExtValue ()).toBits ()))
19101933 return false ;
19111934
0 commit comments