Change error for storage-class to mean linkage, fix lang-linkage diag
authorErich Keane <erich.keane@intel.com>
Wed, 22 Sep 2021 14:25:50 +0000 (07:25 -0700)
committerErich Keane <erich.keane@intel.com>
Wed, 22 Sep 2021 17:51:05 +0000 (10:51 -0700)
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'.

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 3cadd98..0e803ee 100644 (file)
@@ -11208,8 +11208,8 @@ def err_multiversion_mismatched_attrs
             "%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|"
index 13389eb..7908009 100644 (file)
@@ -10322,8 +10322,8 @@ bool Sema::areMultiversionVariantFunctionsCompatible(
     ReturnType = 1,
     ConstexprSpec = 2,
     InlineSpec = 3,
-    StorageClass = 4,
-    Linkage = 5,
+    Linkage = 4,
+    LanguageLinkage = 5,
   };
 
   if (NoProtoDiagID.getDiagID() != 0 && OldFD &&
@@ -10397,11 +10397,11 @@ bool Sema::areMultiversionVariantFunctionsCompatible(
     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 861711b..fe46358 100644 (file)
@@ -34,9 +34,19 @@ int __attribute__((cpu_specific(sandybridge))) foo2(void);
 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 @@ struct S {
 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 5ef1d39..5b2f0fc 100644 (file)
@@ -27,17 +27,26 @@ int __attribute__((target("default"))) foo2(void) { return 2; }
 
 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 @@ struct S {
 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}}