diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 288e8232ca7444..054b81c4a72b51 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10754,6 +10754,9 @@ def err_multiversion_noproto : Error< def err_multiversion_disallowed_other_attr : Error< "attribute '%select{target|cpu_specific|cpu_dispatch}0' multiversioning cannot be combined" " with attribute %1">; +def err_multiversion_mismatched_attrs + : Error<"attributes on multiversioned functions must all match, attribute " + "%0 %select{is missing|has different arguments}1">; def err_multiversion_diff : Error< "multiversioned function declaration has a different %select{calling convention" "|return type|constexpr specification|inline specification|storage class|" diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index ba05b0d32cf4c1..77e15f187e538c 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -10029,11 +10029,16 @@ static bool CheckMultiVersionValue(Sema &S, const FunctionDecl *FD) { // multiversion functions. static bool AttrCompatibleWithMultiVersion(attr::Kind Kind, MultiVersionKind MVType) { + // Note: this list/diagnosis must match the list in + // checkMultiversionAttributesAllSame. switch (Kind) { default: return false; case attr::Used: return MVType == MultiVersionKind::Target; + case attr::NonNull: + case attr::NoThrow: + return true; } } @@ -10201,8 +10206,6 @@ static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD, MVType == MultiVersionKind::CPUDispatch || MVType == MultiVersionKind::CPUSpecific; - // For now, disallow all other attributes. These should be opt-in, but - // an analysis of all of them is a future FIXME. if (CausesMV && OldFD && checkNonMultiVersionCompatAttributes(S, OldFD, NewFD, MVType)) return true; diff --git a/clang/test/Sema/attr-cpuspecific.c b/clang/test/Sema/attr-cpuspecific.c index e32c7a22894d6a..9cfeef8a23562a 100644 --- a/clang/test/Sema/attr-cpuspecific.c +++ b/clang/test/Sema/attr-cpuspecific.c @@ -115,3 +115,5 @@ int use3(void) { // expected-warning@+1 {{CPU list contains duplicate entries; attribute ignored}} int __attribute__((cpu_dispatch(pentium_iii, pentium_iii_no_xmm_regs))) dupe_p3(void); + +void __attribute__((cpu_specific(atom), nothrow, nonnull(1))) addtl_attrs(int*); diff --git a/clang/test/Sema/attr-target-mv.c b/clang/test/Sema/attr-target-mv.c index 33a2c4fa54ebf0..3f072b19083f3e 100644 --- a/clang/test/Sema/attr-target-mv.c +++ b/clang/test/Sema/attr-target-mv.c @@ -101,3 +101,10 @@ __vectorcall int __attribute__((target("arch=sandybridge"))) diff_cc(void); int __attribute__((target("sse4.2"))) diff_ret(void); // expected-error@+1 {{multiversioned function declaration has a different return type}} short __attribute__((target("arch=sandybridge"))) diff_ret(void); + +void __attribute__((target("sse4.2"), nothrow, used, nonnull(1))) addtl_attrs5(int*); +void __attribute__((target("arch=sandybridge"))) addtl_attrs5(int*); + +void __attribute__((target("sse4.2"))) addtl_attrs6(int*); +void __attribute__((target("arch=sandybridge"), nothrow, used, nonnull)) addtl_attrs6(int*); +