Author: AMS21 Date: 2023-06-18T11:40:33Z New Revision: c96306db2cad4cf687cb044c8a0635f982a4db98
URL: https://github.com/llvm/llvm-project/commit/c96306db2cad4cf687cb044c8a0635f982a4db98 DIFF: https://github.com/llvm/llvm-project/commit/c96306db2cad4cf687cb044c8a0635f982a4db98.diff LOG: [clang-tidy] Fix `llvmlibc-inline-function-decl` false positives for templated function definitions For a declaration the `FunctionDecl` begin location does not include the template parameter lists, but for some reason if you have a separate definitions to the declaration the begin location does include them. With this patch we now correctly handle that case. This fixes llvm#62746 Reviewed By: PiotrZSL Differential Revision: https://reviews.llvm.org/D153218 Added: Modified: clang-tools-extra/clang-tidy/llvmlibc/InlineFunctionDeclCheck.cpp clang-tools-extra/docs/ReleaseNotes.rst clang-tools-extra/test/clang-tidy/checkers/llvmlibc/inline-function-decl.hpp Removed: ################################################################################ diff --git a/clang-tools-extra/clang-tidy/llvmlibc/InlineFunctionDeclCheck.cpp b/clang-tools-extra/clang-tidy/llvmlibc/InlineFunctionDeclCheck.cpp index fa643a138792a..f901cd115a8ff 100644 --- a/clang-tools-extra/clang-tidy/llvmlibc/InlineFunctionDeclCheck.cpp +++ b/clang-tools-extra/clang-tidy/llvmlibc/InlineFunctionDeclCheck.cpp @@ -8,6 +8,7 @@ #include "InlineFunctionDeclCheck.h" #include "../utils/FileExtensionsUtils.h" +#include "../utils/LexerUtils.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" @@ -17,6 +18,27 @@ using namespace clang::ast_matchers; namespace clang::tidy::llvm_libc { +namespace { + +const TemplateParameterList * +getLastTemplateParameterList(const FunctionDecl *FuncDecl) { + const TemplateParameterList *ReturnList = + FuncDecl->getDescribedTemplateParams(); + + if (!ReturnList) { + const unsigned NumberOfTemplateParameterLists = + FuncDecl->getNumTemplateParameterLists(); + + if (NumberOfTemplateParameterLists > 0) + ReturnList = FuncDecl->getTemplateParameterList( + NumberOfTemplateParameterLists - 1); + } + + return ReturnList; +} + +} // namespace + InlineFunctionDeclCheck::InlineFunctionDeclCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), @@ -34,16 +56,28 @@ void InlineFunctionDeclCheck::check(const MatchFinder::MatchResult &Result) { return; SourceLocation SrcBegin = FuncDecl->getBeginLoc(); + + // If we have a template parameter list, we need to skip that because the + // LIBC_INLINE macro must be placed after that. + if (const TemplateParameterList *TemplateParams = + getLastTemplateParameterList(FuncDecl)) { + SrcBegin = TemplateParams->getRAngleLoc(); + std::optional<Token> NextToken = + utils::lexer::findNextTokenSkippingComments( + SrcBegin, *Result.SourceManager, Result.Context->getLangOpts()); + if (NextToken) + SrcBegin = NextToken->getLocation(); + } + // Consider functions only in header files. if (!utils::isSpellingLocInHeaderFile(SrcBegin, *Result.SourceManager, HeaderFileExtensions)) return; // Ignore lambda functions as they are internal and implicit. - if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(FuncDecl)) { + if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(FuncDecl)) if (MethodDecl->getParent()->isLambda()) return; - } // Check if decl starts with LIBC_INLINE auto Loc = FullSourceLoc(Result.SourceManager->getFileLoc(SrcBegin), diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 32864fc13d834..7fa744d173649 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -325,6 +325,10 @@ Changes in existing checks <clang-tidy/checks/llvm/header-guard>` check. Global options of the same name should be used instead. +- Fix false positive in :doc:`llvmlibc-inline-function-decl + <clang-tidy/checks/llvmlibc/inline-function-decl>` when using templated + function with separate declarations and definitions. + - Improved the performance of the :doc:`misc-confusable-identifiers <clang-tidy/checks/misc/confusable-identifiers>` check through optimizations. diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvmlibc/inline-function-decl.hpp b/clang-tools-extra/test/clang-tidy/checkers/llvmlibc/inline-function-decl.hpp index 24d0441742a7f..ab4410ad4fb47 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/llvmlibc/inline-function-decl.hpp +++ b/clang-tools-extra/test/clang-tidy/checkers/llvmlibc/inline-function-decl.hpp @@ -68,6 +68,197 @@ LIBC_INLINE void lambda() { [](){}; } +namespace issue_62746 { + +void goodSimpleFunction(); +void badSimpleFunction(); +void badSimpleFunctionWrongLocation(); + +LIBC_INLINE void goodSimpleFunction() {} + +inline void badSimpleFunction() {} +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: 'badSimpleFunction' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl] + +void LIBC_INLINE badSimpleFunctionWrongLocation() {} +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: 'badSimpleFunctionWrongLocation' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl] + +template <typename T> +void goodTemplateFunction(); +template <typename T> +void badTemplateFunction(); +template <typename T> +void badTemplateFunctionWrongLocation(); + +template <typename T> LIBC_INLINE void goodTemplateFunction() {} + +template <typename T> inline void badTemplateFunction() {} +// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: 'badTemplateFunction' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl] + +template <typename T> void LIBC_INLINE badTemplateFunctionWrongLocation() {} +// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: 'badTemplateFunctionWrongLocation' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl] + +template <typename... Ts> +void goodVariadicFunction(); +template <typename... Ts> +void badVariadicFunction(); +template <typename... Ts> +void badVariadicFunctionWrongLocation(); + +template <typename... Ts> LIBC_INLINE void goodVariadicFunction() {} + +template <typename... Ts> inline void badVariadicFunction() {} +// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: 'badVariadicFunction' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl] + +template <typename... Ts> void LIBC_INLINE badVariadicFunctionWrongLocation() {} +// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: 'badVariadicFunctionWrongLocation' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl] + +struct NoTemplate { + void goodNoTemplate(); + void badNoTemplate(); + void badNoTemplateWrongLocation(); + + template <typename T> + void goodNestedTemplate(); + template <typename T> + void badNestedTemplate(); + template <typename T> + void badNestedTemplateWrongLocation(); + + template <typename... Ts> + void goodVariadicTemplate(); + template <typename... Ts> + void badVariadicTemplate(); + template <typename... Ts> + void badVariadicTemplateWrongLocation(); + +}; + +LIBC_INLINE void NoTemplate::goodNoTemplate() {} + +inline void NoTemplate::badNoTemplate() {} +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: 'badNoTemplate' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl] + +void LIBC_INLINE NoTemplate::badNoTemplateWrongLocation() {} +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: 'badNoTemplateWrongLocation' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl] + +template <typename T> LIBC_INLINE void NoTemplate::goodNestedTemplate() {} + +template <typename T> inline void NoTemplate::badNestedTemplate() {} +// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: 'badNestedTemplate' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl] + +template <typename T> void LIBC_INLINE NoTemplate::badNestedTemplateWrongLocation() {} +// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: 'badNestedTemplateWrongLocation' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl] + +template <typename... Ts> LIBC_INLINE void NoTemplate::goodVariadicTemplate() {} + +template <typename... Ts> void inline NoTemplate::badVariadicTemplate() {} +// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: 'badVariadicTemplate' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl] + +template <typename... Ts> void LIBC_INLINE NoTemplate::badVariadicTemplateWrongLocation() {} +// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: 'badVariadicTemplateWrongLocation' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl] + +template <typename T> +struct SimpleTemplate { + void goodSimpleTemplate(); + void badSimpleTemplate(); + void badSimpleTemplateWrongLocation(); + + template <typename U> + void goodNestedTemplate(); + template <typename U> + void badNestedTemplate(); + template <typename U> + void badNestedTemplateWrongLocation(); + + template <typename... Ts> + void goodNestedVariadicTemplate(); + template <typename... Ts> + void badNestedVariadicTemplate(); + template <typename... Ts> + void badNestedVariadicTemplateWrongLocation(); +}; + +template <typename T> LIBC_INLINE void SimpleTemplate<T>::goodSimpleTemplate() {} + +template <typename T> inline void SimpleTemplate<T>::badSimpleTemplate() {} +// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: 'badSimpleTemplate' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl] + +template <typename T> void LIBC_INLINE SimpleTemplate<T>::badSimpleTemplateWrongLocation() {} +// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: 'badSimpleTemplateWrongLocation' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl] + +template <typename T> template <typename U> LIBC_INLINE void SimpleTemplate<T>::goodNestedTemplate() {} + +template <typename T> template <typename U> inline void SimpleTemplate<T>::badNestedTemplate() {} +// CHECK-MESSAGES: :[[@LINE-1]]:45: warning: 'badNestedTemplate' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl] + +template <typename T> template <typename U> void LIBC_INLINE SimpleTemplate<T>::badNestedTemplateWrongLocation() {} +// CHECK-MESSAGES: :[[@LINE-1]]:45: warning: 'badNestedTemplateWrongLocation' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl] + +template <typename T> template <typename... Ts> LIBC_INLINE void SimpleTemplate<T>::goodNestedVariadicTemplate() {} + +template <typename T> template <typename... Ts> inline void SimpleTemplate<T>::badNestedVariadicTemplate() {} +// CHECK-MESSAGES: :[[@LINE-1]]:49: warning: 'badNestedVariadicTemplate' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl] + +template <typename T> template <typename... Ts> void LIBC_INLINE SimpleTemplate<T>::badNestedVariadicTemplateWrongLocation() {} +// CHECK-MESSAGES: :[[@LINE-1]]:49: warning: 'badNestedVariadicTemplateWrongLocation' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl] + +template <typename... Ts> +struct VariadicTemplate { + void goodVariadicTemplate(); + void badVariadicTemplate(); + void badVariadicTemplateWrongLocation(); + + template <typename U> + void goodNestedTemplate(); + template <typename U> + void badNestedTemplate(); + template <typename U> + void badNestedTemplateWrongLocation(); + + template <typename... Us> + void goodNestedVariadicTemplate(); + template <typename... Us> + void badNestedVariadicTemplate(); + template <typename... Us> + void badNestedVariadicTemplateWrongLocation(); +}; + +template <typename... Ts> LIBC_INLINE void VariadicTemplate<Ts...>::goodVariadicTemplate() {} + +template <typename... Ts> inline void VariadicTemplate<Ts...>::badVariadicTemplate() {} +// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: 'badVariadicTemplate' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl] + +template <typename... Ts> void LIBC_INLINE VariadicTemplate<Ts...>::badVariadicTemplateWrongLocation() {} +// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: 'badVariadicTemplateWrongLocation' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl] + +template <typename... Ts> template <typename U> LIBC_INLINE void VariadicTemplate<Ts...>::goodNestedTemplate() {} + +template <typename... Ts> template <typename U> inline void VariadicTemplate<Ts...>::badNestedTemplate() {} +// CHECK-MESSAGES: :[[@LINE-1]]:49: warning: 'badNestedTemplate' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl] + +template <typename... Ts> template <typename U> void LIBC_INLINE VariadicTemplate<Ts...>::badNestedTemplateWrongLocation() {} +// CHECK-MESSAGES: :[[@LINE-1]]:49: warning: 'badNestedTemplateWrongLocation' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl] + +template <typename... Ts> template <typename... Us> LIBC_INLINE void VariadicTemplate<Ts...>::goodNestedVariadicTemplate() {} + +template <typename... Ts> template <typename... Us> inline void VariadicTemplate<Ts...>::badNestedVariadicTemplate() {} +// CHECK-MESSAGES: :[[@LINE-1]]:53: warning: 'badNestedVariadicTemplate' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl] + +template <typename... Ts> template <typename... Us> void LIBC_INLINE VariadicTemplate<Ts...>::badNestedVariadicTemplateWrongLocation() {} +// CHECK-MESSAGES: :[[@LINE-1]]:53: warning: 'badNestedVariadicTemplateWrongLocation' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl] + +template <typename T> +void goodWeirdFormatting(); +template <typename T> +void badWeirdFormatting(); + +template <typename T>LIBC_INLINE void goodWeirdFormatting() {} + +template <typename T>void LIBC_INLINE badWeirdFormatting() {} +// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: 'badWeirdFormatting' must be tagged with the LIBC_INLINE macro; the macro should be placed at the beginning of the declaration [llvmlibc-inline-function-decl] + +} // namespace issue_62746 + } // namespace __llvm_libc #endif // LLVM_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_CHECKERS_LLVMLIBC_INLINEFUNCTIONDECL_H _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits