diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 42fdf2b56dc27..61117cc5ce71f 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -2615,6 +2615,10 @@ class FunctionDecl : public DeclaratorDecl, /// the target functionality. bool isTargetMultiVersion() const; + /// True if this function is the default version of a multiversioned dispatch + /// function as a part of the target functionality. + bool isTargetMultiVersionDefault() const; + /// True if this function is a multiversioned dispatch function as a part of /// the target-clones functionality. bool isTargetClonesMultiVersion() const; diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 40e2903265bf3..e281f2d8874a7 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -3537,6 +3537,11 @@ bool FunctionDecl::isTargetMultiVersion() const { (hasAttr() || hasAttr()); } +bool FunctionDecl::isTargetMultiVersionDefault() const { + return isMultiVersion() && hasAttr() && + getAttr()->isDefaultVersion(); +} + bool FunctionDecl::isTargetClonesMultiVersion() const { return isMultiVersion() && hasAttr(); } diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 2d4e6d1d058cd..cfb653e665ea0 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1393,7 +1393,8 @@ void Sema::ActOnEndOfTranslationUnit() { Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl) << /*function=*/0 << DiagD << DiagRange; } - } else { + } else if (!FD->isTargetMultiVersion() || + FD->isTargetMultiVersionDefault()) { if (FD->getDescribedFunctionTemplate()) Diag(DiagD->getLocation(), diag::warn_unused_template) << /*function=*/0 << DiagD << DiagRange; diff --git a/clang/test/SemaCXX/warn-unused-filescoped.cpp b/clang/test/SemaCXX/warn-unused-filescoped.cpp index be8d350855c07..0c347e9e19c9d 100644 --- a/clang/test/SemaCXX/warn-unused-filescoped.cpp +++ b/clang/test/SemaCXX/warn-unused-filescoped.cpp @@ -236,4 +236,20 @@ constexpr int constexpr4() { return 2; } #endif } +__attribute__((target_version("fp16"))) +static int not_used_fmv(void) { return 1; } +__attribute__((target_version("fp16fml"))) +static int not_used_fmv(void) { return 2; } +__attribute__((target_version("default"))) +static int not_used_fmv(void) { return 0; } // expected-warning {{unused function 'not_used_fmv'}} + + +__attribute__((target_version("fp16"))) +static int definitely_used_fmv(void) { return 1; } +__attribute__((target_version("fp16fml"))) +static int definitely_used_fmv(void) { return 2; } +__attribute__((target_version("default"))) +static int definitely_used_fmv(void) { return 0; } +int definite_user(void) { return definitely_used_fmv(); } + #endif