diff --git a/clang/lib/AST/Interp/Integral.h b/clang/lib/AST/Interp/Integral.h index 8d5edbb5b764e..de588ab8c9f19 100644 --- a/clang/lib/AST/Interp/Integral.h +++ b/clang/lib/AST/Interp/Integral.h @@ -94,7 +94,6 @@ template class Integral final { explicit operator unsigned() const { return V; } explicit operator int64_t() const { return V; } explicit operator uint64_t() const { return V; } - explicit operator int32_t() const { return V; } APSInt toAPSInt() const { return APSInt(APInt(Bits, static_cast(V), Signed), !Signed); diff --git a/clang/lib/AST/Interp/InterpBuiltin.cpp b/clang/lib/AST/Interp/InterpBuiltin.cpp index b4e75593dc4a5..5277d05c82adf 100644 --- a/clang/lib/AST/Interp/InterpBuiltin.cpp +++ b/clang/lib/AST/Interp/InterpBuiltin.cpp @@ -32,65 +32,6 @@ static APSInt peekToAPSInt(InterpStack &Stk, PrimType T) { return R; } -/// Pushes \p Val to the stack, as a target-dependent 'int'. -static void pushInt(InterpState &S, int32_t Val) { - const TargetInfo &TI = S.getCtx().getTargetInfo(); - unsigned IntWidth = TI.getIntWidth(); - - if (IntWidth == 32) - S.Stk.push>(Integral<32, true>::from(Val)); - else if (IntWidth == 16) - S.Stk.push>(Integral<16, true>::from(Val)); - else - llvm_unreachable("Int isn't 16 or 32 bit?"); -} - -static bool retInt(InterpState &S, CodePtr OpPC, APValue &Result) { - const TargetInfo &TI = S.getCtx().getTargetInfo(); - unsigned IntWidth = TI.getIntWidth(); - - if (IntWidth == 32) - return Ret(S, OpPC, Result); - else if (IntWidth == 16) - return Ret(S, OpPC, Result); - llvm_unreachable("Int isn't 16 or 32 bit?"); -} - -static void pushSizeT(InterpState &S, uint64_t Val) { - const TargetInfo &TI = S.getCtx().getTargetInfo(); - unsigned SizeTWidth = TI.getTypeWidth(TI.getSizeType()); - - switch (SizeTWidth) { - case 64: - S.Stk.push>(Integral<64, false>::from(Val)); - break; - case 32: - S.Stk.push>(Integral<32, false>::from(Val)); - break; - case 16: - S.Stk.push>(Integral<16, false>::from(Val)); - break; - default: - llvm_unreachable("We don't handle this size_t size."); - } -} - -static bool retSizeT(InterpState &S, CodePtr OpPC, APValue &Result) { - const TargetInfo &TI = S.getCtx().getTargetInfo(); - unsigned SizeTWidth = TI.getTypeWidth(TI.getSizeType()); - - switch (SizeTWidth) { - case 64: - return Ret(S, OpPC, Result); - case 32: - return Ret(S, OpPC, Result); - case 16: - return Ret(S, OpPC, Result); - } - - llvm_unreachable("size_t isn't 64 or 32 bit?"); -} - static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC, const InterpFrame *Frame) { const Pointer &A = getParam(Frame, 0); @@ -126,35 +67,7 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC, break; } - pushInt(S, Result); - return true; -} - -static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC, - const InterpFrame *Frame) { - const Pointer &StrPtr = getParam(Frame, 0); - - if (!CheckArray(S, OpPC, StrPtr)) - return false; - - if (!CheckLive(S, OpPC, StrPtr, AK_Read)) - return false; - - assert(StrPtr.getFieldDesc()->isPrimitiveArray()); - - size_t Len = 0; - for (size_t I = StrPtr.getIndex();; ++I, ++Len) { - const Pointer &ElemPtr = StrPtr.atIndex(I); - - if (!CheckRange(S, OpPC, ElemPtr, AK_Read)) - return false; - - uint8_t Val = ElemPtr.deref(); - if (Val == 0) - break; - } - - pushSizeT(S, Len); + S.Stk.push>(Integral<32, true>::from(Result)); return true; } @@ -287,7 +200,7 @@ static bool interp__builtin_isnan(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *F) { const Floating &Arg = S.Stk.peek(); - pushInt(S, Arg.isNan()); + S.Stk.push>(Integral<32, true>::from(Arg.isNan())); return true; } @@ -298,9 +211,10 @@ static bool interp__builtin_isinf(InterpState &S, CodePtr OpPC, bool IsInf = Arg.isInf(); if (CheckSign) - pushInt(S, IsInf ? (Arg.isNegative() ? -1 : 1) : 0); + S.Stk.push>( + Integral<32, true>::from(IsInf ? (Arg.isNegative() ? -1 : 1) : 0)); else - pushInt(S, Arg.isInf()); + S.Stk.push>(Integral<32, true>::from(Arg.isInf())); return true; } @@ -309,7 +223,7 @@ static bool interp__builtin_isfinite(InterpState &S, CodePtr OpPC, const Function *F) { const Floating &Arg = S.Stk.peek(); - pushInt(S, Arg.isFinite()); + S.Stk.push>(Integral<32, true>::from(Arg.isFinite())); return true; } @@ -318,7 +232,7 @@ static bool interp__builtin_isnormal(InterpState &S, CodePtr OpPC, const Function *F) { const Floating &Arg = S.Stk.peek(); - pushInt(S, Arg.isNormal()); + S.Stk.push>(Integral<32, true>::from(Arg.isNormal())); return true; } @@ -335,12 +249,12 @@ static bool interp__builtin_isfpclass(InterpState &S, CodePtr OpPC, int32_t Result = static_cast((F.classify() & FPClassArg).getZExtValue()); - pushInt(S, Result); + S.Stk.push>(Integral<32, true>::from(Result)); return true; } -/// Five int values followed by one floating value. +/// Five int32 values followed by one floating value. static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func) { @@ -366,9 +280,8 @@ static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC, unsigned Offset = align(primSize(PT_Float)) + ((1 + (4 - Index)) * align(primSize(PT_Sint32))); - // FIXME: The size of the value we're peeking here is target-dependent. const Integral<32, true> &I = S.Stk.peek>(Offset); - pushInt(S, static_cast(I)); + S.Stk.push>(I); return true; } @@ -399,11 +312,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, return RetVoid(S, OpPC, Dummy); case Builtin::BI__builtin_strcmp: if (interp__builtin_strcmp(S, OpPC, Frame)) - return retInt(S, OpPC, Dummy); - break; - case Builtin::BI__builtin_strlen: - if (interp__builtin_strlen(S, OpPC, Frame)) - return retSizeT(S, OpPC, Dummy); + return Ret(S, OpPC, Dummy); break; case Builtin::BI__builtin_nan: case Builtin::BI__builtin_nanf: @@ -463,34 +372,34 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, case Builtin::BI__builtin_isnan: if (interp__builtin_isnan(S, OpPC, Frame, F)) - return retInt(S, OpPC, Dummy); + return Ret(S, OpPC, Dummy); break; case Builtin::BI__builtin_isinf: if (interp__builtin_isinf(S, OpPC, Frame, F, /*Sign=*/false)) - return retInt(S, OpPC, Dummy); + return Ret(S, OpPC, Dummy); break; case Builtin::BI__builtin_isinf_sign: if (interp__builtin_isinf(S, OpPC, Frame, F, /*Sign=*/true)) - return retInt(S, OpPC, Dummy); + return Ret(S, OpPC, Dummy); break; case Builtin::BI__builtin_isfinite: if (interp__builtin_isfinite(S, OpPC, Frame, F)) - return retInt(S, OpPC, Dummy); + return Ret(S, OpPC, Dummy); break; case Builtin::BI__builtin_isnormal: if (interp__builtin_isnormal(S, OpPC, Frame, F)) - return retInt(S, OpPC, Dummy); + return Ret(S, OpPC, Dummy); break; case Builtin::BI__builtin_isfpclass: if (interp__builtin_isfpclass(S, OpPC, Frame, F, Call)) - return retInt(S, OpPC, Dummy); + return Ret(S, OpPC, Dummy); break; case Builtin::BI__builtin_fpclassify: if (interp__builtin_fpclassify(S, OpPC, Frame, F)) - return retInt(S, OpPC, Dummy); + return Ret(S, OpPC, Dummy); break; case Builtin::BI__builtin_fabs: diff --git a/clang/test/AST/Interp/builtin-functions.cpp b/clang/test/AST/Interp/builtin-functions.cpp index 55ebab1122d58..85f10d7594d8c 100644 --- a/clang/test/AST/Interp/builtin-functions.cpp +++ b/clang/test/AST/Interp/builtin-functions.cpp @@ -1,11 +1,7 @@ -// RUN: %clang_cc1 -Wno-string-plus-int -fexperimental-new-constant-interpreter %s -verify -// RUN: %clang_cc1 -Wno-string-plus-int -fexperimental-new-constant-interpreter -triple i686 %s -verify -// RUN: %clang_cc1 -Wno-string-plus-int -verify=ref %s -Wno-constant-evaluated -// RUN: %clang_cc1 -std=c++20 -Wno-string-plus-int -fexperimental-new-constant-interpreter %s -verify -// RUN: %clang_cc1 -std=c++20 -Wno-string-plus-int -fexperimental-new-constant-interpreter -triple i686 %s -verify -// RUN: %clang_cc1 -std=c++20 -Wno-string-plus-int -verify=ref %s -Wno-constant-evaluated -// RUN: %clang_cc1 -triple avr -std=c++20 -Wno-string-plus-int -fexperimental-new-constant-interpreter %s -verify -// RUN: %clang_cc1 -triple avr -std=c++20 -Wno-string-plus-int -verify=ref %s -Wno-constant-evaluated +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter %s -verify +// RUN: %clang_cc1 -verify=ref %s -Wno-constant-evaluated +// RUN: %clang_cc1 -std=c++20 -fexperimental-new-constant-interpreter %s -verify +// RUN: %clang_cc1 -std=c++20 -verify=ref %s -Wno-constant-evaluated namespace strcmp { @@ -42,70 +38,6 @@ namespace strcmp { // ref-note {{dereferenced one-past-the-end}} } -/// Copied from constant-expression-cxx11.cpp -namespace strlen { -constexpr const char *a = "foo\0quux"; - constexpr char b[] = "foo\0quux"; - constexpr int f() { return 'u'; } - constexpr char c[] = { 'f', 'o', 'o', 0, 'q', f(), 'u', 'x', 0 }; - - static_assert(__builtin_strlen("foo") == 3, ""); - static_assert(__builtin_strlen("foo\0quux") == 3, ""); - static_assert(__builtin_strlen("foo\0quux" + 4) == 4, ""); - - constexpr bool check(const char *p) { - return __builtin_strlen(p) == 3 && - __builtin_strlen(p + 1) == 2 && - __builtin_strlen(p + 2) == 1 && - __builtin_strlen(p + 3) == 0 && - __builtin_strlen(p + 4) == 4 && - __builtin_strlen(p + 5) == 3 && - __builtin_strlen(p + 6) == 2 && - __builtin_strlen(p + 7) == 1 && - __builtin_strlen(p + 8) == 0; - } - - static_assert(check(a), ""); - static_assert(check(b), ""); - static_assert(check(c), ""); - - constexpr int over1 = __builtin_strlen(a + 9); // expected-error {{constant expression}} \ - // expected-note {{one-past-the-end}} \ - // expected-note {{in call to}} \ - // ref-error {{constant expression}} \ - // ref-note {{one-past-the-end}} - constexpr int over2 = __builtin_strlen(b + 9); // expected-error {{constant expression}} \ - // expected-note {{one-past-the-end}} \ - // expected-note {{in call to}} \ - // ref-error {{constant expression}} \ - // ref-note {{one-past-the-end}} - constexpr int over3 = __builtin_strlen(c + 9); // expected-error {{constant expression}} \ - // expected-note {{one-past-the-end}} \ - // expected-note {{in call to}} \ - // ref-error {{constant expression}} \ - // ref-note {{one-past-the-end}} - - constexpr int under1 = __builtin_strlen(a - 1); // expected-error {{constant expression}} \ - // expected-note {{cannot refer to element -1}} \ - // ref-error {{constant expression}} \ - // ref-note {{cannot refer to element -1}} - constexpr int under2 = __builtin_strlen(b - 1); // expected-error {{constant expression}} \ - // expected-note {{cannot refer to element -1}} \ - // ref-error {{constant expression}} \ - // ref-note {{cannot refer to element -1}} - constexpr int under3 = __builtin_strlen(c - 1); // expected-error {{constant expression}} \ - // expected-note {{cannot refer to element -1}} \ - // ref-error {{constant expression}} \ - // ref-note {{cannot refer to element -1}} - - constexpr char d[] = { 'f', 'o', 'o' }; // no nul terminator. - constexpr int bad = __builtin_strlen(d); // expected-error {{constant expression}} \ - // expected-note {{one-past-the-end}} \ - // expected-note {{in call to}} \ - // ref-error {{constant expression}} \ - // ref-note {{one-past-the-end}} -} - namespace nan { constexpr double NaN1 = __builtin_nan(""); @@ -164,12 +96,10 @@ namespace isfpclass { char isfpclass_pos_1 [!__builtin_isfpclass(1.0f, 0x0008) ? 1 : -1]; // fcNegNormal char isfpclass_pos_2 [__builtin_isfpclass(1.0L, 0x01F8) ? 1 : -1]; // fcFinite char isfpclass_pos_3 [!__builtin_isfpclass(1.0, 0x0003) ? 1 : -1]; // fcSNan|fcQNan -#ifndef __AVR__ char isfpclass_pdenorm_0[__builtin_isfpclass(1.0e-40f, 0x0080) ? 1 : -1]; // fcPosSubnormal char isfpclass_pdenorm_1[__builtin_isfpclass(1.0e-310, 0x01F8) ? 1 : -1]; // fcFinite char isfpclass_pdenorm_2[!__builtin_isfpclass(1.0e-40f, 0x003C) ? 1 : -1]; // fcNegative char isfpclass_pdenorm_3[!__builtin_isfpclass(1.0e-310, 0x0207) ? 1 : -1]; // ~fcFinite -#endif char isfpclass_pzero_0 [__builtin_isfpclass(0.0f, 0x0060) ? 1 : -1]; // fcZero char isfpclass_pzero_1 [__builtin_isfpclass(0.0, 0x01F8) ? 1 : -1]; // fcFinite char isfpclass_pzero_2 [!__builtin_isfpclass(0.0L, 0x0020) ? 1 : -1]; // fcNegZero @@ -179,11 +109,9 @@ namespace isfpclass { char isfpclass_nzero_2 [!__builtin_isfpclass(-0.0L, 0x0040) ? 1 : -1]; // fcPosZero char isfpclass_nzero_3 [!__builtin_isfpclass(-0.0, 0x0003) ? 1 : -1]; // fcNan char isfpclass_ndenorm_0[__builtin_isfpclass(-1.0e-40f, 0x0010) ? 1 : -1]; // fcNegSubnormal - char isfpclass_ndenorm_2[!__builtin_isfpclass(-1.0e-40f, 0x03C0) ? 1 : -1]; // fcPositive -#ifndef __AVR__ char isfpclass_ndenorm_1[__builtin_isfpclass(-1.0e-310, 0x01F8) ? 1 : -1]; // fcFinite + char isfpclass_ndenorm_2[!__builtin_isfpclass(-1.0e-40f, 0x03C0) ? 1 : -1]; // fcPositive char isfpclass_ndenorm_3[!__builtin_isfpclass(-1.0e-310, 0x0207) ? 1 : -1]; // ~fcFinite -#endif char isfpclass_neg_0 [__builtin_isfpclass(-1.0, 0x0008) ? 1 : -1]; // fcNegNormal char isfpclass_neg_1 [!__builtin_isfpclass(-1.0f, 0x00100) ? 1 : -1]; // fcPosNormal char isfpclass_neg_2 [__builtin_isfpclass(-1.0L, 0x01F8) ? 1 : -1]; // fcFinite @@ -208,11 +136,9 @@ namespace fpclassify { char classify_inf [__builtin_fpclassify(-1, +1, -1, -1, -1, __builtin_inf())]; char classify_neg_inf [__builtin_fpclassify(-1, +1, -1, -1, -1, -__builtin_inf())]; char classify_normal [__builtin_fpclassify(-1, -1, +1, -1, -1, 1.539)]; -#ifndef __AVR__ char classify_normal2 [__builtin_fpclassify(-1, -1, +1, -1, -1, 1e-307)]; char classify_denorm [__builtin_fpclassify(-1, -1, -1, +1, -1, 1e-308)]; char classify_denorm2 [__builtin_fpclassify(-1, -1, -1, +1, -1, -1e-308)]; -#endif char classify_zero [__builtin_fpclassify(-1, -1, -1, -1, +1, 0.0)]; char classify_neg_zero[__builtin_fpclassify(-1, -1, -1, -1, +1, -0.0)]; char classify_subnorm [__builtin_fpclassify(-1, -1, -1, +1, -1, 1.0e-38f)];