diff options
-rw-r--r-- | include/clang/AST/Expr.h | 5 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 10 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 7 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 2 | ||||
-rw-r--r-- | test/Sema/unused-expr.c | 5 |
5 files changed, 21 insertions, 8 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 6807f2c5a2..1a615c1e3f 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -1176,6 +1176,11 @@ public: Expr *getCallee() { return cast<Expr>(SubExprs[FN]); } void setCallee(Expr *F) { SubExprs[FN] = F; } + Decl *getCalleeDecl(); + const Decl *getCalleeDecl() const { + return const_cast<CallExpr*>(this)->getCalleeDecl(); + } + /// \brief If the callee is a FunctionDecl, return it. Otherwise return 0. FunctionDecl *getDirectCallee(); const FunctionDecl *getDirectCallee() const { diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 034b91ed0f..466ddc663f 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -398,14 +398,18 @@ void CallExpr::DoDestroy(ASTContext& C) { C.Deallocate(this); } -FunctionDecl *CallExpr::getDirectCallee() { +Decl *CallExpr::getCalleeDecl() { Expr *CEE = getCallee()->IgnoreParenCasts(); if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) - return dyn_cast<FunctionDecl>(DRE->getDecl()); + return DRE->getDecl(); return 0; } +FunctionDecl *CallExpr::getDirectCallee() { + return dyn_cast_or_null<FunctionDecl>(getCalleeDecl()); +} + /// setNumArgs - This changes the number of arguments present in this call. /// Any orphaned expressions are deleted by this, and any new operands are set /// to null. @@ -858,7 +862,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, case CXXMemberCallExprClass: { // If this is a direct call, get the callee. const CallExpr *CE = cast<CallExpr>(this); - if (const FunctionDecl *FD = CE->getDirectCallee()) { + if (const Decl *FD = CE->getCalleeDecl()) { // If the callee has attribute pure, const, or warn_unused_result, warn // about it. void foo() { strlen("bar"); } should warn. // diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 84ee207338..718db0437f 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -47,7 +47,7 @@ static const FunctionType *getFunctionType(const Decl *d, // FIXME: We should provide an abstraction around a method or function // to provide the following bits of information. -/// isFunctionOrMethod - Return true if the given decl has function +/// isFunction - Return true if the given decl has function /// type (function or function-typed variable). static bool isFunction(const Decl *d) { return getFunctionType(d, false) != NULL; @@ -731,14 +731,13 @@ static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) } // TODO: could also be applied to methods? - FunctionDecl *Fn = dyn_cast<FunctionDecl>(D); - if (!Fn) { + if (!isFunctionOrMethod(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << 0 /*function*/; return; } - Fn->addAttr(::new (S.Context) WarnUnusedResultAttr()); + D->addAttr(::new (S.Context) WarnUnusedResultAttr()); } static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) { diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index c2a3a3a8ca..6a68db75ea 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -96,7 +96,7 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { if (const CallExpr *CE = dyn_cast<CallExpr>(E)) { // If the callee has attribute pure, const, or warn_unused_result, warn with // a more specific message to make it clear what is happening. - if (const FunctionDecl *FD = CE->getDirectCallee()) { + if (const Decl *FD = CE->getCalleeDecl()) { if (FD->getAttr<WarnUnusedResultAttr>()) { Diag(Loc, diag::warn_unused_call) << R1 << R2 << "warn_unused_result"; return; diff --git a/test/Sema/unused-expr.c b/test/Sema/unused-expr.c index 70f3446e53..284818dc58 100644 --- a/test/Sema/unused-expr.c +++ b/test/Sema/unused-expr.c @@ -96,3 +96,8 @@ int t6() { int t7 __attribute__ ((warn_unused_result)); // expected-warning {{warning: 'warn_unused_result' attribute only applies to function types}} +// PR4010 +int (*fn4)(void) __attribute__ ((warn_unused_result)); +void t8() { + fn4(); // expected-warning {{ignoring return value of function declared with warn_unused_result attribute}} +} |