diff --git a/clang-tools-extra/clang-tidy/google/AvoidThrowingObjCExceptionCheck.cpp b/clang-tools-extra/clang-tidy/google/AvoidThrowingObjCExceptionCheck.cpp --- a/clang-tools-extra/clang-tidy/google/AvoidThrowingObjCExceptionCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/AvoidThrowingObjCExceptionCheck.cpp @@ -36,6 +36,22 @@ Result.Nodes.getNodeAs("raiseException"); auto SourceLoc = MatchedStmt == nullptr ? MatchedExpr->getSelectorStartLoc() : MatchedStmt->getThrowLoc(); + + // Early return on invalid locations. + if (SourceLoc.isInvalid()) + return; + + // If the match location was in a macro, check if the macro was in a system + // header. + if (SourceLoc.isMacroID()) { + SourceManager &SM = *Result.SourceManager; + auto MacroLoc = SM.getImmediateMacroCallerLoc(SourceLoc); + + // Matches in system header macros should be ignored. + if (SM.isInSystemHeader(MacroLoc)) + return; + } + diag(SourceLoc, "pass in NSError ** instead of throwing exception to indicate " "Objective-C errors"); diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -141,6 +141,10 @@ would be emitted for uninitialized members of an anonymous union despite there being an initializer for one of the other members. +- Fixed false positives in :doc:`google-objc-avoid-throwing-exception + ` check for exceptions + thrown by code emitted from macros in system headers. + - Improved :doc:`modernize-use-emplace ` check. diff --git a/clang-tools-extra/test/clang-tidy/checkers/google/Inputs/system-header-throw.h b/clang-tools-extra/test/clang-tidy/checkers/google/Inputs/system-header-throw.h new file mode 100644 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/google/Inputs/system-header-throw.h @@ -0,0 +1,6 @@ +#pragma clang system_header + +#define SYS_THROW(e) @throw e + +#define SYS_RAISE [NSException raise:@"example" format:@"fmt"] + diff --git a/clang-tools-extra/test/clang-tidy/checkers/google/objc-avoid-throwing-exception.m b/clang-tools-extra/test/clang-tidy/checkers/google/objc-avoid-throwing-exception.m --- a/clang-tools-extra/test/clang-tidy/checkers/google/objc-avoid-throwing-exception.m +++ b/clang-tools-extra/test/clang-tidy/checkers/google/objc-avoid-throwing-exception.m @@ -1,4 +1,5 @@ -// RUN: %check_clang_tidy %s google-objc-avoid-throwing-exception %t +// RUN: %check_clang_tidy %s google-objc-avoid-throwing-exception %t -- -- -I %S/Inputs/ + @class NSString; @interface NSException @@ -21,12 +22,29 @@ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass in NSError ** instead of throwing exception to indicate Objective-C errors [google-objc-avoid-throwing-exception] } +#include "system-header-throw.h" + +#define THROW(e) @throw e + +#define RAISE [NSException raise:@"example" format:@"fmt"] + - (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"]; + + NSException *e; + SYS_THROW(e); + + SYS_RAISE; + + THROW(e); + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass in NSError ** instead of throwing exception to indicate Objective-C errors [google-objc-avoid-throwing-exception] + + RAISE; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass in NSError ** instead of throwing exception to indicate Objective-C errors [google-objc-avoid-throwing-exception] } @end