diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/AST/Decl.h | 7 | ||||
| -rw-r--r-- | clang/lib/AST/Decl.cpp | 12 | ||||
| -rw-r--r-- | clang/lib/AST/Expr.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 15 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 4 | ||||
| -rw-r--r-- | clang/test/SemaCXX/warn-unused-result.cpp | 23 |
6 files changed, 49 insertions, 18 deletions
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 3e3d79ff29e..f8e17268e6c 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -1965,6 +1965,13 @@ public: return getType()->getAs<FunctionType>()->getCallResultType(getASTContext()); } + /// \brief Returns true if this function or its return type has the + /// warn_unused_result attribute. If the return type has the attribute and + /// this function is a method of the return type's class, then false will be + /// returned to avoid spurious warnings on member methods such as assignment + /// operators. + bool hasUnusedResultAttr() const; + /// \brief Returns the storage class as written in the source. For the /// computed linkage of symbol, see getLinkage. StorageClass getStorageClass() const { return StorageClass(SClass); } diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 69e44573dc6..2ae73de5074 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2822,6 +2822,18 @@ SourceRange FunctionDecl::getReturnTypeSourceRange() const { return RTRange; } +bool FunctionDecl::hasUnusedResultAttr() const { + QualType RetType = getReturnType(); + if (RetType->isRecordType()) { + const CXXRecordDecl *Ret = RetType->getAsCXXRecordDecl(); + const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(this); + if (Ret && Ret->hasAttr<WarnUnusedResultAttr>() && + !(MD && MD->getCorrespondingMethodInClass(Ret, true))) + return true; + } + return hasAttr<WarnUnusedResultAttr>(); +} + /// \brief For an inline function definition in C, or for a gnu_inline function /// in C++, determine whether the definition will be externally visible. /// diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index d4ec2714d59..76a4da2371b 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -2161,12 +2161,16 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, // If this is a direct call, get the callee. const CallExpr *CE = cast<CallExpr>(this); if (const Decl *FD = CE->getCalleeDecl()) { + const FunctionDecl *Func = dyn_cast<FunctionDecl>(FD); + bool HasWarnUnusedResultAttr = Func ? Func->hasUnusedResultAttr() + : FD->hasAttr<WarnUnusedResultAttr>(); + // If the callee has attribute pure, const, or warn_unused_result, warn // about it. void foo() { strlen("bar"); } should warn. // // Note: If new cases are added here, DiagnoseUnusedExprResult should be // updated to match for QoI. - if (FD->hasAttr<WarnUnusedResultAttr>() || + if (HasWarnUnusedResultAttr || FD->hasAttr<PureAttr>() || FD->hasAttr<ConstAttr>()) { WarnE = this; Loc = CE->getCallee()->getLocStart(); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index ce183d0adf4..1bad38f53b8 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -7489,23 +7489,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // Handle attributes. ProcessDeclAttributes(S, NewFD, D); - QualType RetType = NewFD->getReturnType(); - const CXXRecordDecl *Ret = RetType->isRecordType() ? - RetType->getAsCXXRecordDecl() : RetType->getPointeeCXXRecordDecl(); - if (!NewFD->isInvalidDecl() && !NewFD->hasAttr<WarnUnusedResultAttr>() && - Ret && Ret->hasAttr<WarnUnusedResultAttr>()) { - const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD); - // Attach WarnUnusedResult to functions returning types with that attribute. - // Don't apply the attribute to that type's own non-static member functions - // (to avoid warning on things like assignment operators) - if (!MD || MD->getParent() != Ret) - NewFD->addAttr(WarnUnusedResultAttr::CreateImplicit(Context)); - } - if (getLangOpts().OpenCL) { // OpenCL v1.1 s6.5: Using an address space qualifier in a function return // type declaration will generate a compilation error. - unsigned AddressSpace = RetType.getAddressSpace(); + unsigned AddressSpace = NewFD->getReturnType().getAddressSpace(); if (AddressSpace == LangAS::opencl_local || AddressSpace == LangAS::opencl_global || AddressSpace == LangAS::opencl_constant) { diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 5774f53c060..8b174f8d922 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -239,7 +239,9 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { // is written in a macro body, only warn if it has the warn_unused_result // attribute. if (const Decl *FD = CE->getCalleeDecl()) { - if (FD->hasAttr<WarnUnusedResultAttr>()) { + const FunctionDecl *Func = dyn_cast<FunctionDecl>(FD); + if (Func ? Func->hasUnusedResultAttr() + : FD->hasAttr<WarnUnusedResultAttr>()) { Diag(Loc, diag::warn_unused_result) << R1 << R2; return; } diff --git a/clang/test/SemaCXX/warn-unused-result.cpp b/clang/test/SemaCXX/warn-unused-result.cpp index 7bdb4245a95..01bc457ec20 100644 --- a/clang/test/SemaCXX/warn-unused-result.cpp +++ b/clang/test/SemaCXX/warn-unused-result.cpp @@ -44,6 +44,12 @@ void bah() { } namespace warn_unused_CXX11 { +class Status; +class Foo { + public: + Status doStuff(); +}; + struct [[clang::warn_unused_result]] Status { bool ok() const; Status& operator=(const Status& x); @@ -73,10 +79,23 @@ void lazy() { (void)DoYetAnotherThing(); DoSomething(); // expected-warning {{ignoring return value}} - DoSomethingElse(); // expected-warning {{ignoring return value}} - DoAnotherThing(); // expected-warning {{ignoring return value}} + DoSomethingElse(); + DoAnotherThing(); DoYetAnotherThing(); } + +template <typename T> +class [[clang::warn_unused_result]] StatusOr { +}; +StatusOr<int> doit(); +void test() { + Foo f; + f.doStuff(); // expected-warning {{ignoring return value}} + doit(); // expected-warning {{ignoring return value}} + + auto func = []() { return Status(); }; + func(); // expected-warning {{ignoring return value}} +} } namespace PR17587 { |

