This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. Closed by commit rGcc79ddb52c31: [clang][Interp] Check instance pointers before calling functions on them (authored by tbaeder).
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D135513/new/ https://reviews.llvm.org/D135513 Files: clang/lib/AST/Interp/EvalEmitter.cpp clang/lib/AST/Interp/Function.cpp clang/lib/AST/Interp/Interp.cpp clang/lib/AST/Interp/Interp.h clang/lib/AST/Interp/Opcodes.td clang/test/AST/Interp/records.cpp
Index: clang/test/AST/Interp/records.cpp =================================================================== --- clang/test/AST/Interp/records.cpp +++ clang/test/AST/Interp/records.cpp @@ -156,11 +156,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 { Index: clang/lib/AST/Interp/Opcodes.td =================================================================== --- clang/lib/AST/Interp/Opcodes.td +++ clang/lib/AST/Interp/Opcodes.td @@ -162,7 +162,6 @@ let Args = [ArgFunction]; let Types = [AllTypeClass]; let ChangesPC = 1; - let HasCustomEval = 1; let HasGroup = 1; } Index: clang/lib/AST/Interp/Interp.h =================================================================== --- clang/lib/AST/Interp/Interp.h +++ clang/lib/AST/Interp/Interp.h @@ -114,6 +114,9 @@ template <typename T> inline bool IsTrue(const T &V) { return !V.isZero(); } +/// Interpreter entry point. +bool Interpret(InterpState &S, APValue &Result); + //===----------------------------------------------------------------------===// // Add, Sub, Mul //===----------------------------------------------------------------------===// @@ -1103,6 +1106,35 @@ return true; } +template <PrimType Name, class T = typename PrimConv<Name>::T> +static bool Call(InterpState &S, CodePtr &PC, const Function *Func) { + auto NewFrame = std::make_unique<InterpFrame>(S, Func, PC); + if (Func->hasThisPointer()) { + if (!CheckInvoke(S, PC, NewFrame->getThis())) { + return false; + } + // TODO: CheckCallable + } + + InterpFrame *FrameBefore = S.Current; + S.Current = NewFrame.get(); + + 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)) { + NewFrame.release(); // Frame was delete'd already. + assert(S.Current == FrameBefore); + return true; + } + + // Interpreting the function failed somehow. Reset to + // previous state. + S.Current = FrameBefore; + return false; +} + //===----------------------------------------------------------------------===// // Read opcode arguments //===----------------------------------------------------------------------===// @@ -1116,9 +1148,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 <PrimType Name, class T = typename PrimConv<Name>::T> -static bool Call(InterpState &S, CodePtr &PC, const Function *Func) { - S.Current = new InterpFrame(S, const_cast<Function *>(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<Function *>(Func), PC); Index: clang/lib/AST/Interp/Function.cpp =================================================================== --- clang/lib/AST/Interp/Function.cpp +++ clang/lib/AST/Interp/Function.cpp @@ -30,11 +30,12 @@ } 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<unsigned, SourceInfo>; 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()); return It->second; } 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<T>(S.Stk.pop<T>(), Result); } -template <PrimType OpType> -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;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits