diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -562,18 +562,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); 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 @@ -876,7 +876,7 @@ } static_assert(ignoredDecls() == 12, ""); -struct A{}; +struct A{ int a; }; constexpr int ignoredExprs() { (void)(1 / 2); A a; @@ -908,6 +908,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 {