Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3030,6 +3030,8 @@ def err_attribute_arm_feature_sve_bits_unsupported : Error< "%0 is only supported when '-msve-vector-bits=' is specified with a " "value of 128, 256, 512, 1024 or 2048.">; +def err_sve_vector_in_non_sve_target : Error< + "SVE vector type %0 cannot be used in a target without sve">; def err_attribute_requires_positive_integer : Error< "%0 attribute requires a %select{positive|non-negative}1 " "integral compile time constant expression">; Index: clang/lib/Basic/Targets/AArch64.h =================================================================== --- clang/lib/Basic/Targets/AArch64.h +++ clang/lib/Basic/Targets/AArch64.h @@ -115,6 +115,10 @@ bool hasFeature(StringRef Feature) const override; bool handleTargetFeatures(std::vector &Features, DiagnosticsEngine &Diags) override; + bool + initFeatureMap(llvm::StringMap &Features, DiagnosticsEngine &Diags, + StringRef CPU, + const std::vector &FeaturesVec) const override; bool hasBFloat16Type() const override; Index: clang/lib/Basic/Targets/AArch64.cpp =================================================================== --- clang/lib/Basic/Targets/AArch64.cpp +++ clang/lib/Basic/Targets/AArch64.cpp @@ -670,6 +670,26 @@ return true; } +bool AArch64TargetInfo::initFeatureMap( + llvm::StringMap &Features, DiagnosticsEngine &Diags, StringRef CPU, + const std::vector &FeaturesVec) const { + // FIXME: This should be based on the existing feature map in the backend. + std::vector UpdatedFeaturesVec; + for (const auto &Feature : FeaturesVec) { + if (Feature == "+sve2-bitperm" || Feature == "+sve2-aes" || + Feature == "+sve2-sha3" || Feature == "+sve2-sm4") { + UpdatedFeaturesVec.push_back("+sve2"); + UpdatedFeaturesVec.push_back("+sve"); + } else if (Feature == "+sve2") { + UpdatedFeaturesVec.push_back("+sve"); + } + + UpdatedFeaturesVec.push_back(Feature); + } + + return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec); +} + bool AArch64TargetInfo::hasBFloat16Type() const { return true; } Index: clang/lib/Sema/Sema.cpp =================================================================== --- clang/lib/Sema/Sema.cpp +++ clang/lib/Sema/Sema.cpp @@ -2007,6 +2007,15 @@ if (D) targetDiag(D->getLocation(), diag::note_defined_here, FD) << D; } + + // Don't allow SVE types in functions without a SVE target. + if (Ty->isVLSTBuiltinType() && FD && FD->hasBody()) { + llvm::StringMap CallerFeatureMap; + Context.getFunctionFeatureMap(CallerFeatureMap, FD); + if (!Builtin::evaluateRequiredTargetFeatures( + "sve", CallerFeatureMap)) + Diag(D->getLocation(), diag::err_sve_vector_in_non_sve_target) << Ty; + } }; CheckType(Ty); Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -8492,6 +8492,19 @@ NewVD->setInvalidDecl(); return; } + + // Check that SVE types are only used in functions with SVE available. + if (T->isVLSTBuiltinType() && CurContext->isFunctionOrMethod()) { + const FunctionDecl *FD = cast(CurContext); + llvm::StringMap CallerFeatureMap; + Context.getFunctionFeatureMap(CallerFeatureMap, FD); + if (!Builtin::evaluateRequiredTargetFeatures( + "sve", CallerFeatureMap)) { + Diag(NewVD->getLocation(), diag::err_sve_vector_in_non_sve_target) << T; + NewVD->setInvalidDecl(); + return; + } + } } /// Perform semantic checking on a newly-created variable Index: clang/test/Sema/arm-sve-target.cpp =================================================================== --- /dev/null +++ clang/test/Sema/arm-sve-target.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -DNONEON -std=c++11 -triple aarch64-arm-none-eabi -target-feature -sve %s + +// A target without sve should not be able to use sve types. + +void test_var() { + __SVFloat32_t x; // expected-error {{SVE vector type '__SVFloat32_t' cannot be used in a target without sve}} +} + +__attribute__((target("sve"))) +void test_var_target() { + __SVFloat32_t x; +} + +__attribute__((target("sve2"))) +void test_var_target2() { + __SVFloat32_t x; +} + +__attribute__((target("sve2-bitperm"))) +void test_var_target3() { + __SVFloat32_t x; +} + +__SVFloat32_t other_ret(); +__SVFloat32_t test_ret() { // expected-error {{SVE vector type '__SVFloat32_t' cannot be used in a target without sve}} + return other_ret(); +} + +__attribute__((target("sve"))) +__SVFloat32_t test_ret_target() { + return other_ret(); +} + +void test_arg(__SVFloat32_t arg) { // expected-error {{SVE vector type '__SVFloat32_t' cannot be used in a target without sve}} +} + +__attribute__((target("sve"))) +void test_arg_target(__SVFloat32_t arg) { +}