Author: Paul Walker
Date: 2025-11-25T13:14:10Z
New Revision: 6bf3249fe9771c5732d993304ecee11f55927f9f

URL: 
https://github.com/llvm/llvm-project/commit/6bf3249fe9771c5732d993304ecee11f55927f9f
DIFF: 
https://github.com/llvm/llvm-project/commit/6bf3249fe9771c5732d993304ecee11f55927f9f.diff

LOG: [Clang][Sema] Emit diagnostic for __builtin_vectorelements(<SVEType>) when 
SVE is not available. (#168097)

As is done for other targets, I've moved the target type checking code
into SemaARM and migrated existing uses.

Fixes https://github.com/llvm/llvm-project/issues/155736

Added: 
    clang/test/Sema/AArch64/builtin_vectorelements.c

Modified: 
    clang/include/clang/Sema/SemaARM.h
    clang/lib/Sema/Sema.cpp
    clang/lib/Sema/SemaARM.cpp
    clang/lib/Sema/SemaDecl.cpp
    clang/lib/Sema/SemaExpr.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Sema/SemaARM.h 
b/clang/include/clang/Sema/SemaARM.h
index 104992e8826c3..1e8941a381dc5 100644
--- a/clang/include/clang/Sema/SemaARM.h
+++ b/clang/include/clang/Sema/SemaARM.h
@@ -96,6 +96,9 @@ class SemaARM : public SemaBase {
   bool checkTargetClonesAttr(SmallVectorImpl<StringRef> &Params,
                              SmallVectorImpl<SourceLocation> &Locs,
                              SmallVectorImpl<SmallString<64>> &NewParams);
+  bool checkSVETypeSupport(QualType Ty, SourceLocation Loc,
+                           const FunctionDecl *FD,
+                           const llvm::StringMap<bool> &FeatureMap);
 };
 
 SemaARM::ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD);

diff  --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 46addea232b03..1541b2cc95d8c 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -2254,16 +2254,10 @@ void Sema::checkTypeSupport(QualType Ty, SourceLocation 
Loc, ValueDecl *D) {
     }
 
     // Don't allow SVE types in functions without a SVE target.
