diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -247,9 +247,18 @@ // If this is a GNU statement expression expanded from a macro, it is probably // unused because it is a function-like macro that can be used as either an // expression or statement. Don't warn, because it is almost certainly a - // false positive. - if (isa(E) && Loc.isMacroID()) + // false positive. But we do want to check CallExprs with + // WarnUnusedResultAttr. + if (isa(E) && Loc.isMacroID()) { + if (const CallExpr *CE = dyn_cast(WarnExpr)) + if (const Decl *FD = CE->getCalleeDecl()) + if (FD->hasAttr()) + DiagnoseNoDiscard(*this, + cast_or_null( + CE->getUnusedResultAttr(Context)), + Loc, R1, R2, /*isCtor=*/false); return; + } // Check if this is the UNREFERENCED_PARAMETER from the Microsoft headers. // That macro is frequently used to suppress "unused parameter" warnings, diff --git a/clang/test/Frontend/macros.c b/clang/test/Frontend/macros.c --- a/clang/test/Frontend/macros.c +++ b/clang/test/Frontend/macros.c @@ -1,5 +1,4 @@ -// RUN: %clang_cc1 -DA= -DB=1 -verify -fsyntax-only %s -// expected-no-diagnostics +// RUN: %clang_cc1 -Wunused-result -DA= -DB=1 -verify -fsyntax-only %s int a[(B A) == 1 ? 1 : -1]; @@ -11,3 +10,15 @@ void foo(int a, int b, int c) { memset(a,b,c); // No warning! } + +__attribute__((warn_unused_result)) static inline int bar(void) { + return 42; +} + +#define baz() ({ \ + bar(); \ +}) + +void quux(void) { + baz(); // expected-warning {{ignoring return value of function declared with 'warn_unused_result' attribute}} +}