@@ -148,6 +148,17 @@ static bool retPrimValue(InterpState &S, CodePtr OpPC,
148148#undef RET_CASE
149149}
150150
151+ static void diagnoseNonConstexprBuiltin (InterpState &S, CodePtr OpPC,
152+ unsigned ID) {
153+ auto Loc = S.Current ->getSource (OpPC);
154+ if (S.getLangOpts ().CPlusPlus11 )
155+ S.CCEDiag (Loc, diag::note_constexpr_invalid_function)
156+ << /* isConstexpr=*/ 0 << /* isConstructor=*/ 0
157+ << (" '" + S.getASTContext ().BuiltinInfo .getName (ID) + " '" ).str ();
158+ else
159+ S.CCEDiag (Loc, diag::note_invalid_subexpr_in_const_expr);
160+ }
161+
151162static bool interp__builtin_is_constant_evaluated (InterpState &S, CodePtr OpPC,
152163 const InterpFrame *Frame,
153164 const CallExpr *Call) {
@@ -181,10 +192,14 @@ static bool interp__builtin_is_constant_evaluated(InterpState &S, CodePtr OpPC,
181192
182193static bool interp__builtin_strcmp (InterpState &S, CodePtr OpPC,
183194 const InterpFrame *Frame,
184- const CallExpr *Call) {
195+ const Function *Func, const CallExpr *Call) {
196+ unsigned ID = Func->getBuiltinID ();
185197 const Pointer &A = getParam<Pointer>(Frame, 0 );
186198 const Pointer &B = getParam<Pointer>(Frame, 1 );
187199
200+ if (ID == Builtin::BIstrcmp)
201+ diagnoseNonConstexprBuiltin (S, OpPC, ID);
202+
188203 if (!CheckLive (S, OpPC, A, AK_Read) || !CheckLive (S, OpPC, B, AK_Read))
189204 return false ;
190205
@@ -224,9 +239,13 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
224239
225240static bool interp__builtin_strlen (InterpState &S, CodePtr OpPC,
226241 const InterpFrame *Frame,
227- const CallExpr *Call) {
242+ const Function *Func, const CallExpr *Call) {
243+ unsigned ID = Func->getBuiltinID ();
228244 const Pointer &StrPtr = getParam<Pointer>(Frame, 0 );
229245
246+ if (ID == Builtin::BIstrlen)
247+ diagnoseNonConstexprBuiltin (S, OpPC, ID);
248+
230249 if (!CheckArray (S, OpPC, StrPtr))
231250 return false ;
232251
@@ -1772,6 +1791,7 @@ static bool interp__builtin_elementwise_popcount(InterpState &S, CodePtr OpPC,
17721791 INT_TYPE_SWITCH_NO_BOOL (ElemT, {
17731792 Dst.atIndex (I).deref <T>() =
17741793 T::from (Arg.atIndex (I).deref <T>().toAPSInt ().popcount ());
1794+ Dst.atIndex (I).initialize ();
17751795 });
17761796 }
17771797
@@ -1781,21 +1801,36 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
17811801 const InterpFrame *Frame,
17821802 const Function *Func, const CallExpr *Call) {
17831803 assert (Call->getNumArgs () == 3 );
1804+ unsigned ID = Func->getBuiltinID ();
17841805 Pointer DestPtr = getParam<Pointer>(Frame, 0 );
17851806 const Pointer &SrcPtr = getParam<Pointer>(Frame, 1 );
17861807 const APSInt &Size =
17871808 peekToAPSInt (S.Stk , *S.getContext ().classify (Call->getArg (2 )));
17881809 assert (!Size.isSigned () && " memcpy and friends take an unsigned size" );
17891810
1790- if (DestPtr.isDummy () || SrcPtr.isDummy ())
1791- return false ;
1811+ if (ID == Builtin::BImemcpy || ID == Builtin::BImemmove)
1812+ diagnoseNonConstexprBuiltin (S, OpPC, ID);
1813+
1814+ bool Move = (ID == Builtin::BI__builtin_memmove || ID == Builtin::BImemmove);
17921815
17931816 // If the size is zero, we treat this as always being a valid no-op.
17941817 if (Size.isZero ()) {
17951818 S.Stk .push <Pointer>(DestPtr);
17961819 return true ;
17971820 }
17981821
1822+ if (SrcPtr.isZero () || DestPtr.isZero ()) {
1823+ Pointer DiagPtr = (SrcPtr.isZero () ? SrcPtr : DestPtr);
1824+ S.FFDiag (S.Current ->getSource (OpPC), diag::note_constexpr_memcpy_null)
1825+ << /* IsMove=*/ Move << /* IsWchar=*/ false << !SrcPtr.isZero ()
1826+ << DiagPtr.toDiagnosticString (S.getASTContext ());
1827+ return false ;
1828+ }
1829+
1830+ // As a last resort, reject dummy pointers.
1831+ if (DestPtr.isDummy () || SrcPtr.isDummy ())
1832+ return false ;
1833+
17991834 if (!DoBitCastPtr (S, OpPC, SrcPtr, DestPtr))
18001835 return false ;
18011836
@@ -1818,11 +1853,13 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
18181853 case Builtin::BI__assume:
18191854 break ;
18201855 case Builtin::BI__builtin_strcmp:
1821- if (!interp__builtin_strcmp (S, OpPC, Frame, Call))
1856+ case Builtin::BIstrcmp:
1857+ if (!interp__builtin_strcmp (S, OpPC, Frame, F, Call))
18221858 return false ;
18231859 break ;
18241860 case Builtin::BI__builtin_strlen:
1825- if (!interp__builtin_strlen (S, OpPC, Frame, Call))
1861+ case Builtin::BIstrlen:
1862+ if (!interp__builtin_strlen (S, OpPC, Frame, F, Call))
18261863 return false ;
18271864 break ;
18281865 case Builtin::BI__builtin_nan:
@@ -2263,6 +2300,9 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
22632300 break ;
22642301
22652302 case Builtin::BI__builtin_memcpy:
2303+ case Builtin::BImemcpy:
2304+ case Builtin::BI__builtin_memmove:
2305+ case Builtin::BImemmove:
22662306 if (!interp__builtin_memcpy (S, OpPC, Frame, F, Call))
22672307 return false ;
22682308 break ;
0 commit comments