Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add check to avoid throwing objc exception according to Google Object…
…ive-C guide Summary: This is a small check to avoid throwing objc exceptions. In specific it will detect the usage of @throw statement and throw warning. Reviewers: hokein, benhamilton Reviewed By: hokein, benhamilton Subscribers: cfe-commits, mgorny Differential Revision: https://reviews.llvm.org/D40058 llvm-svn: 318366
- Loading branch information
1 parent
35019db
commit 9994581
Showing
8 changed files
with
166 additions
and
0 deletions.
There are no files selected for viewing
47 changes: 47 additions & 0 deletions
47
clang-tools-extra/clang-tidy/google/AvoidThrowingObjCExceptionCheck.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
//===--- AvoidThrowingObjCExceptionCheck.cpp - clang-tidy------------------===// | ||
// | ||
// The LLVM Compiler Infrastructure | ||
// | ||
// This file is distributed under the University of Illinois Open Source | ||
// License. See LICENSE.TXT for details. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "AvoidThrowingObjCExceptionCheck.h" | ||
#include "clang/AST/ASTContext.h" | ||
#include "clang/ASTMatchers/ASTMatchFinder.h" | ||
|
||
using namespace clang::ast_matchers; | ||
|
||
namespace clang { | ||
namespace tidy { | ||
namespace google { | ||
namespace objc { | ||
|
||
void AvoidThrowingObjCExceptionCheck::registerMatchers(MatchFinder *Finder) { | ||
Finder->addMatcher(objcThrowStmt().bind("throwStmt"), this); | ||
Finder->addMatcher( | ||
objcMessageExpr(anyOf(hasSelector("raise:format:"), | ||
hasSelector("raise:format:arguments:")), | ||
hasReceiverType(asString("NSException"))) | ||
.bind("raiseException"), | ||
this); | ||
} | ||
|
||
void AvoidThrowingObjCExceptionCheck::check( | ||
const MatchFinder::MatchResult &Result) { | ||
const auto *MatchedStmt = | ||
Result.Nodes.getNodeAs<ObjCAtThrowStmt>("throwStmt"); | ||
const auto *MatchedExpr = | ||
Result.Nodes.getNodeAs<ObjCMessageExpr>("raiseException"); | ||
auto SourceLoc = MatchedStmt == nullptr ? MatchedExpr->getSelectorStartLoc() | ||
: MatchedStmt->getThrowLoc(); | ||
diag(SourceLoc, | ||
"pass in NSError ** instead of throwing exception to indicate " | ||
"Objective-C errors"); | ||
} | ||
|
||
} // namespace objc | ||
} // namespace google | ||
} // namespace tidy | ||
} // namespace clang |
39 changes: 39 additions & 0 deletions
39
clang-tools-extra/clang-tidy/google/AvoidThrowingObjCExceptionCheck.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
//===--- AvoidThrowingObjCExceptionCheck.h - clang-tidy----------*- C++ -*-===// | ||
// | ||
// The LLVM Compiler Infrastructure | ||
// | ||
// This file is distributed under the University of Illinois Open Source | ||
// License. See LICENSE.TXT for details. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_OBJC_AVOID_THROWING_EXCEPTION_H | ||
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_OBJC_AVOID_THROWING_EXCEPTION_H | ||
|
||
#include "../ClangTidy.h" | ||
|
||
namespace clang { | ||
namespace tidy { | ||
namespace google { | ||
namespace objc { | ||
|
||
/// The check is to find usage of @throw invocation in Objective-C code. | ||
/// We should avoid using @throw for Objective-C exceptions according to | ||
/// the Google Objective-C Style Guide. | ||
/// | ||
/// For the user-facing documentation see: | ||
/// http://clang.llvm.org/extra/clang-tidy/checks/google-objc-avoid-throwing-exception.html | ||
class AvoidThrowingObjCExceptionCheck : public ClangTidyCheck { | ||
public: | ||
AvoidThrowingObjCExceptionCheck(StringRef Name, ClangTidyContext *Context) | ||
: ClangTidyCheck(Name, Context) {} | ||
void registerMatchers(ast_matchers::MatchFinder *Finder) override; | ||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override; | ||
}; | ||
|
||
} // namespace objc | ||
} // namespace google | ||
} // namespace tidy | ||
} // namespace clang | ||
|
||
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_OBJC_AVOID_THROWING_EXCEPTION_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-throwing-exception.rst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
.. title:: clang-tidy - google-objc-avoid-throwing-exception | ||
|
||
google-objc-avoid-throwing-exception | ||
==================================== | ||
|
||
This check finds finds uses of throwing exceptions usages in Objective-C files. | ||
For the same reason as the Google C++ style guide, we prefer not throwing | ||
exceptions from Objective-C code. | ||
|
||
The corresponding C++ style guide rule: | ||
https://google.github.io/styleguide/cppguide.html#Exceptions | ||
|
||
Instead, prefer passing in ``NSError **`` and return ``BOOL`` to indicate success or failure. | ||
|
||
A counterexample: | ||
|
||
.. code-block:: objc | ||
- (void)readFile { | ||
if ([self isError]) { | ||
@throw [NSException exceptionWithName:...]; | ||
} | ||
} | ||
Instead, returning an error via ``NSError **`` is preferred: | ||
|
||
.. code-block:: objc | ||
- (BOOL)readFileWithError:(NSError **)error { | ||
if ([self isError]) { | ||
*error = [NSError errorWithDomain:...]; | ||
return NO; | ||
} | ||
return YES; | ||
} | ||
The corresponding style guide rule: | ||
http://google.github.io/styleguide/objcguide.html#avoid-throwing-exceptions |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
clang-tools-extra/test/clang-tidy/google-objc-avoid-throwing-exception.m
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// RUN: %check_clang_tidy %s google-objc-avoid-throwing-exception %t | ||
@class NSString; | ||
|
||
@interface NSException | ||
|
||
+ (void)raise:(NSString *)name format:(NSString *)format; | ||
+ (void)raise:(NSString *)name format:(NSString *)format arguments:(NSString *)args; // using NSString type since va_list cannot be recognized here | ||
|
||
@end | ||
|
||
@interface NotException | ||
|
||
+ (void)raise:(NSString *)name format:(NSString *)format; | ||
|
||
@end | ||
|
||
@implementation Foo | ||
- (void)f { | ||
NSString *foo = @"foo"; | ||
@throw foo; | ||
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass in NSError ** instead of throwing exception to indicate Objective-C errors [google-objc-avoid-throwing-exception] | ||
} | ||
|
||
- (void)f2 { | ||
[NSException raise:@"TestException" format:@"Test"]; | ||
// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: pass in NSError ** instead of throwing exception to indicate Objective-C errors [google-objc-avoid-throwing-exception] | ||
[NSException raise:@"TestException" format:@"Test %@" arguments:@"bar"]; | ||
// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: pass in NSError ** instead of throwing exception to indicate Objective-C errors [google-objc-avoid-throwing-exception] | ||
[NotException raise:@"NotException" format:@"Test"]; | ||
} | ||
@end | ||
|