r350404 - Refactor the way we handle diagnosing unused expression results.

Aaron Ballman via cfe-commits cfe-commits at lists.llvm.org
Sun Jan 6 08:44:38 PST 2019


On Sun, Jan 6, 2019 at 10:58 AM Nico Weber <thakis at chromium.org> wrote:
>
> On Sat, Jan 5, 2019 at 10:16 AM Aaron Ballman <aaron at aaronballman.com> wrote:
>>
>> On Fri, Jan 4, 2019 at 8:41 PM Richard Smith <richard at metafoo.co.uk> wrote:
>> >
>> > On Fri, 4 Jan 2019 at 17:33, Nico Weber via cfe-commits <cfe-commits at lists.llvm.org> wrote:
>> >>
>> >> Nice, this is finding bugs: https://bugs.chromium.org/p/chromium/issues/detail?id=919262
>> >>
>> >> However, I noticed that for that case, the same warning is printed twice:
>> >>
>> >> ../../third_party/crashpad/crashpad/util/win/process_info.cc(227,36):  error: expression result unused [-Werror,-Wunused-value]
>> >>       NTSTATUS_LOG(ERROR, status), "NtQueryInformationProcess";
>> >>                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~
>> >> ../../third_party/crashpad/crashpad/util/win/process_info.cc(227,36):  error: expression result unused [-Werror,-Wunused-value]
>> >>       NTSTATUS_LOG(ERROR, status), "NtQueryInformationProcess";
>> >>
>> >>
>> >> Is that expected?
>>
>> Yes and no. It's not unexpected, but it's not super helpful either. As
>> Richard points out below, this happens because of template
>> instantiation.
>>
>> > The first diagnostic appears when parsing the template, the second one appears when instantiating it. In the complete diagnostic output:
>> >
>> > ../../third_party/crashpad/crashpad/util/win/process_info.cc(227,36):  error: expression result unused [-Werror,-Wunused-value]
>> >       NTSTATUS_LOG(ERROR, status), "NtQueryInformationProcess";
>> >                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~
>> >
>> > ../../third_party/crashpad/crashpad/util/win/process_info.cc(227,36):  error: expression result unused [-Werror,-Wunused-value]
>> >       NTSTATUS_LOG(ERROR, status), "NtQueryInformationProcess";
>> >                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~
>> > ../../third_party/crashpad/crashpad/util/win/process_info.cc(531,17):  note: in instantiation of function template specialization 'crashpad::GetProcessBasicInformation<crashpad::process_types::internal::Traits32>' requested here
>> >   bool result = GetProcessBasicInformation<process_types::internal::Traits32>(
>> >                 ^
>> >
>> > It'd be nice to suppress the diagnostic during instantiation if it appeared during the initial parse (generally, not with something specific to this warning).
>>
>> Agreed, though I don't have the time to work on that currently.
>> Hopefully the behavior here isn't too onerous for Chromium (or other
>> projects)?
>
>
> It wasn't a problem for us, no. The warning found a bug, we fixed the bug, everyone's happy. Just thought I'd mention the diag looks strange; thanks for the explanation (and the warning improvement) :-)

I'm glad to hear the refactoring is catching more issues, that's
great! I'm also glad the template instantiation stuff isn't causing
too much of a problem for you.

~Aaron

