erichkeane created this revision. erichkeane added a reviewer: aaron.ballman. erichkeane requested review of this revision.
Allow multiversioning declarations to match when the actual formal linkage matches, not just when the storage class is identical. Additionally, change the ambiguous 'linkage' mismatch to be more specific and say 'language linkage'. https://reviews.llvm.org/D110255 Files: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaDecl.cpp clang/test/SemaCXX/attr-cpuspecific.cpp clang/test/SemaCXX/attr-target-mv.cpp
Index: clang/test/SemaCXX/attr-target-mv.cpp =================================================================== --- clang/test/SemaCXX/attr-target-mv.cpp +++ clang/test/SemaCXX/attr-target-mv.cpp @@ -27,17 +27,26 @@ static int __attribute__((target("sse4.2"))) bar(void) { return 0; } static int __attribute__((target("arch=sandybridge"))) bar(void); -//expected-error@+1 {{multiversioned function declaration has a different storage class}} +//expected-error@+1 {{multiversioned function declaration has a different linkage}} int __attribute__((target("arch=ivybridge"))) bar(void) {return 1;} static int __attribute__((target("default"))) bar(void) { return 2; } int __attribute__((target("sse4.2"))) bar2(void) { return 0; } -//expected-error@+1 {{multiversioned function declaration has a different storage class}} +//expected-error@+1 {{multiversioned function declaration has a different linkage}} static int __attribute__((target("arch=sandybridge"))) bar2(void); int __attribute__((target("arch=ivybridge"))) bar2(void) {return 1;} int __attribute__((target("default"))) bar2(void) { return 2; } +// no diagnostic, since this doesn't change the linkage. +int __attribute__((target("sse4.2"))) bar3(void) { return 0; } +extern int __attribute__((target("arch=sandybridge"))) bar2(void); + +namespace { +int __attribute__((target("sse4.2"))) bar4(void) { return 0; } +static int __attribute__((target("arch=sandybridge"))) bar4(void); +} + inline int __attribute__((target("sse4.2"))) baz(void) { return 0; } inline int __attribute__((target("arch=sandybridge"))) baz(void); //expected-error@+1 {{multiversioned function declaration has a different inline specification}} @@ -102,7 +111,7 @@ extern "C" { int __attribute__((target("sse4.2"))) diff_mangle(void) { return 0; } } -//expected-error@+1 {{multiversioned function declaration has a different linkage}} +//expected-error@+1 {{multiversioned function declaration has a different language linkage}} int __attribute__((target("arch=sandybridge"))) diff_mangle(void) { return 0; } // expected-error@+1 {{multiversioned functions do not yet support deduced return types}} Index: clang/test/SemaCXX/attr-cpuspecific.cpp =================================================================== --- clang/test/SemaCXX/attr-cpuspecific.cpp +++ clang/test/SemaCXX/attr-cpuspecific.cpp @@ -34,9 +34,19 @@ constexpr int __attribute__((cpu_specific(ivybridge))) foo2(void); static int __attribute__((cpu_specific(sandybridge))) bar(void); -//expected-error@+1 {{multiversioned function declaration has a different storage class}} +//expected-error@+1 {{multiversioned function declaration has a different linkage}} int __attribute__((cpu_dispatch(ivybridge))) bar(void) {} +// OK +extern int __attribute__((cpu_specific(sandybridge))) bar2(void); +int __attribute__((cpu_dispatch(ivybridge))) bar2(void) {} + +namespace { +int __attribute__((cpu_specific(sandybridge))) bar3(void); +static int __attribute__((cpu_dispatch(ivybridge))) bar3(void) {} +} + + inline int __attribute__((cpu_specific(sandybridge))) baz(void); //expected-error@+1 {{multiversioned function declaration has a different inline specification}} int __attribute__((cpu_specific(ivybridge))) baz(void) {return 1;} @@ -74,7 +84,7 @@ extern "C" { int __attribute__((cpu_specific(atom))) diff_mangle(void) { return 0; } } -//expected-error@+1 {{multiversioned function declaration has a different linkage}} +//expected-error@+1 {{multiversioned function declaration has a different language linkage}} int __attribute__((cpu_specific(sandybridge))) diff_mangle(void) { return 0; } __attribute__((cpu_specific(atom))) void DiffDecl(); Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -10320,8 +10320,8 @@ ReturnType = 1, ConstexprSpec = 2, InlineSpec = 3, - StorageClass = 4, - Linkage = 5, + Linkage = 4, + LanguageLinkage = 5, }; if (NoProtoDiagID.getDiagID() != 0 && OldFD && @@ -10395,11 +10395,11 @@ if (OldFD->isInlineSpecified() != NewFD->isInlineSpecified()) return Diag(DiffDiagIDAt.first, DiffDiagIDAt.second) << InlineSpec; - if (OldFD->getStorageClass() != NewFD->getStorageClass()) - return Diag(DiffDiagIDAt.first, DiffDiagIDAt.second) << StorageClass; + if (OldFD->getFormalLinkage() != NewFD->getFormalLinkage()) + return Diag(DiffDiagIDAt.first, DiffDiagIDAt.second) << Linkage; if (!CLinkageMayDiffer && OldFD->isExternC() != NewFD->isExternC()) - return Diag(DiffDiagIDAt.first, DiffDiagIDAt.second) << Linkage; + return Diag(DiffDiagIDAt.first, DiffDiagIDAt.second) << LanguageLinkage; if (CheckEquivalentExceptionSpec( OldFD->getType()->getAs<FunctionProtoType>(), OldFD->getLocation(), Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -11208,8 +11208,8 @@ "%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|" - "linkage}0">; + "|return type|constexpr specification|inline specification|linkage|" + "language linkage}0">; def err_multiversion_doesnt_support : Error< "attribute '%select{target|cpu_specific|cpu_dispatch}0' multiversioned functions do not " "yet support %select{function templates|virtual functions|"
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits