[clang] 961da69 - Improve diagnostics for disallowed attributes used with multiversioning

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Tue Aug 4 07:40:39 PDT 2020


Author: Erich Keane
Date: 2020-08-04T07:40:27-07:00
New Revision: 961da69d7eafe44411d5ac9719209653d196f9e2

URL: https://github.com/llvm/llvm-project/commit/961da69d7eafe44411d5ac9719209653d196f9e2
DIFF: https://github.com/llvm/llvm-project/commit/961da69d7eafe44411d5ac9719209653d196f9e2.diff

LOG: Improve diagnostics for disallowed attributes used with multiversioning

Since we permit using SOME attributes (at the moment, just 1) with
multiversioning, we should improve the message as it still implies that
no attributes should be combined with multiversioning.

Added: 
    

Modified: 
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Sema/SemaDecl.cpp
    clang/test/Sema/attr-cpuspecific.c
    clang/test/Sema/attr-target-mv.c

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 91112860a2d0..288e8232ca74 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10751,9 +10751,9 @@ def err_multiversion_duplicate : Error<
   "multiversioned function redeclarations require identical target attributes">;
 def err_multiversion_noproto : Error<
   "multiversioned function must have a prototype">;
-def err_multiversion_no_other_attrs : Error<
+def err_multiversion_disallowed_other_attr : Error<
   "attribute '%select{target|cpu_specific|cpu_dispatch}0' multiversioning cannot be combined"
-  " with other attributes">;
+  " with attribute %1">;
 def err_multiversion_
diff  : Error<
   "multiversioned function declaration has a 
diff erent %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 531c2801bf92..ba05b0d32cf4 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -10037,23 +10037,37 @@ static bool AttrCompatibleWithMultiVersion(attr::Kind Kind,
   }
 }
 
-static bool HasNonMultiVersionAttributes(const FunctionDecl *FD,
-                                         MultiVersionKind MVType) {
+static bool checkNonMultiVersionCompatAttributes(Sema &S,
+                                                 const FunctionDecl *FD,
+                                                 const FunctionDecl *CausedFD,
+                                                 MultiVersionKind MVType) {
+  bool IsCPUSpecificCPUDispatchMVType =
+      MVType == MultiVersionKind::CPUDispatch ||
+      MVType == MultiVersionKind::CPUSpecific;
+  const auto Diagnose = [FD, CausedFD, IsCPUSpecificCPUDispatchMVType](
+                            Sema &S, const Attr *A) {
+    S.Diag(FD->getLocation(), diag::err_multiversion_disallowed_other_attr)
+        << IsCPUSpecificCPUDispatchMVType << A;
+    if (CausedFD)
+      S.Diag(CausedFD->getLocation(), diag::note_multiversioning_caused_here);
+    return true;
+  };
+
   for (const Attr *A : FD->attrs()) {
     switch (A->getKind()) {
     case attr::CPUDispatch:
     case attr::CPUSpecific:
       if (MVType != MultiVersionKind::CPUDispatch &&
           MVType != MultiVersionKind::CPUSpecific)
-        return true;
+        return Diagnose(S, A);
       break;
     case attr::Target:
       if (MVType != MultiVersionKind::Target)
-        return true;
+        return Diagnose(S, A);
       break;
     default:
       if (!AttrCompatibleWithMultiVersion(A->getKind(), MVType))
-        return true;
+        return Diagnose(S, A);
       break;
     }
   }
@@ -10189,16 +10203,12 @@ static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD,
 
   // 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 && HasNonMultiVersionAttributes(OldFD, MVType)) {
-    S.Diag(OldFD->getLocation(), diag::err_multiversion_no_other_attrs)
-        << IsCPUSpecificCPUDispatchMVType;
-    S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here);
+  if (CausesMV && OldFD &&
+      checkNonMultiVersionCompatAttributes(S, OldFD, NewFD, MVType))
     return true;
-  }
 
-  if (HasNonMultiVersionAttributes(NewFD, MVType))
-    return S.Diag(NewFD->getLocation(), diag::err_multiversion_no_other_attrs)
-           << IsCPUSpecificCPUDispatchMVType;
+  if (checkNonMultiVersionCompatAttributes(S, NewFD, nullptr, MVType))
+    return true;
 
   // Only allow transition to MultiVersion if it hasn't been used.
   if (OldFD && CausesMV && OldFD->isUsed(false))

diff  --git a/clang/test/Sema/attr-cpuspecific.c b/clang/test/Sema/attr-cpuspecific.c
index ae86742ca081..e32c7a22894d 100644
--- a/clang/test/Sema/attr-cpuspecific.c
+++ b/clang/test/Sema/attr-cpuspecific.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-linux-gnu  -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu  -fsyntax-only -verify %s -Wnonnull
 
 void __attribute__((cpu_specific(ivybridge))) no_default(void);
 void __attribute__((cpu_specific(sandybridge)))  no_default(void);
@@ -80,7 +80,7 @@ int __attribute((cpu_dispatch())) no_dispatch(void) {}
 // expected-error at +1 {{'cpu_specific' attribute takes at least 1 argument}}
 int __attribute((cpu_specific())) no_specific(void) {}
 
-//expected-error at +1 {{attribute 'cpu_specific' multiversioning cannot be combined}}
+//expected-error at +1 {{attribute 'cpu_specific' multiversioning cannot be combined with attribute 'used'}}
 void __attribute__((used,cpu_specific(sandybridge)))  addtl_attrs(void);
 
 void __attribute__((target("default"))) addtl_attrs2(void);

diff  --git a/clang/test/Sema/attr-target-mv.c b/clang/test/Sema/attr-target-mv.c
index e9156a6c73e7..33a2c4fa54eb 100644
--- a/clang/test/Sema/attr-target-mv.c
+++ b/clang/test/Sema/attr-target-mv.c
@@ -77,14 +77,14 @@ int prev_no_target2(void);
 int __attribute__((target("arch=ivybridge")))  prev_no_target2(void);
 
 void __attribute__((target("sse4.2"))) addtl_attrs(void);
-//expected-error at +2 {{attribute 'target' multiversioning cannot be combined}}
+//expected-error at +2 {{attribute 'target' multiversioning cannot be combined with attribute 'no_caller_saved_registers'}}
 void __attribute__((no_caller_saved_registers,target("arch=sandybridge")))
 addtl_attrs(void);
 
-//expected-error at +1 {{attribute 'target' multiversioning cannot be combined}}
+//expected-error at +1 {{attribute 'target' multiversioning cannot be combined with attribute 'no_caller_saved_registers'}}
 void __attribute__((target("default"), no_caller_saved_registers)) addtl_attrs2(void);
 
-//expected-error at +2 {{attribute 'target' multiversioning cannot be combined}}
+//expected-error at +2 {{attribute 'target' multiversioning cannot be combined with attribute 'no_caller_saved_registers'}}
 //expected-note at +2 {{function multiversioning caused by this declaration}}
 void __attribute__((no_caller_saved_registers,target("sse4.2"))) addtl_attrs3(void);
 void __attribute__((target("arch=sandybridge")))  addtl_attrs3(void);


        


More information about the cfe-commits mailing list