Index: clang/lib/AST/Interp/EvalEmitter.cpp =================================================================== --- clang/lib/AST/Interp/EvalEmitter.cpp +++ clang/lib/AST/Interp/EvalEmitter.cpp @@ -102,14 +102,6 @@ return ReturnValue(S.Stk.pop(), Result); } -template -bool EvalEmitter::emitCall(const Function *Func, const SourceInfo &Info) { - - S.Current = new InterpFrame(S, Func, {}); - // Result of call will be on the stack and needs to be handled by the caller. - return Interpret(S, Result); -} - bool EvalEmitter::emitCallVoid(const Function *Func, const SourceInfo &Info) { APValue VoidResult; InterpFrame *before = S.Current; Index: clang/lib/AST/Interp/Function.cpp =================================================================== --- clang/lib/AST/Interp/Function.cpp +++ clang/lib/AST/Interp/Function.cpp @@ -30,11 +30,13 @@ } SourceInfo Function::getSource(CodePtr PC) const { + assert(PC >= getCodeBegin() && "PC does not belong to this function"); + assert(PC <= getCodeEnd() && "PC Does not belong to this function"); unsigned Offset = PC - getCodeBegin(); using Elem = std::pair; auto It = llvm::lower_bound(SrcMap, Elem{Offset, {}}, llvm::less_first()); - if (It == SrcMap.end() || It->first != Offset) - llvm::report_fatal_error("missing source location"); + assert(It != SrcMap.end()); + It--; // We want the offset *before* the given one. return It->second; } Index: clang/lib/AST/Interp/Interp.h =================================================================== --- clang/lib/AST/Interp/Interp.h +++ clang/lib/AST/Interp/Interp.h @@ -119,6 +119,9 @@ template inline bool IsTrue(const T &V) { return !V.isZero(); } +/// Interpreter entry point. +bool Interpret(InterpState &S, APValue &Result); + //===----------------------------------------------------------------------===// // Add, Sub, Mul //===----------------------------------------------------------------------===// @@ -1150,6 +1153,38 @@ } } +template ::T> +static bool Call(InterpState &S, CodePtr &PC, const Function *Func) { + auto *NewFrame = new InterpFrame(S, Func, PC); + if (Func->hasThisPointer()) { + if (!CheckInvoke(S, PC, NewFrame->getThis())) { + NewFrame->popArgs(); + delete NewFrame; + return false; + } + // TODO: CheckCallable + } + + InterpFrame *FrameBefore = S.Current; + S.Current = NewFrame; + + APValue CallResult; + // Note that we cannot assert(CallResult.hasValue()) here since + // Ret() above only sets the APValue if the curent frame doesn't + // have a caller set. + if (Interpret(S, CallResult)) { + assert(S.Current == FrameBefore); + return true; + } + + // Interpreting the function failed somehow. Reset to + // previous state. + NewFrame->popArgs(); + delete NewFrame; + S.Current = FrameBefore; + return false; +} + //===----------------------------------------------------------------------===// // Read opcode arguments //===----------------------------------------------------------------------===// @@ -1163,9 +1198,6 @@ } } -/// Interpreter entry point. -bool Interpret(InterpState &S, APValue &Result); - } // namespace interp } // namespace clang Index: clang/lib/AST/Interp/Interp.cpp =================================================================== --- clang/lib/AST/Interp/Interp.cpp +++ clang/lib/AST/Interp/Interp.cpp @@ -53,16 +53,6 @@ return true; } -template ::T> -static bool Call(InterpState &S, CodePtr &PC, const Function *Func) { - S.Current = new InterpFrame(S, const_cast(Func), PC); - APValue CallResult; - // Note that we cannot assert(CallResult.hasValue()) here since - // Ret() above only sets the APValue if the curent frame doesn't - // have a caller set. - return Interpret(S, CallResult); -} - static bool CallVoid(InterpState &S, CodePtr &PC, const Function *Func) { APValue VoidResult; S.Current = new InterpFrame(S, const_cast(Func), PC); Index: clang/lib/AST/Interp/Opcodes.td =================================================================== --- clang/lib/AST/Interp/Opcodes.td +++ clang/lib/AST/Interp/Opcodes.td @@ -168,7 +168,6 @@ let Args = [ArgFunction]; let Types = [AllTypeClass]; let ChangesPC = 1; - let HasCustomEval = 1; let HasGroup = 1; } Index: clang/test/AST/Interp/records.cpp =================================================================== --- clang/test/AST/Interp/records.cpp +++ clang/test/AST/Interp/records.cpp @@ -144,11 +144,14 @@ constexpr int foo() { // ref-error {{never produces a constant expression}} S *s = nullptr; - return s->get12(); // ref-note 2{{member call on dereferenced null pointer}} + return s->get12(); // ref-note 2{{member call on dereferenced null pointer}} \ + // expected-note {{member call on dereferenced null pointer}} + } - // FIXME: The new interpreter doesn't reject this currently. static_assert(foo() == 12, ""); // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to 'foo()'}} + // ref-note {{in call to 'foo()'}} \ + // expected-error {{not an integral constant expression}} \ + // expected-note {{in call to 'foo()'}} }; struct FourBoolPairs {