diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -1441,9 +1441,9 @@ } template -static inline bool IncDecPtrHelper(InterpState &S, CodePtr OpPC) { +static inline bool IncDecPtrHelper(InterpState &S, CodePtr OpPC, + const Pointer &Ptr) { using OneT = Integral<8, false>; - const Pointer &Ptr = S.Stk.pop(); // Get the current value on the stack. S.Stk.push(Ptr.deref()); @@ -1460,11 +1460,21 @@ } static inline bool IncPtr(InterpState &S, CodePtr OpPC) { - return IncDecPtrHelper(S, OpPC); + const Pointer &Ptr = S.Stk.pop(); + + if (!CheckInitialized(S, OpPC, Ptr, AK_Increment)) + return false; + + return IncDecPtrHelper(S, OpPC, Ptr); } static inline bool DecPtr(InterpState &S, CodePtr OpPC) { - return IncDecPtrHelper(S, OpPC); + const Pointer &Ptr = S.Stk.pop(); + + if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement)) + return false; + + return IncDecPtrHelper(S, OpPC, Ptr); } /// 1) Pops a Pointer from the stack. diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp --- a/clang/test/AST/Interp/literals.cpp +++ b/clang/test/AST/Interp/literals.cpp @@ -509,36 +509,72 @@ } static_assert(incBool(), ""); - template + /// FIXME: The diagnostics for pre-inc/dec of pointers doesn't match the + /// current interpreter. But they are stil OK. + template constexpr int uninit() { T a; - if constexpr (Inc) - ++a; // ref-note 2{{increment of uninitialized}} \ - // expected-note 2{{increment of uninitialized}} - else - --a; // ref-note 2{{decrement of uninitialized}} \ - // expected-note 2{{decrement of uninitialized}} + if constexpr (Inc) { + if (Pre) + ++a; // ref-note 3{{increment of uninitialized}} \ + // expected-note 2{{increment of uninitialized}} \ + // expected-note {{read of uninitialized}} + else + a++; // ref-note 2{{increment of uninitialized}} \ + // expected-note 2{{increment of uninitialized}} + } else { + if (Pre) + --a; // ref-note 3{{decrement of uninitialized}} \ + // expected-note 2{{decrement of uninitialized}} \ + // expected-note {{read of uninitialized}} + else + a--; // ref-note 2{{decrement of uninitialized}} \ + // expected-note 2{{decrement of uninitialized}} + } return 1; } - static_assert(uninit(), ""); // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to 'uninit()'}} \ - // expected-error {{not an integral constant expression}} \ - // expected-note {{in call to 'uninit()'}} - - static_assert(uninit(), ""); // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to 'uninit()'}} \ - // expected-error {{not an integral constant expression}} \ - // expected-note {{in call to 'uninit()'}} - - static_assert(uninit(), ""); // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to 'uninit()'}} \ - // expected-error {{not an integral constant expression}} \ - // expected-note {{in call to 'uninit()'}} - - static_assert(uninit(), ""); // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to 'uninit()'}} \ - // expected-error {{not an integral constant expression}} \ - // expected-note {{in call to 'uninit()'}} + static_assert(uninit(), ""); // ref-error {{not an integral constant expression}} \ + // ref-note {{in call to 'uninit()'}} \ + // expected-error {{not an integral constant expression}} \ + // expected-note {{in call to 'uninit()'}} + static_assert(uninit(), ""); // ref-error {{not an integral constant expression}} \ + // ref-note {{in call to 'uninit()'}} \ + // expected-error {{not an integral constant expression}} \ + // expected-note {{in call to 'uninit()'}} + + static_assert(uninit(), ""); // ref-error {{not an integral constant expression}} \ + // ref-note {{in call to 'uninit()'}} \ + // expected-error {{not an integral constant expression}} \ + // expected-note {{in call to 'uninit()'}} + static_assert(uninit(), ""); // ref-error {{not an integral constant expression}} \ + // ref-note {{in call to 'uninit()'}} \ + // expected-error {{not an integral constant expression}} \ + // expected-note {{in call to 'uninit()'}} + static_assert(uninit(), ""); // ref-error {{not an integral constant expression}} \ + // ref-note {{in call to 'uninit()'}} \ + // expected-error {{not an integral constant expression}} \ + // expected-note {{in call to 'uninit()'}} + static_assert(uninit(), ""); // ref-error {{not an integral constant expression}} \ + // ref-note {{in call to 'uninit()'}} \ + // expected-error {{not an integral constant expression}} \ + // expected-note {{in call to 'uninit()'}} + + static_assert(uninit(), ""); // ref-error {{not an integral constant expression}} \ + // ref-note {{in call to 'uninit()'}} \ + // expected-error {{not an integral constant expression}} \ + // expected-note {{in call to 'uninit()'}} + static_assert(uninit(), ""); // ref-error {{not an integral constant expression}} \ + // ref-note {{in call to 'uninit()'}} \ + // expected-error {{not an integral constant expression}} \ + // expected-note {{in call to 'uninit()'}} + static_assert(uninit(), ""); // ref-error {{not an integral constant expression}} \ + // ref-note {{in call to 'uninit()'}} \ + // expected-error {{not an integral constant expression}} \ + // expected-note {{in call to 'uninit()'}} + static_assert(uninit(), ""); // ref-error {{not an integral constant expression}} \ + // ref-note {{in call to 'uninit()'}} \ + // expected-error {{not an integral constant expression}} \ + // expected-note {{in call to 'uninit()'}} constexpr int OverFlow() { // ref-error {{never produces a constant expression}} \ // expected-error {{never produces a constant expression}}