>
>>
>>
>> ~Aaron
>>
>> >
>> >> Code is here:
>> >> https://cs.chromium.org/chromium/src/third_party/crashpad/crashpad/util/win/process_info.cc?q=crashpad/util/win/process_info.cc&sq=package:chromium&g=0&l=227
>> >> https://cs.chromium.org/chromium/src/third_party/crashpad/crashpad/util/win/ntstatus_logging.h?type=cs&q=NTSTATUS_LOG&sq=package:chromium&g=0&l=63
>> >>
>> >>
>> >> On Fri, Jan 4, 2019 at 12:01 PM Aaron Ballman via cfe-commits <cfe-commits at lists.llvm.org> wrote:
>> >>>
>> >>> Author: aaronballman
>> >>> Date: Fri Jan  4 08:58:14 2019
>> >>> New Revision: 350404
>> >>>
>> >>> URL: http://llvm.org/viewvc/llvm-project?rev=350404&view=rev
>> >>> Log:
>> >>> Refactor the way we handle diagnosing unused expression results.
>> >>>
>> >>> Rather than sprinkle calls to DiagnoseUnusedExprResult() around in places where we want diagnostics, we now diagnose unused expression statements and full expressions in a more generic way when acting on the final expression statement. This results in more appropriate diagnostics for [[nodiscard]] where we were previously lacking them, such as when the body of a for loop is not a compound statement.
>> >>>
>> >>> This patch fixes PR39837.
>> >>>
>> >>> Modified:
>> >>>     cfe/trunk/include/clang/Parse/Parser.h
>> >>>     cfe/trunk/include/clang/Sema/Sema.h
>> >>>     cfe/trunk/lib/Parse/ParseObjc.cpp
>> >>>     cfe/trunk/lib/Parse/ParseOpenMP.cpp
>> >>>     cfe/trunk/lib/Parse/ParseStmt.cpp
>> >>>     cfe/trunk/lib/Sema/SemaCoroutine.cpp
>> >>>     cfe/trunk/lib/Sema/SemaDecl.cpp
>> >>>     cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>> >>>     cfe/trunk/lib/Sema/SemaExpr.cpp
>> >>>     cfe/trunk/lib/Sema/SemaExprCXX.cpp
>> >>>     cfe/trunk/lib/Sema/SemaLambda.cpp
>> >>>     cfe/trunk/lib/Sema/SemaOpenMP.cpp
>> >>>     cfe/trunk/lib/Sema/SemaStmt.cpp
>> >>>     cfe/trunk/lib/Sema/TreeTransform.h
>> >>>     cfe/trunk/test/CXX/stmt.stmt/stmt.select/p3.cpp
>> >>>     cfe/trunk/test/CodeCompletion/pragma-macro-token-caching.c
>> >>>     cfe/trunk/test/Parser/cxx1z-init-statement.cpp
>> >>>     cfe/trunk/test/Parser/switch-recovery.cpp
>> >>>     cfe/trunk/test/SemaCXX/cxx1z-init-statement.cpp
>> >>>     cfe/trunk/test/SemaCXX/for-range-examples.cpp
>> >>>     cfe/trunk/test/SemaCXX/warn-unused-result.cpp
>> >>>
>> >>> Modified: cfe/trunk/include/clang/Parse/Parser.h
>> >>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=350404&r1=350403&r2=350404&view=diff
>> >>> ==============================================================================
>> >>> --- cfe/trunk/include/clang/Parse/Parser.h (original)
>> >>> +++ cfe/trunk/include/clang/Parse/Parser.h Fri Jan  4 08:58:14 2019
>> >>> @@ -360,6 +360,11 @@ class Parser : public CodeCompletionHand
>> >>>    /// just a regular sub-expression.
>> >>>    SourceLocation ExprStatementTokLoc;
>> >>>
>> >>> +  /// Tests whether an expression value is discarded based on token lookahead.
>> >>> +  /// It will return true if the lexer is currently processing the })
>> >>> +  /// terminating a GNU statement expression and false otherwise.
>> >>> +  bool isExprValueDiscarded();
>> >>> +
>> >>>  public:
>> >>>    Parser(Preprocessor &PP, Sema &Actions, bool SkipFunctionBodies);
>> >>>    ~Parser() override;
>> >>>
>> >>> Modified: cfe/trunk/include/clang/Sema/Sema.h
>> >>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=350404&r1=350403&r2=350404&view=diff
>> >>> ==============================================================================
>> >>> --- cfe/trunk/include/clang/Sema/Sema.h (original)
>> >>> +++ cfe/trunk/include/clang/Sema/Sema.h Fri Jan  4 08:58:14 2019
>> >>> @@ -1365,6 +1365,7 @@ public:
>> >>>    void PopCompoundScope();
>> >>>
>> >>>    sema::CompoundScopeInfo &getCurCompoundScope() const;
>> >>> +  bool isCurCompoundStmtAStmtExpr() const;
>> >>>
>> >>>    bool hasAnyUnrecoverableErrorsInThisFunction() const;
>> >>>
>> >>> @@ -3685,16 +3686,17 @@ public:
>> >>>      return MakeFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation());
>> >>>    }
>> >>>    FullExprArg MakeFullExpr(Expr *Arg, SourceLocation CC) {
>> >>> -    return FullExprArg(ActOnFinishFullExpr(Arg, CC).get());
>> >>> +    return FullExprArg(
>> >>> +        ActOnFinishFullExpr(Arg, CC, /*DiscardedValue*/ false).get());
>> >>>    }
>> >>>    FullExprArg MakeFullDiscardedValueExpr(Expr *Arg) {
>> >>>      ExprResult FE =
>> >>> -      ActOnFinishFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation(),
>> >>> -                          /*DiscardedValue*/ true);
>> >>> +        ActOnFinishFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation(),
>> >>> +                            /*DiscardedValue*/ true);
>> >>>      return FullExprArg(FE.get());
>> >>>    }
>> >>>
>> >>> -  StmtResult ActOnExprStmt(ExprResult Arg);
>> >>> +  StmtResult ActOnExprStmt(ExprResult Arg, bool DiscardedValue = true);
>> >>>    StmtResult ActOnExprStmtError();
>> >>>
>> >>>    StmtResult ActOnNullStmt(SourceLocation SemiLoc,
>> >>> @@ -5340,13 +5342,12 @@ public:
>> >>>    CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary,
>> >>>                                   bool BoundToLvalueReference);
>> >>>
>> >>> -  ExprResult ActOnFinishFullExpr(Expr *Expr) {
>> >>> -    return ActOnFinishFullExpr(Expr, Expr ? Expr->getExprLoc()
>> >>> -                                          : SourceLocation());
>> >>> +  ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue) {
>> >>> +    return ActOnFinishFullExpr(
>> >>> +        Expr, Expr ? Expr->getExprLoc() : SourceLocation(), DiscardedValue);
>> >>>    }
>> >>>    ExprResult ActOnFinishFullExpr(Expr *Expr, SourceLocation CC,
>> >>> -                                 bool DiscardedValue = false,
>> >>> -                                 bool IsConstexpr = false);
>> >>> +                                 bool DiscardedValue, bool IsConstexpr = false);
>> >>>    StmtResult ActOnFinishFullStmt(Stmt *Stmt);
>> >>>
>> >>>    // Marks SS invalid if it represents an incomplete type.
>> >>>
>> >>> Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
>> >>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=350404&r1=350403&r2=350404&view=diff
>> >>> ==============================================================================
>> >>> --- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
>> >>> +++ cfe/trunk/lib/Parse/ParseObjc.cpp Fri Jan  4 08:58:14 2019
>> >>> @@ -2741,7 +2741,7 @@ StmtResult Parser::ParseObjCAtStatement(
>> >>>
>> >>>    // Otherwise, eat the semicolon.
>> >>>    ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
>> >>> -  return Actions.ActOnExprStmt(Res);
>> >>> +  return Actions.ActOnExprStmt(Res, isExprValueDiscarded());
>> >>>  }
>> >>>
>> >>>  ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
>> >>>
>> >>> Modified: cfe/trunk/lib/Parse/ParseOpenMP.cpp
>> >>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseOpenMP.cpp?rev=350404&r1=350403&r2=350404&view=diff
>> >>> ==============================================================================
>> >>> --- cfe/trunk/lib/Parse/ParseOpenMP.cpp (original)
>> >>> +++ cfe/trunk/lib/Parse/ParseOpenMP.cpp Fri Jan  4 08:58:14 2019
>> >>> @@ -314,7 +314,7 @@ Parser::ParseOpenMPDeclareReductionDirec
>> >>>      Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
>> >>>      ExprResult CombinerResult =
>> >>>          Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(),
>> >>> -                                    D->getLocation(), /*DiscardedValue=*/true);
>> >>> +                                    D->getLocation(), /*DiscardedValue*/ false);
>> >>>      Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get());
>> >>>
>> >>>      if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
>> >>> @@ -356,7 +356,7 @@ Parser::ParseOpenMPDeclareReductionDirec
>> >>>            if (Actions.getLangOpts().CPlusPlus) {
>> >>>              InitializerResult = Actions.ActOnFinishFullExpr(
>> >>>                  ParseAssignmentExpression().get(), D->getLocation(),
>> >>> -                /*DiscardedValue=*/true);
>> >>> +                /*DiscardedValue*/ false);
>> >>>            } else {
>> >>>              ConsumeToken();
>> >>>              ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
>> >>> @@ -364,7 +364,7 @@ Parser::ParseOpenMPDeclareReductionDirec
>> >>>          } else {
>> >>>            InitializerResult = Actions.ActOnFinishFullExpr(
>> >>>                ParseAssignmentExpression().get(), D->getLocation(),
>> >>> -              /*DiscardedValue=*/true);
>> >>> +              /*DiscardedValue*/ false);
>> >>>          }
>> >>>          Actions.ActOnOpenMPDeclareReductionInitializerEnd(
>> >>>              D, InitializerResult.get(), OmpPrivParm);
>> >>> @@ -1455,7 +1455,7 @@ ExprResult Parser::ParseOpenMPParensExpr
>> >>>    ExprResult LHS(ParseCastExpression(
>> >>>        /*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast));
>> >>>    ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
>> >>> -  Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
>> >>> +  Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
>> >>>
>> >>>    // Parse ')'.
>> >>>    RLoc = Tok.getLocation();
>> >>> @@ -1711,7 +1711,8 @@ OMPClause *Parser::ParseOpenMPSingleExpr
>> >>>      SourceLocation ELoc = Tok.getLocation();
>> >>>      ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
>> >>>      Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
>> >>> -    Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
>> >>> +    Val =
>> >>> +        Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
>> >>>    }
>> >>>
>> >>>    // Parse ')'.
>> >>> @@ -1996,7 +1997,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDi
>> >>>      Data.ColonLoc = Tok.getLocation();
>> >>>      SourceLocation ELoc = ConsumeToken();
>> >>>      ExprResult Tail = ParseAssignmentExpression();
>> >>> -    Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc);
>> >>> +    Tail =
>> >>> +        Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false);
>> >>>      if (Tail.isUsable())
>> >>>        Data.TailExpr = Tail.get();
>> >>>      else
>> >>>
>> >>> Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
>> >>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=350404&r1=350403&r2=350404&view=diff
>> >>> ==============================================================================
>> >>> --- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
>> >>> +++ cfe/trunk/lib/Parse/ParseStmt.cpp Fri Jan  4 08:58:14 2019
>> >>> @@ -439,7 +439,7 @@ StmtResult Parser::ParseExprStatement()
>> >>>
>> >>>    // Otherwise, eat the semicolon.
>> >>>    ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
>> >>> -  return Actions.ActOnExprStmt(Expr);
>> >>> +  return Actions.ActOnExprStmt(Expr, isExprValueDiscarded());
>> >>>  }
>> >>>
>> >>>  /// ParseSEHTryBlockCommon
>> >>> @@ -958,6 +958,16 @@ bool Parser::ConsumeNullStmt(StmtVector
>> >>>    return true;
>> >>>  }
>> >>>
>> >>> +bool Parser::isExprValueDiscarded() {
>> >>> +  if (Actions.isCurCompoundStmtAStmtExpr()) {
>> >>> +    // Look to see if the next two tokens close the statement expression;
>> >>> +    // if so, this expression statement is the last statement in a
>> >>> +    // statment expression.
>> >>> +    return Tok.isNot(tok::r_brace) || NextToken().isNot(tok::r_paren);
>> >>> +  }
>> >>> +  return true;
>> >>> +}
>> >>> +
>> >>>  /// ParseCompoundStatementBody - Parse a sequence of statements and invoke the
>> >>>  /// ActOnCompoundStmt action.  This expects the '{' to be the current token, and
>> >>>  /// consume the '}' at the end of the block.  It does not manipulate the scope
>> >>> @@ -1062,7 +1072,7 @@ StmtResult Parser::ParseCompoundStatemen
>> >>>          // Eat the semicolon at the end of stmt and convert the expr into a
>> >>>          // statement.
>> >>>          ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
>> >>> -        R = Actions.ActOnExprStmt(Res);
>> >>> +        R = Actions.ActOnExprStmt(Res, isExprValueDiscarded());
>> >>>        }
>> >>>      }
>> >>>
>> >>> @@ -1698,8 +1708,16 @@ StmtResult Parser::ParseForStatement(Sou
>> >>>      if (!Value.isInvalid()) {
>> >>>        if (ForEach)
>> >>>          FirstPart = Actions.ActOnForEachLValueExpr(Value.get());
>> >>> -      else
>> >>> -        FirstPart = Actions.ActOnExprStmt(Value);
>> >>> +      else {
>> >>> +        // We already know this is not an init-statement within a for loop, so
>> >>> +        // if we are parsing a C++11 range-based for loop, we should treat this
>> >>> +        // expression statement as being a discarded value expression because
>> >>> +        // we will err below. This way we do not warn on an unused expression
>> >>> +        // that was an error in the first place, like with: for (expr : expr);
>> >>> +        bool IsRangeBasedFor =
>> >>> +            getLangOpts().CPlusPlus11 && !ForEach && Tok.is(tok::colon);
>> >>> +        FirstPart = Actions.ActOnExprStmt(Value, !IsRangeBasedFor);
>> >>> +      }
>> >>>      }
>> >>>
>> >>>      if (Tok.is(tok::semi)) {
>> >>>
>> >>> Modified: cfe/trunk/lib/Sema/SemaCoroutine.cpp
>> >>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCoroutine.cpp?rev=350404&r1=350403&r2=350404&view=diff
>> >>> ==============================================================================
>> >>> --- cfe/trunk/lib/Sema/SemaCoroutine.cpp (original)
>> >>> +++ cfe/trunk/lib/Sema/SemaCoroutine.cpp Fri Jan  4 08:58:14 2019
>> >>> @@ -647,7 +647,7 @@ bool Sema::ActOnCoroutineBodyStart(Scope
>> >>>        return StmtError();
>> >>>      Suspend = BuildResolvedCoawaitExpr(Loc, Suspend.get(),
>> >>>                                         /*IsImplicit*/ true);
>> >>> -    Suspend = ActOnFinishFullExpr(Suspend.get());
>> >>> +    Suspend = ActOnFinishFullExpr(Suspend.get(), /*DiscardedValue*/ false);
>> >>>      if (Suspend.isInvalid()) {
>> >>>        Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required)
>> >>>            << ((Name == "initial_suspend") ? 0 : 1);
>> >>> @@ -868,7 +868,7 @@ StmtResult Sema::BuildCoreturnStmt(Sourc
>> >>>    if (PC.isInvalid())
>> >>>      return StmtError();
>> >>>
>> >>> -  Expr *PCE = ActOnFinishFullExpr(PC.get()).get();
>> >>> +  Expr *PCE = ActOnFinishFullExpr(PC.get(), /*DiscardedValue*/ false).get();
>> >>>
>> >>>    Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE, IsImplicit);
>> >>>    return Res;
>> >>> @@ -1237,7 +1237,7 @@ bool CoroutineStmtBuilder::makeNewAndDel
>> >>>
>> >>>    ExprResult NewExpr =
>> >>>        S.ActOnCallExpr(S.getCurScope(), NewRef.get(), Loc, NewArgs, Loc);
>> >>> -  NewExpr = S.ActOnFinishFullExpr(NewExpr.get());
>> >>> +  NewExpr = S.ActOnFinishFullExpr(NewExpr.get(), /*DiscardedValue*/ false);
>> >>>    if (NewExpr.isInvalid())
>> >>>      return false;
>> >>>
>> >>> @@ -1263,7 +1263,8 @@ bool CoroutineStmtBuilder::makeNewAndDel
>> >>>
>> >>>    ExprResult DeleteExpr =
>> >>>        S.ActOnCallExpr(S.getCurScope(), DeleteRef.get(), Loc, DeleteArgs, Loc);
>> >>> -  DeleteExpr = S.ActOnFinishFullExpr(DeleteExpr.get());
>> >>> +  DeleteExpr =
>> >>> +      S.ActOnFinishFullExpr(DeleteExpr.get(), /*DiscardedValue*/ false);
>> >>>    if (DeleteExpr.isInvalid())
>> >>>      return false;
>> >>>
>> >>> @@ -1348,7 +1349,8 @@ bool CoroutineStmtBuilder::makeOnExcepti
>> >>>
>> >>>    ExprResult UnhandledException = buildPromiseCall(S, Fn.CoroutinePromise, Loc,
>> >>>                                                     "unhandled_exception", None);
>> >>> -  UnhandledException = S.ActOnFinishFullExpr(UnhandledException.get(), Loc);
>> >>> +  UnhandledException = S.ActOnFinishFullExpr(UnhandledException.get(), Loc,
>> >>> +                                             /*DiscardedValue*/ false);
>> >>>    if (UnhandledException.isInvalid())
>> >>>      return false;
>> >>>
>> >>> @@ -1401,7 +1403,8 @@ bool CoroutineStmtBuilder::makeGroDeclAn
>> >>>           "get_return_object type must no longer be dependent");
>> >>>
>> >>>    if (FnRetType->isVoidType()) {
>> >>> -    ExprResult Res = S.ActOnFinishFullExpr(this->ReturnValue, Loc);
>> >>> +    ExprResult Res =
>> >>> +        S.ActOnFinishFullExpr(this->ReturnValue, Loc, /*DiscardedValue*/ false);
>> >>>      if (Res.isInvalid())
>> >>>        return false;
>> >>>
>> >>> @@ -1433,7 +1436,7 @@ bool CoroutineStmtBuilder::makeGroDeclAn
>> >>>    if (Res.isInvalid())
>> >>>      return false;
>> >>>
>> >>> -  Res = S.ActOnFinishFullExpr(Res.get());
>> >>> +  Res = S.ActOnFinishFullExpr(Res.get(), /*DiscardedValue*/ false);
>> >>>    if (Res.isInvalid())
>> >>>      return false;
>> >>>
>> >>>
>> >>> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
>> >>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=350404&r1=350403&r2=350404&view=diff
>> >>> ==============================================================================
>> >>> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
>> >>> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Jan  4 08:58:14 2019
>> >>> @@ -11204,9 +11204,9 @@ void Sema::AddInitializerToDecl(Decl *Re
>> >>>    //   struct T { S a, b; } t = { Temp(), Temp() }
>> >>>    //
>> >>>    // we should destroy the first Temp before constructing the second.
>> >>> -  ExprResult Result = ActOnFinishFullExpr(Init, VDecl->getLocation(),
>> >>> -                                          false,
>> >>> -                                          VDecl->isConstexpr());
>> >>> +  ExprResult Result =
>> >>> +      ActOnFinishFullExpr(Init, VDecl->getLocation(),
>> >>> +                          /*DiscardedValue*/ false, VDecl->isConstexpr());
>> >>>    if (Result.isInvalid()) {
>> >>>      VDecl->setInvalidDecl();
>> >>>      return;
>> >>>
>> >>> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>> >>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=350404&r1=350403&r2=350404&view=diff
>> >>> ==============================================================================
>> >>> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
>> >>> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Jan  4 08:58:14 2019
>> >>> @@ -1205,7 +1205,7 @@ static bool checkTupleLikeDecomposition(
>> >>>      E = Seq.Perform(S, Entity, Kind, Init);
>> >>>      if (E.isInvalid())
>> >>>        return true;
>> >>> -    E = S.ActOnFinishFullExpr(E.get(), Loc);
>> >>> +    E = S.ActOnFinishFullExpr(E.get(), Loc, /*DiscardedValue*/ false);
>> >>>      if (E.isInvalid())
>> >>>        return true;
>> >>>      RefVD->setInit(E.get());
>> >>> @@ -3682,7 +3682,7 @@ void Sema::ActOnFinishCXXInClassMemberIn
>> >>>    // C++11 [class.base.init]p7:
>> >>>    //   The initialization of each base and member constitutes a
>> >>>    //   full-expression.
>> >>> -  Init = ActOnFinishFullExpr(Init.get(), InitLoc);
>> >>> +  Init = ActOnFinishFullExpr(Init.get(), InitLoc, /*DiscardedValue*/ false);
>> >>>    if (Init.isInvalid()) {
>> >>>      FD->setInvalidDecl();
>> >>>      return;
>> >>> @@ -4040,7 +4040,8 @@ Sema::BuildMemberInitializer(ValueDecl *
>> >>>      // C++11 [class.base.init]p7:
>> >>>      //   The initialization of each base and member constitutes a
>> >>>      //   full-expression.
>> >>> -    MemberInit = ActOnFinishFullExpr(MemberInit.get(), InitRange.getBegin());
>> >>> +    MemberInit = ActOnFinishFullExpr(MemberInit.get(), InitRange.getBegin(),
>> >>> +                                     /*DiscardedValue*/ false);
>> >>>      if (MemberInit.isInvalid())
>> >>>        return true;
>> >>>
>> >>> @@ -4095,8 +4096,8 @@ Sema::BuildDelegatingInitializer(TypeSou
>> >>>    // C++11 [class.base.init]p7:
>> >>>    //   The initialization of each base and member constitutes a
>> >>>    //   full-expression.
>> >>> -  DelegationInit = ActOnFinishFullExpr(DelegationInit.get(),
>> >>> -                                       InitRange.getBegin());
>> >>> +  DelegationInit = ActOnFinishFullExpr(
>> >>> +      DelegationInit.get(), InitRange.getBegin(), /*DiscardedValue*/ false);
>> >>>    if (DelegationInit.isInvalid())
>> >>>      return true;
>> >>>
>> >>> @@ -4225,7 +4226,8 @@ Sema::BuildBaseInitializer(QualType Base
>> >>>    // C++11 [class.base.init]p7:
>> >>>    //   The initialization of each base and member constitutes a
>> >>>    //   full-expression.
>> >>> -  BaseInit = ActOnFinishFullExpr(BaseInit.get(), InitRange.getBegin());
>> >>> +  BaseInit = ActOnFinishFullExpr(BaseInit.get(), InitRange.getBegin(),
>> >>> +                                 /*DiscardedValue*/ false);
>> >>>    if (BaseInit.isInvalid())
>> >>>      return true;
>> >>>
>> >>>
>> >>> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
>> >>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=350404&r1=350403&r2=350404&view=diff
>> >>> ==============================================================================
>> >>> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
>> >>> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Jan  4 08:58:14 2019
>> >>> @@ -4736,8 +4736,9 @@ bool Sema::CheckCXXDefaultArgExpr(Source
>> >>>      if (Result.isInvalid())
>> >>>        return true;
>> >>>
>> >>> -    Result = ActOnFinishFullExpr(Result.getAs<Expr>(),
>> >>> -                                 Param->getOuterLocStart());
>> >>> +    Result =
>> >>> +        ActOnFinishFullExpr(Result.getAs<Expr>(), Param->getOuterLocStart(),
>> >>> +                            /*DiscardedValue*/ false);
>> >>>      if (Result.isInvalid())
>> >>>        return true;
>> >>>
>> >>>
>> >>> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
>> >>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=350404&r1=350403&r2=350404&view=diff
>> >>> ==============================================================================
>> >>> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
>> >>> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Fri Jan  4 08:58:14 2019
>> >>> @@ -7803,6 +7803,8 @@ ExprResult Sema::ActOnFinishFullExpr(Exp
>> >>>      FullExpr = IgnoredValueConversions(FullExpr.get());
>> >>>      if (FullExpr.isInvalid())
>> >>>        return ExprError();
>> >>> +
>> >>> +    DiagnoseUnusedExprResult(FullExpr.get());
>> >>>    }
>> >>>
>> >>>    FullExpr = CorrectDelayedTyposInExpr(FullExpr.get());
>> >>>
>> >>> Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
>> >>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=350404&r1=350403&r2=350404&view=diff
>> >>> ==============================================================================
>> >>> --- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
>> >>> +++ cfe/trunk/lib/Sema/SemaLambda.cpp Fri Jan  4 08:58:14 2019
>> >>> @@ -1724,7 +1724,7 @@ ExprResult Sema::BuildBlockForLambdaConv
>> >>>                                                   /*NRVO=*/false),
>> >>>        CurrentLocation, Src);
>> >>>    if (!Init.isInvalid())
>> >>> -    Init = ActOnFinishFullExpr(Init.get());
>> >>> +    Init = ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false);
>> >>>
>> >>>    if (Init.isInvalid())
>> >>>      return ExprError();
>> >>>
>> >>> Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
>> >>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=350404&r1=350403&r2=350404&view=diff
>> >>> ==============================================================================
>> >>> --- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
>> >>> +++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Fri Jan  4 08:58:14 2019
>> >>> @@ -5320,7 +5320,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKin
>> >>>          LastIteration.get(), UB.get());
>> >>>      EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
>> >>>                               CondOp.get());
>> >>> -    EUB = SemaRef.ActOnFinishFullExpr(EUB.get());
>> >>> +    EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue*/ false);
>> >>>
>> >>>      // If we have a combined directive that combines 'distribute', 'for' or
>> >>>      // 'simd' we need to be able to access the bounds of the schedule of the
>> >>> @@ -5349,7 +5349,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKin
>> >>>                                       LastIteration.get(), CombUB.get());
>> >>>        CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
>> >>>                                     CombCondOp.get());
>> >>> -      CombEUB = SemaRef.ActOnFinishFullExpr(CombEUB.get());
>> >>> +      CombEUB =
>> >>> +          SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue*/ false);
>> >>>
>> >>>        const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
>> >>>        // We expect to have at least 2 more parameters than the 'parallel'
>> >>> @@ -5383,7 +5384,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKin
>> >>>              ? LB.get()
>> >>>              : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
>> >>>      Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
>> >>> -    Init = SemaRef.ActOnFinishFullExpr(Init.get());
>> >>> +    Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false);
>> >>>
>> >>>      if (isOpenMPLoopBoundSharingDirective(DKind)) {
>> >>>        Expr *CombRHS =
>> >>> @@ -5394,7 +5395,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKin
>> >>>                : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
>> >>>        CombInit =
>> >>>            SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
>> >>> -      CombInit = SemaRef.ActOnFinishFullExpr(CombInit.get());
>> >>> +      CombInit =
>> >>> +          SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue*/ false);
>> >>>      }
>> >>>    }
>> >>>
>> >>> @@ -5426,7 +5428,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKin
>> >>>    if (!Inc.isUsable())
>> >>>      return 0;
>> >>>    Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
>> >>> -  Inc = SemaRef.ActOnFinishFullExpr(Inc.get());
>> >>> +  Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue*/ false);
>> >>>    if (!Inc.isUsable())
>> >>>      return 0;
>> >>>
>> >>> @@ -5444,7 +5446,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKin
>> >>>      // LB = LB + ST
>> >>>      NextLB =
>> >>>          SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
>> >>> -    NextLB = SemaRef.ActOnFinishFullExpr(NextLB.get());
>> >>> +    NextLB =
>> >>> +        SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue*/ false);
>> >>>      if (!NextLB.isUsable())
>> >>>        return 0;
>> >>>      // UB + ST
>> >>> @@ -5454,7 +5457,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKin
>> >>>      // UB = UB + ST
>> >>>      NextUB =
>> >>>          SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
>> >>> -    NextUB = SemaRef.ActOnFinishFullExpr(NextUB.get());
>> >>> +    NextUB =
>> >>> +        SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue*/ false);
>> >>>      if (!NextUB.isUsable())
>> >>>        return 0;
>> >>>      if (isOpenMPLoopBoundSharingDirective(DKind)) {
>> >>> @@ -5465,7 +5469,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKin
>> >>>        // LB = LB + ST
>> >>>        CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
>> >>>                                        CombNextLB.get());
>> >>> -      CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get());
>> >>> +      CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
>> >>> +                                               /*DiscardedValue*/ false);
>> >>>        if (!CombNextLB.isUsable())
>> >>>          return 0;
>> >>>        // UB + ST
>> >>> @@ -5476,7 +5481,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKin
>> >>>        // UB = UB + ST
>> >>>        CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
>> >>>                                        CombNextUB.get());
>> >>> -      CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get());
>> >>> +      CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
>> >>> +                                               /*DiscardedValue*/ false);
>> >>>        if (!CombNextUB.isUsable())
>> >>>          return 0;
>> >>>      }
>> >>> @@ -5497,7 +5503,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKin
>> >>>      assert(DistInc.isUsable() && "distribute inc expr was not built");
>> >>>      DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
>> >>>                                   DistInc.get());
>> >>> -    DistInc = SemaRef.ActOnFinishFullExpr(DistInc.get());
>> >>> +    DistInc =
>> >>> +        SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue*/ false);
>> >>>      assert(DistInc.isUsable() && "distribute inc expr was not built");
>> >>>
>> >>>      // Build expression: UB = min(UB, prevUB) for #for in composite or combined
>> >>> @@ -5509,7 +5516,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKin
>> >>>          DistEUBLoc, DistEUBLoc, IsUBGreater.get(), PrevUB.get(), UB.get());
>> >>>      PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
>> >>>                                   CondOp.get());
>> >>> -    PrevEUB = SemaRef.ActOnFinishFullExpr(PrevEUB.get());
>> >>> +    PrevEUB =
>> >>> +        SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue*/ false);
>> >>>
>> >>>      // Build IV <= PrevUB to be used in parallel for is in combination with
>> >>>      // a distribute directive with schedule(static, 1)
>> >>> @@ -5613,8 +5621,10 @@ checkOpenMPLoop(OpenMPDirectiveKind DKin
>> >>>    Built.IterationVarRef = IV.get();
>> >>>    Built.LastIteration = LastIteration.get();
>> >>>    Built.NumIterations = NumIterations.get();
>> >>> -  Built.CalcLastIteration =
>> >>> -      SemaRef.ActOnFinishFullExpr(CalcLastIteration.get()).get();
>> >>> +  Built.CalcLastIteration = SemaRef
>> >>> +                                .ActOnFinishFullExpr(CalcLastIteration.get(),
>> >>> +                                                     /*DiscardedValue*/ false)
>> >>> +                                .get();
>> >>>    Built.PreCond = PreCond.get();
>> >>>    Built.PreInits = buildPreInits(C, Captures);
>> >>>    Built.Cond = Cond.get();
>> >>> @@ -10267,8 +10277,8 @@ OMPClause *Sema::ActOnOpenMPLastprivateC
>> >>>                                           PseudoDstExpr, PseudoSrcExpr);
>> >>>      if (AssignmentOp.isInvalid())
>> >>>        continue;
>> >>> -    AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
>> >>> -                                       /*DiscardedValue=*/true);
>> >>> +    AssignmentOp =
>> >>> +        ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false);
>> >>>      if (AssignmentOp.isInvalid())
>> >>>        continue;
>> >>>
>> >>> @@ -11274,7 +11284,8 @@ static bool actOnOMPReductionKindClause(
>> >>>                             BO_Assign, LHSDRE, ConditionalOp);
>> >>>          }
>> >>>          if (ReductionOp.isUsable())
>> >>> -          ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get());
>> >>> +          ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
>> >>> +                                              /*DiscardedValue*/ false);
>> >>>        }
>> >>>        if (!ReductionOp.isUsable())
>> >>>          continue;
>> >>> @@ -11612,7 +11623,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause
>> >>>          buildDeclRefExpr(*this, SaveVar, StepExpr->getType(), StepLoc);
>> >>>      ExprResult CalcStep =
>> >>>          BuildBinOp(CurScope, StepLoc, BO_Assign, SaveRef.get(), StepExpr);
>> >>> -    CalcStep = ActOnFinishFullExpr(CalcStep.get());
>> >>> +    CalcStep = ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue*/ false);
>> >>>
>> >>>      // Warn about zero linear step (it would be probably better specified as
>> >>>      // making corresponding variables 'const').
>> >>> @@ -11700,7 +11711,7 @@ static bool FinishOpenMPLinearClause(OMP
>> >>>      else
>> >>>        Update = *CurPrivate;
>> >>>      Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
>> >>> -                                         /*DiscardedValue=*/true);
>> >>> +                                         /*DiscardedValue*/ false);
>> >>>
>> >>>      // Build final: Var = InitExpr + NumIterations * Step
>> >>>      ExprResult Final;
>> >>> @@ -11711,7 +11722,7 @@ static bool FinishOpenMPLinearClause(OMP
>> >>>      else
>> >>>        Final = *CurPrivate;
>> >>>      Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
>> >>> -                                        /*DiscardedValue=*/true);
>> >>> +                                        /*DiscardedValue*/ false);
>> >>>
>> >>>      if (!Update.isUsable() || !Final.isUsable()) {
>> >>>        Updates.push_back(nullptr);
>> >>> @@ -11879,7 +11890,7 @@ OMPClause *Sema::ActOnOpenMPCopyinClause
>> >>>      if (AssignmentOp.isInvalid())
>> >>>        continue;
>> >>>      AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
>> >>> -                                       /*DiscardedValue=*/true);
>> >>> +                                       /*DiscardedValue*/ false);
>> >>>      if (AssignmentOp.isInvalid())
>> >>>        continue;
>> >>>
>> >>> @@ -11987,8 +11998,8 @@ OMPClause *Sema::ActOnOpenMPCopyprivateC
>> >>>          DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
>> >>>      if (AssignmentOp.isInvalid())
>> >>>        continue;
>> >>> -    AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
>> >>> -                                       /*DiscardedValue=*/true);
>> >>> +    AssignmentOp =
>> >>> +        ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false);
>> >>>      if (AssignmentOp.isInvalid())
>> >>>        continue;
>> >>>
>> >>>
>> >>> Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
>> >>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=350404&r1=350403&r2=350404&view=diff
>> >>> ==============================================================================
>> >>> --- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
>> >>> +++ cfe/trunk/lib/Sema/SemaStmt.cpp Fri Jan  4 08:58:14 2019
>> >>> @@ -42,12 +42,11 @@
>> >>>  using namespace clang;
>> >>>  using namespace sema;
>> >>>
>> >>> -StmtResult Sema::ActOnExprStmt(ExprResult FE) {
>> >>> +StmtResult Sema::ActOnExprStmt(ExprResult FE, bool DiscardedValue) {
>> >>>    if (FE.isInvalid())
>> >>>      return StmtError();
>> >>>
>> >>> -  FE = ActOnFinishFullExpr(FE.get(), FE.get()->getExprLoc(),
>> >>> -                           /*DiscardedValue*/ true);
>> >>> +  FE = ActOnFinishFullExpr(FE.get(), FE.get()->getExprLoc(), DiscardedValue);
>> >>>    if (FE.isInvalid())
>> >>>      return StmtError();
>> >>>
>> >>> @@ -348,6 +347,10 @@ sema::CompoundScopeInfo &Sema::getCurCom
>> >>>    return getCurFunction()->CompoundScopes.back();
>> >>>  }
>> >>>
>> >>> +bool Sema::isCurCompoundStmtAStmtExpr() const {
>> >>> +  return getCurCompoundScope().IsStmtExpr;
>> >>> +}
>> >>> +
>> >>>  StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
>> >>>                                     ArrayRef<Stmt *> Elts, bool isStmtExpr) {
>> >>>    const unsigned NumElts = Elts.size();
>> >>> @@ -370,14 +373,6 @@ StmtResult Sema::ActOnCompoundStmt(Sourc
>> >>>        Diag(D->getLocation(), diag::ext_mixed_decls_code);
>> >>>      }
>> >>>    }
>> >>> -  // Warn about unused expressions in statements.
>> >>> -  for (unsigned i = 0; i != NumElts; ++i) {
>> >>> -    // Ignore statements that are last in a statement expression.
>> >>> -    if (isStmtExpr && i == NumElts - 1)
>> >>> -      continue;
>> >>> -
>> >>> -    DiagnoseUnusedExprResult(Elts[i]);
>> >>> -  }
>> >>>
>> >>>    // Check for suspicious empty body (null statement) in `for' and `while'
>> >>>    // statements.  Don't do anything for template instantiations, this just adds
>> >>> @@ -469,15 +464,12 @@ Sema::ActOnCaseStmt(SourceLocation CaseL
>> >>>
>> >>>  /// ActOnCaseStmtBody - This installs a statement as the body of a case.
>> >>>  void Sema::ActOnCaseStmtBody(Stmt *S, Stmt *SubStmt) {
>> >>> -  DiagnoseUnusedExprResult(SubStmt);
>> >>>    cast<CaseStmt>(S)->setSubStmt(SubStmt);
>> >>>  }
>> >>>
>> >>>  StmtResult
>> >>>  Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc,
>> >>>                         Stmt *SubStmt, Scope *CurScope) {
>> >>> -  DiagnoseUnusedExprResult(SubStmt);
>> >>> -
>> >>>    if (getCurFunction()->SwitchStack.empty()) {
>> >>>      Diag(DefaultLoc, diag::err_default_not_in_switch);
>> >>>      return SubStmt;
>> >>> @@ -571,9 +563,6 @@ StmtResult Sema::BuildIfStmt(SourceLocat
>> >>>    if (IsConstexpr || isa<ObjCAvailabilityCheckExpr>(Cond.get().second))
>> >>>      setFunctionHasBranchProtectedScope();
>> >>>
>> >>> -  DiagnoseUnusedExprResult(thenStmt);
>> >>> -  DiagnoseUnusedExprResult(elseStmt);
>> >>> -
>> >>>    return IfStmt::Create(Context, IfLoc, IsConstexpr, InitStmt, Cond.get().first,
>> >>>                          Cond.get().second, thenStmt, ElseLoc, elseStmt);
>> >>>  }
>> >>> @@ -1301,8 +1290,6 @@ StmtResult Sema::ActOnWhileStmt(SourceLo
>> >>>        !Diags.isIgnored(diag::warn_comma_operator, CondVal.second->getExprLoc()))
>> >>>      CommaVisitor(*this).Visit(CondVal.second);
>> >>>
>> >>> -  DiagnoseUnusedExprResult(Body);
>> >>> -
>> >>>    if (isa<NullStmt>(Body))
>> >>>      getCurCompoundScope().setHasEmptyLoopBodies();
>> >>>
>> >>> @@ -1322,7 +1309,7 @@ Sema::ActOnDoStmt(SourceLocation DoLoc,
>> >>>      return StmtError();
>> >>>    Cond = CondResult.get();
>> >>>
>> >>> -  CondResult = ActOnFinishFullExpr(Cond, DoLoc);
>> >>> +  CondResult = ActOnFinishFullExpr(Cond, DoLoc, /*DiscardedValue*/ false);
>> >>>    if (CondResult.isInvalid())
>> >>>      return StmtError();
>> >>>    Cond = CondResult.get();
>> >>> @@ -1332,8 +1319,6 @@ Sema::ActOnDoStmt(SourceLocation DoLoc,
>> >>>        !Diags.isIgnored(diag::warn_comma_operator, Cond->getExprLoc()))
>> >>>      CommaVisitor(*this).Visit(Cond);
>> >>>
>> >>> -  DiagnoseUnusedExprResult(Body);
>> >>> -
>> >>>    return new (Context) DoStmt(Body, Cond, DoLoc, WhileLoc, CondRParen);
>> >>>  }
>> >>>
>> >>> @@ -1778,11 +1763,6 @@ StmtResult Sema::ActOnForStmt(SourceLoca
>> >>>      CommaVisitor(*this).Visit(Second.get().second);
>> >>>
>> >>>    Expr *Third  = third.release().getAs<Expr>();
>> >>> -
>> >>> -  DiagnoseUnusedExprResult(First);
>> >>> -  DiagnoseUnusedExprResult(Third);
>> >>> -  DiagnoseUnusedExprResult(Body);
>> >>> -
>> >>>    if (isa<NullStmt>(Body))
>> >>>      getCurCompoundScope().setHasEmptyLoopBodies();
>> >>>
>> >>> @@ -1802,7 +1782,7 @@ StmtResult Sema::ActOnForEachLValueExpr(
>> >>>    if (result.isInvalid()) return StmtError();
>> >>>    E = result.get();
>> >>>
>> >>> -  ExprResult FullExpr = ActOnFinishFullExpr(E);
>> >>> +  ExprResult FullExpr = ActOnFinishFullExpr(E, /*DiscardedValue*/ false);
>> >>>    if (FullExpr.isInvalid())
>> >>>      return StmtError();
>> >>>    return StmtResult(static_cast<Stmt*>(FullExpr.get()));
>> >>> @@ -1956,7 +1936,8 @@ Sema::ActOnObjCForCollectionStmt(SourceL
>> >>>    if (CollectionExprResult.isInvalid())
>> >>>      return StmtError();
>> >>>
>> >>> -  CollectionExprResult = ActOnFinishFullExpr(CollectionExprResult.get());
>> >>> +  CollectionExprResult =
>> >>> +      ActOnFinishFullExpr(CollectionExprResult.get(), /*DiscardedValue*/ false);
>> >>>    if (CollectionExprResult.isInvalid())
>> >>>      return StmtError();
>> >>>
>> >>> @@ -2593,7 +2574,8 @@ StmtResult Sema::BuildCXXForRangeStmt(So
>> >>>      if (!NotEqExpr.isInvalid())
>> >>>        NotEqExpr = CheckBooleanCondition(ColonLoc, NotEqExpr.get());
>> >>>      if (!NotEqExpr.isInvalid())
>> >>> -      NotEqExpr = ActOnFinishFullExpr(NotEqExpr.get());
>> >>> +      NotEqExpr =
>> >>> +          ActOnFinishFullExpr(NotEqExpr.get(), /*DiscardedValue*/ false);
>> >>>      if (NotEqExpr.isInvalid()) {
>> >>>        Diag(RangeLoc, diag::note_for_range_invalid_iterator)
>> >>>          << RangeLoc << 0 << BeginRangeRef.get()->getType();
>> >>> @@ -2616,7 +2598,7 @@ StmtResult Sema::BuildCXXForRangeStmt(So
>> >>>        // co_await during the initial parse.
>> >>>        IncrExpr = ActOnCoawaitExpr(S, CoawaitLoc, IncrExpr.get());
>> >>>      if (!IncrExpr.isInvalid())
>> >>> -      IncrExpr = ActOnFinishFullExpr(IncrExpr.get());
>> >>> +      IncrExpr = ActOnFinishFullExpr(IncrExpr.get(), /*DiscardedValue*/ false);
>> >>>      if (IncrExpr.isInvalid()) {
>> >>>        Diag(RangeLoc, diag::note_for_range_invalid_iterator)
>> >>>          << RangeLoc << 2 << BeginRangeRef.get()->getType() ;
>> >>> @@ -2871,7 +2853,7 @@ Sema::ActOnIndirectGotoStmt(SourceLocati
>> >>>        return StmtError();
>> >>>    }
>> >>>
>> >>> -  ExprResult ExprRes = ActOnFinishFullExpr(E);
>> >>> +  ExprResult ExprRes = ActOnFinishFullExpr(E, /*DiscardedValue*/ false);
>> >>>    if (ExprRes.isInvalid())
>> >>>      return StmtError();
>> >>>    E = ExprRes.get();
>> >>> @@ -3221,7 +3203,8 @@ Sema::ActOnCapScopeReturnStmt(SourceLoca
>> >>>            ExpressionEvaluationContext::DiscardedStatement &&
>> >>>        (HasDeducedReturnType || CurCap->HasImplicitReturnType)) {
>> >>>      if (RetValExp) {
>> >>> -      ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc);
>> >>> +      ExprResult ER =
>> >>> +          ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false);
>> >>>        if (ER.isInvalid())
>> >>>          return StmtError();
>> >>>        RetValExp = ER.get();
>> >>> @@ -3348,7 +3331,8 @@ Sema::ActOnCapScopeReturnStmt(SourceLoca
>> >>>    }
>> >>>
>> >>>    if (RetValExp) {
>> >>> -    ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc);
>> >>> +    ExprResult ER =
>> >>> +        ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false);
>> >>>      if (ER.isInvalid())
>> >>>        return StmtError();
>> >>>      RetValExp = ER.get();
>> >>> @@ -3578,7 +3562,8 @@ StmtResult Sema::BuildReturnStmt(SourceL
>> >>>            ExpressionEvaluationContext::DiscardedStatement &&
>> >>>        FnRetType->getContainedAutoType()) {
>> >>>      if (RetValExp) {
>> >>> -      ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc);
>> >>> +      ExprResult ER =
>> >>> +          ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false);
>> >>>        if (ER.isInvalid())
>> >>>          return StmtError();
>> >>>        RetValExp = ER.get();
>> >>> @@ -3672,7 +3657,8 @@ StmtResult Sema::BuildReturnStmt(SourceL
>> >>>        }
>> >>>
>> >>>        if (RetValExp) {
>> >>> -        ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc);
>> >>> +        ExprResult ER =
>> >>> +            ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false);
>> >>>          if (ER.isInvalid())
>> >>>            return StmtError();
>> >>>          RetValExp = ER.get();
>> >>> @@ -3751,7 +3737,8 @@ StmtResult Sema::BuildReturnStmt(SourceL
>> >>>      }
>> >>>
>> >>>      if (RetValExp) {
>> >>> -      ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc);
>> >>> +      ExprResult ER =
>> >>> +          ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false);
>> >>>        if (ER.isInvalid())
>> >>>          return StmtError();
>> >>>        RetValExp = ER.get();
>> >>> @@ -3804,7 +3791,7 @@ StmtResult Sema::BuildObjCAtThrowStmt(So
>> >>>      if (Result.isInvalid())
>> >>>        return StmtError();
>> >>>
>> >>> -    Result = ActOnFinishFullExpr(Result.get());
>> >>> +    Result = ActOnFinishFullExpr(Result.get(), /*DiscardedValue*/ false);
>> >>>      if (Result.isInvalid())
>> >>>        return StmtError();
>> >>>      Throw = Result.get();
>> >>> @@ -3876,7 +3863,7 @@ Sema::ActOnObjCAtSynchronizedOperand(Sou
>> >>>    }
>> >>>
>> >>>    // The operand to @synchronized is a full-expression.
>> >>> -  return ActOnFinishFullExpr(operand);
>> >>> +  return ActOnFinishFullExpr(operand, /*DiscardedValue*/ false);
>> >>>  }
>> >>>
>> >>>  StmtResult
>> >>>
>> >>> Modified: cfe/trunk/lib/Sema/TreeTransform.h
>> >>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=350404&r1=350403&r2=350404&view=diff
>> >>> ==============================================================================
>> >>> --- cfe/trunk/lib/Sema/TreeTransform.h (original)
>> >>> +++ cfe/trunk/lib/Sema/TreeTransform.h Fri Jan  4 08:58:14 2019
>> >>> @@ -328,7 +328,7 @@ public:
>> >>>    /// other mechanism.
>> >>>    ///
>> >>>    /// \returns the transformed statement.
>> >>> -  StmtResult TransformStmt(Stmt *S);
>> >>> +  StmtResult TransformStmt(Stmt *S, bool DiscardedValue = false);
>> >>>
>> >>>    /// Transform the given statement.
>> >>>    ///
>> >>> @@ -3269,8 +3269,8 @@ private:
>> >>>                                        bool DeducibleTSTContext);
>> >>>  };
>> >>>
>> >>> -template<typename Derived>
>> >>> -StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) {
>> >>> +template <typename Derived>
>> >>> +StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S, bool DiscardedValue) {
>> >>>    if (!S)
>> >>>      return S;
>> >>>
>> >>> @@ -3294,7 +3294,7 @@ StmtResult TreeTransform<Derived>::Trans
>> >>>        if (E.isInvalid())
>> >>>          return StmtError();
>> >>>
>> >>> -      return getSema().ActOnExprStmt(E);
>> >>> +      return getSema().ActOnExprStmt(E, DiscardedValue);
>> >>>      }
>> >>>    }
>> >>>
>> >>> @@ -4715,7 +4715,8 @@ TreeTransform<Derived>::TransformVariabl
>> >>>    }
>> >>>    if (SizeResult.isInvalid())
>> >>>      return QualType();
>> >>> -  SizeResult = SemaRef.ActOnFinishFullExpr(SizeResult.get());
>> >>> +  SizeResult =
>> >>> +      SemaRef.ActOnFinishFullExpr(SizeResult.get(), /*DiscardedValue*/ false);
>> >>>    if (SizeResult.isInvalid())
>> >>>      return QualType();
>> >>>
>> >>> @@ -6520,7 +6521,9 @@ TreeTransform<Derived>::TransformCompoun
>> >>>    bool SubStmtChanged = false;
>> >>>    SmallVector<Stmt*, 8> Statements;
>> >>>    for (auto *B : S->body()) {
>> >>> -    StmtResult Result = getDerived().TransformStmt(B);
>> >>> +    StmtResult Result =
>> >>> +        getDerived().TransformStmt(B, !IsStmtExpr || B != S->body_back());
>> >>> +
>> >>>      if (Result.isInvalid()) {
>> >>>        // Immediately fail if this was a DeclStmt, since it's very
>> >>>        // likely that this will cause problems for future statements.
>> >>>
>> >>> Modified: cfe/trunk/test/CXX/stmt.stmt/stmt.select/p3.cpp
>> >>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/stmt.stmt/stmt.select/p3.cpp?rev=350404&r1=350403&r2=350404&view=diff
>> >>> ==============================================================================
>> >>> --- cfe/trunk/test/CXX/stmt.stmt/stmt.select/p3.cpp (original)
>> >>> +++ cfe/trunk/test/CXX/stmt.stmt/stmt.select/p3.cpp Fri Jan  4 08:58:14 2019
>> >>> @@ -1,5 +1,5 @@
>> >>> -// RUN: %clang_cc1 -fsyntax-only -verify %s
>> >>> -// RUN: %clang_cc1 -fsyntax-only -std=c++1z -Wc++14-compat -verify %s -DCPP17
>> >>> +// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify %s
>> >>> +// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -std=c++1z -Wc++14-compat -verify %s -DCPP17
>> >>>
>> >>>  int f();
>> >>>
>> >>> @@ -71,7 +71,6 @@ void whileInitStatement() {
>> >>>  // last loop above. It would be nice to remove this.
>> >>>  void whileInitStatement2() {
>> >>>    while (; false) {} // expected-error {{expected expression}}
>> >>> -  // expected-warning at -1 {{expression result unused}}
>> >>> -  // expected-error at -2 {{expected ';' after expression}}
>> >>> -  // expected-error at -3 {{expected expression}}
>> >>> +  // expected-error at -1 {{expected ';' after expression}}
>> >>> +  // expected-error at -2 {{expected expression}}
>> >>>  }
>> >>>
>> >>> Modified: cfe/trunk/test/CodeCompletion/pragma-macro-token-caching.c
>> >>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeCompletion/pragma-macro-token-caching.c?rev=350404&r1=350403&r2=350404&view=diff
>> >>> ==============================================================================
>> >>> --- cfe/trunk/test/CodeCompletion/pragma-macro-token-caching.c (original)
>> >>> +++ cfe/trunk/test/CodeCompletion/pragma-macro-token-caching.c Fri Jan  4 08:58:14 2019
>> >>> @@ -12,7 +12,7 @@ void completeParam(int param) {
>> >>>
>> >>>  void completeParamPragmaError(int param) {
>> >>>      Outer(__extension__({ _Pragma(2) })); // expected-error {{_Pragma takes a parenthesized string literal}}
>> >>> -    param;
>> >>> +    param; // expected-warning {{expression result unused}}
>> >>>  }
>> >>>
>> >>>  // RUN: %clang_cc1 -fsyntax-only -verify -code-completion-at=%s:16:1 %s | FileCheck %s
>> >>>
>> >>> Modified: cfe/trunk/test/Parser/cxx1z-init-statement.cpp
>> >>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx1z-init-statement.cpp?rev=350404&r1=350403&r2=350404&view=diff
>> >>> ==============================================================================
>> >>> --- cfe/trunk/test/Parser/cxx1z-init-statement.cpp (original)
>> >>> +++ cfe/trunk/test/Parser/cxx1z-init-statement.cpp Fri Jan  4 08:58:14 2019
>> >>> @@ -13,9 +13,9 @@ int f() {
>> >>>    if (T(n) = 0; n) {}
>> >>>
>> >>>    // init-statement expressions
>> >>> -  if (T{f()}; f()) {}
>> >>> -  if (T{f()}, g, h; f()) {} // expected-warning 2{{unused}}
>> >>> -  if (T(f()), g, h + 1; f()) {} // expected-warning 2{{unused}}
>> >>> +  if (T{f()}; f()) {} // expected-warning {{expression result unused}}
>> >>> +  if (T{f()}, g, h; f()) {} // expected-warning 2{{unused}} expected-warning {{expression result unused}}
>> >>> +  if (T(f()), g, h + 1; f()) {} // expected-warning 2{{unused}} expected-warning {{expression result unused}}
>> >>>
>> >>>    // condition declarations
>> >>>    if (T(n){g}) {}
>> >>> @@ -35,7 +35,7 @@ int f() {
>> >>>
>> >>>    // Likewise for 'switch'
>> >>>    switch (int n; n) {}
>> >>> -  switch (g; int g = 5) {}
>> >>> +  switch (g; int g = 5) {} // expected-warning {{expression result unused}}
>> >>>
>> >>>    if (int a, b; int c = a) { // expected-note 6{{previous}}
>> >>>      int a; // expected-error {{redefinition}}
>> >>>
>> >>> Modified: cfe/trunk/test/Parser/switch-recovery.cpp
>> >>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/switch-recovery.cpp?rev=350404&r1=350403&r2=350404&view=diff
>> >>> ==============================================================================
>> >>> --- cfe/trunk/test/Parser/switch-recovery.cpp (original)
>> >>> +++ cfe/trunk/test/Parser/switch-recovery.cpp Fri Jan  4 08:58:14 2019
>> >>> @@ -105,7 +105,7 @@ void test9(int x) { // expected-note {{'
>> >>>                expected-error {{expected expression}}
>> >>>      8:: x; // expected-error {{expected ';' after expression}} \
>> >>>                expected-error {{no member named 'x' in the global namespace; did you mean simply 'x'?}} \
>> >>> -              expected-warning 2 {{expression result unused}}
>> >>> +              expected-warning {{expression result unused}}
>> >>>      9:: :y; // expected-error {{expected ';' after expression}} \
>> >>>                 expected-error {{expected unqualified-id}} \
>> >>>                 expected-warning {{expression result unused}}
>> >>>
>> >>> Modified: cfe/trunk/test/SemaCXX/cxx1z-init-statement.cpp
>> >>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1z-init-statement.cpp?rev=350404&r1=350403&r2=350404&view=diff
>> >>> ==============================================================================
>> >>> --- cfe/trunk/test/SemaCXX/cxx1z-init-statement.cpp (original)
>> >>> +++ cfe/trunk/test/SemaCXX/cxx1z-init-statement.cpp Fri Jan  4 08:58:14 2019
>> >>> @@ -1,5 +1,5 @@
>> >>> -// RUN: %clang_cc1 -std=c++1z -verify %s
>> >>> -// RUN: %clang_cc1 -std=c++17 -verify %s
>> >>> +// RUN: %clang_cc1 -std=c++1z -Wno-unused-value -verify %s
>> >>> +// RUN: %clang_cc1 -std=c++17 -Wno-unused-value -verify %s
>> >>>
>> >>>  void testIf() {
>> >>>    int x = 0;
>> >>> @@ -12,7 +12,7 @@ void testIf() {
>> >>>      int x = 0; // expected-error {{redefinition of 'x'}}
>> >>>
>> >>>    if (x; int a = 0) ++a;
>> >>> -  if (x, +x; int a = 0) // expected-note 2 {{previous definition is here}} expected-warning {{unused}}
>> >>> +  if (x, +x; int a = 0) // expected-note 2 {{previous definition is here}}
>> >>>      int a = 0; // expected-error {{redefinition of 'a'}}
>> >>>    else
>> >>>      int a = 0; // expected-error {{redefinition of 'a'}}
>> >>> @@ -48,7 +48,7 @@ void testSwitch() {
>> >>>        ++a;
>> >>>    }
>> >>>
>> >>> -  switch (x, +x; int a = 0) { // expected-note {{previous definition is here}} expected-warning {{unused}}
>> >>> +  switch (x, +x; int a = 0) { // expected-note {{previous definition is here}}
>> >>>      case 0:
>> >>>        int a = 0; // expected-error {{redefinition of 'a'}} // expected-note {{previous definition is here}}
>> >>>      case 1:
>> >>>
>> >>> Modified: cfe/trunk/test/SemaCXX/for-range-examples.cpp
>> >>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/for-range-examples.cpp?rev=350404&r1=350403&r2=350404&view=diff
>> >>> ==============================================================================
>> >>> --- cfe/trunk/test/SemaCXX/for-range-examples.cpp (original)
>> >>> +++ cfe/trunk/test/SemaCXX/for-range-examples.cpp Fri Jan  4 08:58:14 2019
>> >>> @@ -244,7 +244,7 @@ void foo ()
>> >>>  {
>> >>>    int b = 1, a[b];
>> >>>    a[0] = 0;
>> >>> -  [&] { for (int c : a) 0; } ();
>> >>> +  [&] { for (int c : a) 0; } (); // expected-warning {{expression result unused}}
>> >>>  }
>> >>>
>> >>>
>> >>>
>> >>> Modified: cfe/trunk/test/SemaCXX/warn-unused-result.cpp
>> >>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-unused-result.cpp?rev=350404&r1=350403&r2=350404&view=diff
>> >>> ==============================================================================
>> >>> --- cfe/trunk/test/SemaCXX/warn-unused-result.cpp (original)
>> >>> +++ cfe/trunk/test/SemaCXX/warn-unused-result.cpp Fri Jan  4 08:58:14 2019
>> >>> @@ -33,6 +33,36 @@ void test() {
>> >>>    const S &s4 = g1();
>> >>>  }
>> >>>
>> >>> +void testSubstmts(int i) {
>> >>> +  switch (i) {
>> >>> +  case 0:
>> >>> +    f(); // expected-warning {{ignoring return value}}
>> >>> +  default:
>> >>> +    f(); // expected-warning {{ignoring return value}}
>> >>> +  }
>> >>> +
>> >>> +  if (i)
>> >>> +    f(); // expected-warning {{ignoring return value}}
>> >>> +  else
>> >>> +    f(); // expected-warning {{ignoring return value}}
>> >>> +
>> >>> +  while (i)
>> >>> +    f(); // expected-warning {{ignoring return value}}
>> >>> +
>> >>> +  do
>> >>> +    f(); // expected-warning {{ignoring return value}}
>> >>> +  while (i);
>> >>> +
>> >>> +  for (f(); // expected-warning {{ignoring return value}}
>> >>> +       ;
>> >>> +       f() // expected-warning {{ignoring return value}}
>> >>> +      )
>> >>> +    f(); // expected-warning {{ignoring return value}}
>> >>> +
>> >>> +  f(),  // expected-warning {{ignoring return value}}
>> >>> +  (void)f();
>> >>> +}
>> >>> +
>> >>>  struct X {
>> >>>   int foo() __attribute__((warn_unused_result));
>> >>>  };
>> >>> @@ -206,3 +236,13 @@ void f() {
>> >>>    (void)++p;
>> >>>  }
>> >>>  } // namespace
>> >>> +
>> >>> +namespace PR39837 {
>> >>> +[[clang::warn_unused_result]] int f(int);
>> >>> +
>> >>> +void g() {
>> >>> +  int a[2];
>> >>> +  for (int b : a)
>> >>> +    f(b); // expected-warning {{ignoring return value}}
>> >>> +}
>> >>> +} // namespace PR39837
>> >>>
>> >>>
>> >>> _______________________________________________
>> >>> cfe-commits mailing list
>> >>> cfe-commits at lists.llvm.org
>> >>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>> >>
>> >> _______________________________________________
>> >> cfe-commits mailing list
>> >> cfe-commits at lists.llvm.org
>> >> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


More information about the cfe-commits mailing list