Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -383,6 +383,9 @@ template bool ByteCodeExprGen::VisitMemberExpr(const MemberExpr *E) { + if (DiscardResult) + return true; + // 'Base.Member' const Expr *Base = E->getBase(); const ValueDecl *Member = E->getMemberDecl(); @@ -1050,8 +1053,6 @@ if (Func->isFullyCompiled() && !Func->isConstexpr()) return false; - QualType ReturnType = E->getCallReturnType(Ctx.getASTContext()); - Optional T = classify(ReturnType); // Put arguments on the stack. for (const auto *Arg : E->arguments()) { if (!this->visit(Arg)) @@ -1061,7 +1062,18 @@ // In any case call the function. The return value will end up on the stack and // if the function has RVO, we already have the pointer on the stack to write // the result into. - return this->emitCall(Func, E); + if (!this->emitCall(Func, E)) + return false; + + QualType ReturnType = E->getCallReturnType(Ctx.getASTContext()); + if (DiscardResult && !ReturnType->isVoidType()) { + Optional T = classify(ReturnType); + if (T) + return this->emitPop(*T, E); + // TODO: This is a RVO function and we need to ignore the return value. + } + + return true; } else { assert(false && "We don't support non-FunctionDecl callees right now."); } @@ -1111,11 +1123,16 @@ template bool ByteCodeExprGen::VisitCXXThisExpr(const CXXThisExpr *E) { + if (DiscardResult) + return true; return this->emitThis(E); } template bool ByteCodeExprGen::VisitUnaryOperator(const UnaryOperator *E) { + if (DiscardResult) + return true; + const Expr *SubExpr = E->getSubExpr(); switch (E->getOpcode()) { Index: clang/test/AST/Interp/literals.cpp =================================================================== --- clang/test/AST/Interp/literals.cpp +++ clang/test/AST/Interp/literals.cpp @@ -279,6 +279,17 @@ static_assert((12 | true) == 13, ""); }; + +#if __cplusplus >= 201402L +constexpr bool IgnoredUnary() { + bool bo = true; + !bo; // expected-warning {{expression result unused}} \ + // ref-warning {{expression result unused}} + return bo; +} +static_assert(IgnoredUnary(), ""); +#endif + namespace floats { constexpr int i = 2; constexpr float f = 1.0f; Index: clang/test/AST/Interp/records.cpp =================================================================== --- clang/test/AST/Interp/records.cpp +++ clang/test/AST/Interp/records.cpp @@ -204,6 +204,26 @@ // expected-error {{static assertion failed}} \ // expected-note {{evaluates to '12 == 200'}} + +struct S { + int a = 0; + constexpr int get5() const { return 5; } + constexpr void fo() const { + this; // expected-warning {{expression result unused}} \ + // ref-warning {{expression result unused}} + this->a; // expected-warning {{expression result unused}} \ + // ref-warning {{expression result unused}} + get5(); + } + + constexpr int m() const { + fo(); + return 1; + } +}; +constexpr S s; +static_assert(s.m() == 1, ""); + namespace MI { class A { public: