Index: clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp =================================================================== --- clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp +++ clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp @@ -47,6 +47,25 @@ return InnerMatcher.matches(*E, Finder, Builder); } +AST_MATCHER(ImplicitCastExpr, isArrayToPointerDecay) { + return Node.getCastKind() == CK_ArrayToPointerDecay; +} + +AST_MATCHER(ImplicitCastExpr, sysSymbolDecayInSysHeader) { + auto &SM = Finder->getASTContext().getSourceManager(); + if (SM.isInSystemMacro(Node.getLocStart())) { + if (isa(Node.getSubExpr())) + return true; + + if (const auto *SymbolDeclRef = dyn_cast(Node.getSubExpr())) { + const ValueDecl *SymbolDecl = SymbolDeclRef->getDecl(); + if (SymbolDecl && SM.isInSystemHeader(SymbolDecl->getLocation())) + return true; + } + } + return false; +} + void ProBoundsArrayToPointerDecayCheck::registerMatchers(MatchFinder *Finder) { if (!getLangOpts().CPlusPlus) return; @@ -56,10 +75,12 @@ // 2) inside a range-for over an array // 3) if it converts a string literal to a pointer Finder->addMatcher( - implicitCastExpr(unless(hasParent(arraySubscriptExpr())), + implicitCastExpr(isArrayToPointerDecay(), + unless(hasParent(arraySubscriptExpr())), unless(hasParentIgnoringImpCasts(explicitCastExpr())), unless(isInsideOfRangeBeginEndStmt()), - unless(hasSourceExpression(stringLiteral()))) + unless(hasSourceExpression(stringLiteral())), + unless(sysSymbolDecayInSysHeader())) .bind("cast"), this); } @@ -67,8 +88,6 @@ void ProBoundsArrayToPointerDecayCheck::check( const MatchFinder::MatchResult &Result) { const auto *MatchedCast = Result.Nodes.getNodeAs("cast"); - if (MatchedCast->getCastKind() != CK_ArrayToPointerDecay) - return; diag(MatchedCast->getExprLoc(), "do not implicitly decay an array into a " "pointer; consider using gsl::array_view or " Index: test/clang-tidy/Inputs/cppcoreguidelines-pro-bounds-array-to-pointer-decay/macro.h =================================================================== --- /dev/null +++ test/clang-tidy/Inputs/cppcoreguidelines-pro-bounds-array-to-pointer-decay/macro.h @@ -0,0 +1,14 @@ +const char SYS_STRING[2] = "s"; +const int SYS_INT_ARRAY[2] = {0, 0}; + +void sys_fn_decay_str(const char *); +void sys_fn_decay_int_array(const int *); + +#define sys_macro_with_pretty_function_string_decay sys_fn_decay_str(__PRETTY_FUNCTION__) +#define sys_macro_with_sys_string_decay sys_fn_decay_str(SYS_STRING) +#define sys_macro_with_sys_int_array_decay sys_fn_decay_int_array(SYS_INT_ARRAY) + +#define user_code_in_sys_macro(expr) expr; + +#define decay_to_char_pointer_in_macro(expr) sys_fn_decay_str(expr) +#define decay_to_int_pointer_in_macro(expr) sys_fn_decay_int_array(expr) Index: test/clang-tidy/cppcoreguidelines-pro-bounds-array-to-pointer-decay.cpp =================================================================== --- test/clang-tidy/cppcoreguidelines-pro-bounds-array-to-pointer-decay.cpp +++ test/clang-tidy/cppcoreguidelines-pro-bounds-array-to-pointer-decay.cpp @@ -1,5 +1,7 @@ -// RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-array-to-pointer-decay %t +// RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-array-to-pointer-decay %t -- -- -isystem%S/Inputs/cppcoreguidelines-pro-bounds-array-to-pointer-decay + #include +#include namespace gsl { template @@ -45,3 +47,49 @@ void *a[2]; f2(static_cast(a)); // OK, explicit cast } + +void user_fn_decay_str(const char *); +void user_fn_decay_int_array(const int *); +void bug32239() { + sys_macro_with_pretty_function_string_decay; // Ok + sys_macro_with_sys_string_decay; // Ok + sys_macro_with_sys_int_array_decay; // Ok + + sys_fn_decay_str(__PRETTY_FUNCTION__); // Not Ok - should it be ok? + // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: do not implicitly decay an array into a pointer; consider using gsl::array_view or an explicit cast instead [cppcoreguidelines-pro-bounds-array-to-pointer-decay] + + sys_fn_decay_str(SYS_STRING); // Not Ok - should it be ok? + // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: do not implicitly decay an array into a pointer; consider using gsl::array_view or an explicit cast instead [cppcoreguidelines-pro-bounds-array-to-pointer-decay] + + sys_fn_decay_int_array(SYS_INT_ARRAY); // Not Ok + // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: do not implicitly decay an array into a pointer; consider using gsl::array_view or an explicit cast instead [cppcoreguidelines-pro-bounds-array-to-pointer-decay] + + user_code_in_sys_macro(sys_fn_decay_str(__PRETTY_FUNCTION__)); // Not Ok - should it be ok? + // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: do not implicitly decay an array into a pointer; consider using gsl::array_view or an explicit cast instead [cppcoreguidelines-pro-bounds-array-to-pointer-decay] + + user_code_in_sys_macro(sys_fn_decay_str(SYS_STRING)); // Not Ok - should it be ok? + // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: do not implicitly decay an array into a pointer; consider using gsl::array_view or an explicit cast instead [cppcoreguidelines-pro-bounds-array-to-pointer-decay] + + user_code_in_sys_macro(sys_fn_decay_int_array(SYS_INT_ARRAY)); // Not Ok + // CHECK-MESSAGES: :[[@LINE-1]]:49: warning: do not implicitly decay an array into a pointer; consider using gsl::array_view or an explicit cast instead [cppcoreguidelines-pro-bounds-array-to-pointer-decay] + + const char UserString[1] = ""; + decay_to_char_pointer_in_macro(UserString); // Not Ok + // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: do not implicitly decay an array into a pointer; consider using gsl::array_view or an explicit cast instead [cppcoreguidelines-pro-bounds-array-to-pointer-decay] + + decay_to_char_pointer_in_macro(__PRETTY_FUNCTION__); // Not Ok + // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: do not implicitly decay an array into a pointer; consider using gsl::array_view or an explicit cast instead [cppcoreguidelines-pro-bounds-array-to-pointer-decay] + + int a[5]; + decay_to_int_pointer_in_macro(a); // Not Ok + // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: do not implicitly decay an array into a pointer; consider using gsl::array_view or an explicit cast instead [cppcoreguidelines-pro-bounds-array-to-pointer-decay] + + user_fn_decay_str(__PRETTY_FUNCTION__); // Not Ok - should it be ok? + // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: do not implicitly decay an array into a pointer; consider using gsl::array_view or an explicit cast instead [cppcoreguidelines-pro-bounds-array-to-pointer-decay] + + user_fn_decay_str(SYS_STRING); // Not Ok - should it be ok? + // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: do not implicitly decay an array into a pointer; consider using gsl::array_view or an explicit cast instead [cppcoreguidelines-pro-bounds-array-to-pointer-decay] + + user_fn_decay_int_array(SYS_INT_ARRAY); // Not ok + // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: do not implicitly decay an array into a pointer; consider using gsl::array_view or an explicit cast instead [cppcoreguidelines-pro-bounds-array-to-pointer-decay] +}