Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -622,18 +622,18 @@ template bool ByteCodeExprGen::VisitMemberExpr(const MemberExpr *E) { - if (DiscardResult) - return true; - // 'Base.Member' const Expr *Base = E->getBase(); - const ValueDecl *Member = E->getMemberDecl(); + + if (DiscardResult) + return this->discard(Base); if (!this->visit(Base)) return false; // Base above gives us a pointer on the stack. // TODO: Implement non-FieldDecl members. + const ValueDecl *Member = E->getMemberDecl(); if (const auto *FD = dyn_cast(Member)) { const RecordDecl *RD = FD->getParent(); const Record *R = getRecord(RD); @@ -947,7 +947,13 @@ return false; if (!this->visitInitializer(SubExpr)) return false; - return this->emitInitGlobalTempComp(TempDecl, E); + + if (!this->emitInitGlobalTempComp(TempDecl, E)) + return false; + + if (DiscardResult) + return this->emitPopPtr(E); + return true; } // For everyhing else, use local variables. @@ -957,6 +963,9 @@ if (!this->visitInitializer(SubExpr)) return false; this->emitSetLocal(*SubExprT, *LocalIndex, E); + + if (DiscardResult) + return true; return this->emitGetPtrLocal(*LocalIndex, E); } } else { @@ -964,7 +973,14 @@ allocateLocal(SubExpr, /*IsExtended=*/true)) { if (!this->emitGetPtrLocal(*LocalIndex, E)) return false; - return this->visitInitializer(SubExpr); + + if (!this->visitInitializer(SubExpr)) + return false; + + if (DiscardResult) + return this->emitPopPtr(E); + + return true; } } return false; Index: clang/test/AST/Interp/literals.cpp =================================================================== --- clang/test/AST/Interp/literals.cpp +++ clang/test/AST/Interp/literals.cpp @@ -857,7 +857,7 @@ } static_assert(ignoredDecls() == 12, ""); -struct A{}; +struct A{ int a; }; constexpr int ignoredExprs() { (void)(1 / 2); A a; @@ -887,6 +887,19 @@ constexpr int Value = Comma(5); static_assert(Value == 8, ""); +/// Ignored MemberExprs need to still evaluate the Base +/// expr. +constexpr A callme(int &i) { + ++i; + return A{}; +} +constexpr int ignoredMemberExpr() { + int i = 0; + callme(i).a; // ref-warning {{result unused}} \ + // expected-warning {{result unused}} + return i; +} +static_assert(ignoredMemberExpr() == 1, ""); #endif namespace PredefinedExprs {