-    if (Ty->isSVESizelessBuiltinType() && FD && !FD->getType().isNull()) {
+    if (Ty->isSVESizelessBuiltinType() && FD) {
       llvm::StringMap<bool> CallerFeatureMap;
       Context.getFunctionFeatureMap(CallerFeatureMap, FD);
-      if (!Builtin::evaluateRequiredTargetFeatures("sve", CallerFeatureMap)) {
-        if (!Builtin::evaluateRequiredTargetFeatures("sme", CallerFeatureMap))
-          Diag(Loc, diag::err_sve_vector_in_non_sve_target) << Ty;
-        else if (!IsArmStreamingFunction(FD,
-                                         /*IncludeLocallyStreaming=*/true))
-          Diag(Loc, diag::err_sve_vector_in_non_streaming_function) << Ty;
-      }
+      ARM().checkSVETypeSupport(Ty, Loc, FD, CallerFeatureMap);
     }
 
     if (auto *VT = Ty->getAs<VectorType>();

diff  --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp
index 39f37cc679efa..a5164a94b57fa 100644
--- a/clang/lib/Sema/SemaARM.cpp
+++ b/clang/lib/Sema/SemaARM.cpp
@@ -1684,4 +1684,24 @@ bool SemaARM::checkTargetClonesAttr(
   return false;
 }
 
+bool SemaARM::checkSVETypeSupport(QualType Ty, SourceLocation Loc,
+                                  const FunctionDecl *FD,
+                                  const llvm::StringMap<bool> &FeatureMap) {
+  if (!Ty->isSVESizelessBuiltinType())
+    return false;
+
+  if (FeatureMap.lookup("sve"))
+    return false;
+
+  // No SVE environment available.
+  if (!FeatureMap.lookup("sme"))
+    return Diag(Loc, diag::err_sve_vector_in_non_sve_target) << Ty;
+
+  // SVE environment only available to streaming functions.
+  if (FD && !FD->getType().isNull() &&
+      !IsArmStreamingFunction(FD, /*IncludeLocallyStreaming=*/true))
+    return Diag(Loc, diag::err_sve_vector_in_non_streaming_function) << Ty;
+
+  return false;
+}
 } // namespace clang

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 651437a6f4c30..7ad1f17263c4d 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9132,20 +9132,10 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) 
{
     const FunctionDecl *FD = cast<FunctionDecl>(CurContext);
     llvm::StringMap<bool> CallerFeatureMap;
     Context.getFunctionFeatureMap(CallerFeatureMap, FD);
-
-    if (!Builtin::evaluateRequiredTargetFeatures("sve", CallerFeatureMap)) {
-      if (!Builtin::evaluateRequiredTargetFeatures("sme", CallerFeatureMap)) {
-        Diag(NewVD->getLocation(), diag::err_sve_vector_in_non_sve_target) << 
T;
-        NewVD->setInvalidDecl();
-        return;
-      } else if (!IsArmStreamingFunction(FD,
-                                         /*IncludeLocallyStreaming=*/true)) {
-        Diag(NewVD->getLocation(),
-             diag::err_sve_vector_in_non_streaming_function)
-            << T;
-        NewVD->setInvalidDecl();
-        return;
-      }
+    if (ARM().checkSVETypeSupport(T, NewVD->getLocation(), FD,
+                                  CallerFeatureMap)) {
+      NewVD->setInvalidDecl();
+      return;
     }
   }
 

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index d3c2cc559ea20..c808dec12a6cf 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -4189,6 +4189,14 @@ static bool CheckVectorElementsTraitOperandType(Sema &S, 
QualType T,
            << ""
            << "__builtin_vectorelements" << T << ArgRange;
 
+  if (auto *FD = dyn_cast<FunctionDecl>(S.CurContext)) {
+    if (T->isSVESizelessBuiltinType()) {
+      llvm::StringMap<bool> CallerFeatureMap;
+      S.Context.getFunctionFeatureMap(CallerFeatureMap, FD);
+      return S.ARM().checkSVETypeSupport(T, Loc, FD, CallerFeatureMap);
+    }
+  }
+
   return false;
 }
 

diff  --git a/clang/test/Sema/AArch64/builtin_vectorelements.c 
b/clang/test/Sema/AArch64/builtin_vectorelements.c
new file mode 100644
index 0000000000000..3391da3fc81e1
--- /dev/null
+++ b/clang/test/Sema/AArch64/builtin_vectorelements.c
@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -fsyntax-only -verify %s
+// REQUIRES: aarch64-registered-target
+
+#include <arm_sve.h>
+
+__attribute__((target("sve")))
+long test_builtin_vectorelements_sve(void) {
+  return __builtin_vectorelements(svuint8_t);
+}
+
+__attribute__((target("sve2p1")))
+long test_builtin_vectorelements_sve2p1(void) {
+  return __builtin_vectorelements(svuint8_t);
+}
+
+long test_builtin_vectorelements_no_sve(void) {
+  // expected-error@+1 {{SVE vector type 'svuint8_t' (aka '__SVUint8_t') 
cannot be used in a target without sve}}
+  return __builtin_vectorelements(svuint8_t);
+}
+
+__attribute__((target("sme")))
+long test_builtin_vectorelements_sme_streaming(void) __arm_streaming {
+  return __builtin_vectorelements(svuint8_t);
+}
+
+__attribute__((target("sme2p1")))
+long test_builtin_vectorelements_sme2p1_streaming(void) __arm_streaming {
+  return __builtin_vectorelements(svuint8_t);
+}
+
+__attribute__((target("sme")))
+long test_builtin_vectorelements_sme(void) {
+  // expected-error@+1 {{SVE vector type 'svuint8_t' (aka '__SVUint8_t') 
cannot be used in a non-streaming function}}
+  return __builtin_vectorelements(svuint8_t);
+}
+
+__attribute__((target("sve,sme")))
+long test_builtin_vectorelements_sve_sme_streaming_compatible(void) 
__arm_streaming_compatible {
+  return __builtin_vectorelements(svuint8_t);
+}
+
+__attribute__((target("sme")))
+long test_builtin_vectorelements_sme_streaming_compatible(void) 
__arm_streaming_compatible {
+  // expected-error@+1 {{SVE vector type 'svuint8_t' (aka '__SVUint8_t') 
cannot be used in a non-streaming function}}
+  return __builtin_vectorelements(svuint8_t);
+}


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to