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