This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG1f08b0867412: [clang][ARM] Emit warnings when PACBTI-M is 
used with unsupported architectures (authored by amilendra).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D115501/new/

https://reviews.llvm.org/D115501

Files:
  clang/include/clang/Basic/DiagnosticCommonKinds.td
  clang/include/clang/Basic/TargetInfo.h
  clang/lib/Basic/Targets/AArch64.cpp
  clang/lib/Basic/Targets/AArch64.h
  clang/lib/Basic/Targets/ARM.cpp
  clang/lib/Basic/Targets/ARM.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/CodeGen/TargetInfo.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/CodeGen/arm-branch-protection-attr-2.c
  clang/test/CodeGen/arm_acle.c
  clang/test/Driver/aarch64-security-options.c
  clang/test/Driver/arm-security-options.c
  clang/test/Frontend/arm-branch-protection-default-arch.c
  clang/test/Frontend/arm-ignore-branch-protection-option.c
  clang/test/Frontend/arm-invalid-branch-protection.c
  clang/test/Sema/arm-branch-protection-attr-warn.c
  clang/test/Sema/arm-branch-protection.c
  llvm/include/llvm/ADT/Triple.h
  llvm/unittests/ADT/TripleTest.cpp

Index: llvm/unittests/ADT/TripleTest.cpp
===================================================================
--- llvm/unittests/ADT/TripleTest.cpp
+++ llvm/unittests/ADT/TripleTest.cpp
@@ -1702,4 +1702,148 @@
     EXPECT_EQ(Triple::AArch64SubArch_arm64e, T.getSubArch());
   }
 }
+
+TEST(TripleTest, isArmT32) {
+  // Not isArmT32
+  {
+    Triple T = Triple("thumbv6m");
+    EXPECT_FALSE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv8m.base");
+    EXPECT_FALSE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv7s");
+    EXPECT_FALSE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv7k");
+    EXPECT_FALSE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv7ve");
+    EXPECT_FALSE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv6");
+    EXPECT_FALSE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv6m");
+    EXPECT_FALSE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv6k");
+    EXPECT_FALSE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv6t2");
+    EXPECT_FALSE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv5");
+    EXPECT_FALSE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv5te");
+    EXPECT_FALSE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv4t");
+    EXPECT_FALSE(T.isArmT32());
+  }
+
+  // isArmT32
+  {
+    Triple T = Triple("arm");
+    EXPECT_TRUE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv7m");
+    EXPECT_TRUE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv7em");
+    EXPECT_TRUE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv8m.main");
+    EXPECT_TRUE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv8.1m.main");
+    EXPECT_TRUE(T.isArmT32());
+  }
+}
+
+TEST(TripleTest, isArmMClass) {
+  // not M-class
+  {
+    Triple T = Triple("armv7s");
+    EXPECT_FALSE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("armv7k");
+    EXPECT_FALSE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("armv7ve");
+    EXPECT_FALSE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("armv6");
+    EXPECT_FALSE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("armv6k");
+    EXPECT_FALSE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("armv6t2");
+    EXPECT_FALSE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("armv5");
+    EXPECT_FALSE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("armv5te");
+    EXPECT_FALSE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("armv4t");
+    EXPECT_FALSE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("arm");
+    EXPECT_FALSE(T.isArmMClass());
+  }
+
+  // is M-class
+  {
+    Triple T = Triple("armv6m");
+    EXPECT_TRUE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("armv7m");
+    EXPECT_TRUE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("armv7em");
+    EXPECT_TRUE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("armv8m.base");
+    EXPECT_TRUE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("armv8m.main");
+    EXPECT_TRUE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("armv8.1m.main");
+    EXPECT_TRUE(T.isArmMClass());
+  }
+}
 } // end anonymous namespace
Index: llvm/include/llvm/ADT/Triple.h
===================================================================
--- llvm/include/llvm/ADT/Triple.h
+++ llvm/include/llvm/ADT/Triple.h
@@ -721,6 +721,41 @@
            isOSBinFormatELF();
   }
 
+  /// Tests whether the target is T32.
+  bool isArmT32() const {
+    switch (auto SubArch = getSubArch()) {
+    case Triple::ARMSubArch_v8m_baseline:
+    case Triple::ARMSubArch_v7s:
+    case Triple::ARMSubArch_v7k:
+    case Triple::ARMSubArch_v7ve:
+    case Triple::ARMSubArch_v6:
+    case Triple::ARMSubArch_v6m:
+    case Triple::ARMSubArch_v6k:
+    case Triple::ARMSubArch_v6t2:
+    case Triple::ARMSubArch_v5:
+    case Triple::ARMSubArch_v5te:
+    case Triple::ARMSubArch_v4t:
+      return false;
+    default:
+      return true;
+    }
+  }
+
+  /// Tests whether the target is an M-class.
+  bool isArmMClass() const {
+    switch (auto SubArch = getSubArch()) {
+    case Triple::ARMSubArch_v6m:
+    case Triple::ARMSubArch_v7m:
+    case Triple::ARMSubArch_v7em:
+    case Triple::ARMSubArch_v8m_mainline:
+    case Triple::ARMSubArch_v8m_baseline:
+    case Triple::ARMSubArch_v8_1m_mainline:
+      return true;
+    default:
+      return false;
+    }
+  }
+
   /// Tests whether the target is AArch64 (little and big endian).
   bool isAArch64() const {
     return getArch() == Triple::aarch64 || getArch() == Triple::aarch64_be ||
Index: clang/test/Sema/arm-branch-protection.c
===================================================================
--- /dev/null
+++ clang/test/Sema/arm-branch-protection.c
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -triple thumbv6m -verify -fsyntax-only %s
+
+// expected-no-diagnostics
+// Armv8.1-M.Main
+__attribute__((target("arch=cortex-m55,branch-protection=bti"))) void f1() {}
+__attribute__((target("arch=cortex-m55,branch-protection=pac-ret"))) void f2() {}
+__attribute__((target("arch=cortex-m55,branch-protection=bti+pac-ret"))) void f3() {}
+__attribute__((target("arch=cortex-m55,branch-protection=bti+pac-ret+leaf"))) void f4() {}
+// Armv8-M.Main
+__attribute__((target("arch=cortex-m33,branch-protection=bti"))) void f5() {}
+__attribute__((target("arch=cortex-m33,branch-protection=pac-ret"))) void f6() {}
+__attribute__((target("arch=cortex-m33,branch-protection=bti+pac-ret"))) void f7() {}
+__attribute__((target("arch=cortex-m33,branch-protection=bti+pac-ret+leaf"))) void f8() {}
+// Armv7-M
+__attribute__((target("arch=cortex-m3,branch-protection=bti"))) void f9() {}
+__attribute__((target("arch=cortex-m3,branch-protection=pac-ret"))) void f10() {}
+__attribute__((target("arch=cortex-m3,branch-protection=bti+pac-ret"))) void f11() {}
+__attribute__((target("arch=cortex-m3,branch-protection=bti+pac-ret+leaf"))) void f12() {}
+// Armv7E-M
+__attribute__((target("arch=cortex-m4,branch-protection=bti"))) void f13() {}
+__attribute__((target("arch=cortex-m4,branch-protection=pac-ret"))) void f14() {}
+__attribute__((target("arch=cortex-m4,branch-protection=bti+pac-ret"))) void f15() {}
+__attribute__((target("arch=cortex-m4,branch-protection=bti+pac-ret+leaf"))) void f16() {}
Index: clang/test/Sema/arm-branch-protection-attr-warn.c
===================================================================
--- /dev/null
+++ clang/test/Sema/arm-branch-protection-attr-warn.c
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple thumbv6m -verify -fsyntax-only %s
+
+// expected-warning@+1 {{unsupported 'branch-protection' in the 'target' attribute string; 'target' attribute ignored}}
+__attribute__((target("arch=cortex-m0,branch-protection=bti"))) void f1() {}
+
+// expected-warning@+1 {{unsupported 'branch-protection' in the 'target' attribute string; 'target' attribute ignored}}
+__attribute__((target("arch=cortex-m0,branch-protection=pac-ret"))) void f2() {}
+
+// expected-warning@+1 {{unsupported 'branch-protection' in the 'target' attribute string; 'target' attribute ignored}}
+__attribute__((target("arch=cortex-m0,branch-protection=bti+pac-ret"))) void f3() {}
+
+// expected-warning@+1 {{unsupported 'branch-protection' in the 'target' attribute string; 'target' attribute ignored}}
+__attribute__((target("arch=cortex-m0,branch-protection=bti+pac-ret+leaf"))) void f4() {}
+
+// expected-warning@+1 {{unsupported 'branch-protection' in the 'target' attribute string; 'target' attribute ignored}}
+__attribute__((target("arch=cortex-a17,thumb,branch-protection=bti+pac-ret+leaf"))) void f5() {}
Index: clang/test/Frontend/arm-invalid-branch-protection.c
===================================================================
--- clang/test/Frontend/arm-invalid-branch-protection.c
+++ clang/test/Frontend/arm-invalid-branch-protection.c
@@ -1,7 +1,7 @@
 // REQUIRES: arm-registered-target
-// RUN: %clang -target arm-arm-none-eabi -mbranch-protection=pac-ret+b-key -c %s -o /dev/null 2>&1 | FileCheck %s
-// RUN: %clang -target arm-arm-none-eabi -mbranch-protection=pac-ret+b-key+leaf -c %s -o /dev/null 2>&1 | FileCheck %s
-// RUN: %clang -target arm-arm-none-eabi -mbranch-protection=bti+pac-ret+b-key -c %s -o /dev/null 2>&1 | FileCheck %s
-// RUN: %clang -target arm-arm-none-eabi -mbranch-protection=bti+pac-ret+b-key+leaf -c %s -o /dev/null 2>&1 | FileCheck %s
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -mbranch-protection=pac-ret+b-key -c %s -o /dev/null 2>&1 | FileCheck %s
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -mbranch-protection=pac-ret+b-key+leaf -c %s -o /dev/null 2>&1 | FileCheck %s
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -mbranch-protection=bti+pac-ret+b-key -c %s -o /dev/null 2>&1 | FileCheck %s
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -mbranch-protection=bti+pac-ret+b-key+leaf -c %s -o /dev/null 2>&1 | FileCheck %s
 
 // CHECK: warning: invalid branch protection option 'b-key' in '-mbranch-protection={{[a-z+-]*}}' [-Wbranch-protection]
Index: clang/test/Frontend/arm-ignore-branch-protection-option.c
===================================================================
--- /dev/null
+++ clang/test/Frontend/arm-ignore-branch-protection-option.c
@@ -0,0 +1,18 @@
+// REQUIRES: arm-registered-target
+
+/// Check warning for
+// RUN: %clang -target arm-arm-none-eabi -march=armv7-m -mbranch-protection=bti %s -S -emit-llvm -o - 2>&1 | FileCheck %s
+
+__attribute__((target("arch=cortex-m0"))) void f() {}
+
+// CHECK: warning: ignoring the 'branch-protection' attribute because the 'cortex-m0' architecture does not support it [-Wbranch-protection]
+// CHECK-NEXT: __attribute__((target("arch=cortex-m0"))) void f() {}
+
+/// Check there are no branch protection function attributes
+
+// CHECK-NOT:  attributes { {{.*}} "sign-return-address"
+// CHECK-NOT:  attributes { {{.*}} "sign-return-address-key"
+// CHECK-NOT:  attributes { {{.*}} "branch-target-enforcement"
+
+/// Check that there are branch protection module attributes despite the warning.
+// CHECK: !{i32 1, !"branch-target-enforcement", i32 1}
Index: clang/test/Frontend/arm-branch-protection-default-arch.c
===================================================================
--- /dev/null
+++ clang/test/Frontend/arm-branch-protection-default-arch.c
@@ -0,0 +1,27 @@
+// REQUIRES: arm-registered-target
+
+/// Check warning for
+// RUN: %clang -target arm-arm-none-eabi %s -S -o - 2>&1 | FileCheck %s
+
+__attribute__((target("branch-protection=bti"))) void f1() {}
+__attribute__((target("branch-protection=pac-ret"))) void f2() {}
+__attribute__((target("branch-protection=bti+pac-ret"))) void f3() {}
+__attribute__((target("branch-protection=bti+pac-ret+leaf"))) void f4() {}
+
+// CHECK: warning: unsupported 'branch-protection' in the 'target' attribute string; 'target' attribute ignored [-Wignored-attributes]
+// CHECK-NEXT: __attribute__((target("branch-protection=bti"))) void f1() {}
+
+// CHECK: warning: unsupported 'branch-protection' in the 'target' attribute string; 'target' attribute ignored [-Wignored-attributes]
+// CHECK-NEXT: __attribute__((target("branch-protection=pac-ret"))) void f2() {}
+
+// CHECK: warning: unsupported 'branch-protection' in the 'target' attribute string; 'target' attribute ignored [-Wignored-attributes]
+// CHECK-NEXT: __attribute__((target("branch-protection=bti+pac-ret"))) void f3() {}
+
+// CHECK: warning: unsupported 'branch-protection' in the 'target' attribute string; 'target' attribute ignored [-Wignored-attributes]
+// CHECK-NEXT: __attribute__((target("branch-protection=bti+pac-ret+leaf"))) void f4() {}
+
+/// Check there are no branch protection function attributes
+
+// CHECK-NOT:  attributes { {{.*}} "sign-return-address"
+// CHECK-NOT:  attributes { {{.*}} "sign-return-address-key"
+// CHECK-NOT:  attributes { {{.*}} "branch-target-enforcement"
Index: clang/test/Driver/arm-security-options.c
===================================================================
--- clang/test/Driver/arm-security-options.c
+++ clang/test/Driver/arm-security-options.c
@@ -1,48 +1,80 @@
 // Check the -mbranch-protection=option
 
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=pac-ret 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=pac-ret 2>&1 | \
 // RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-A --check-prefix=BTE-OFF
 
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+leaf 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=pac-ret+leaf 2>&1 | \
 // RUN: FileCheck %s --check-prefix=RA-ALL --check-prefix=KEY-A --check-prefix=BTE-OFF
 
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+leaf+b-key 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=pac-ret+leaf+b-key 2>&1 | \
 // RUN: FileCheck %s --check-prefix=RA-ALL --check-prefix=KEY-B --check-prefix=BTE-OFF
 
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+b-key 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=pac-ret+b-key 2>&1 | \
 // RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-B --check-prefix=BTE-OFF
 
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=bti 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=bti 2>&1 | \
 // RUN: FileCheck %s --check-prefix=RA-OFF --check-prefix=BTE-ON
 
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=bti+pac-ret 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=bti+pac-ret 2>&1 | \
 // RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-A --check-prefix=BTE-ON
 
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=bti+pac-ret+leaf 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=bti+pac-ret+leaf 2>&1 | \
 // RUN: FileCheck %s --check-prefix=RA-ALL --check-prefix=KEY-A --check-prefix=BTE-ON
 
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=bti 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=bti 2>&1 | \
 // RUN: FileCheck %s --check-prefix=RA-OFF --check-prefix=BTE-ON
 
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=bti+pac-ret+b-key 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=bti+pac-ret+b-key 2>&1 | \
 // RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-B --check-prefix=BTE-ON
 
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=bti+pac-ret+leaf+b-key 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=bti+pac-ret+leaf+b-key 2>&1 | \
 // RUN: FileCheck %s --check-prefix=RA-ALL --check-prefix=KEY-B --check-prefix=BTE-ON
 
 // -mbranch-protection with standard
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=standard 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=standard 2>&1 | \
 // RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-A --check-prefix=BTE-ON
 
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=bar 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=bar 2>&1 | \
 // RUN: FileCheck %s --check-prefix=BAD-BP-PROTECTION
 
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+bti+b-key 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=pac-ret+bti+b-key 2>&1 | \
 // RUN: FileCheck %s --check-prefix=BAD-B-KEY-COMBINATION
 
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+bti+leaf 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=pac-ret+bti+leaf 2>&1 | \
 // RUN: FileCheck %s --check-prefix=BAD-LEAF-COMBINATION
 
+// -mbranch-protection with supported architectures other than v8.1-m.main
+// RUN: %clang -target arm-arm-none-eabi -march=armv8-m.main -c %s -### -mbranch-protection=pac-ret 2>&1 | \
+// RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-A --check-prefix=BTE-OFF
+
+// RUN: %clang -target arm-arm-none-eabi -march=armv7-m -c %s -### -mbranch-protection=pac-ret 2>&1 | \
+// RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-A --check-prefix=BTE-OFF
+
+// RUN: %clang -target arm-arm-none-eabi -march=armv7e-m -c %s -### -mbranch-protection=pac-ret 2>&1 | \
+// RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-A --check-prefix=BTE-OFF
+
+// -mbranch-protection with unsupported architectures
+// RUN: %clang -target arm-arm-none-eabi -march=armv6-m -c %s -### -mbranch-protection=bti 2>&1 | \
+// RUN: FileCheck %s --check-prefix=INCOMPATIBLE-ARCH
+
+// RUN: %clang -target arm-arm-none-eabi -march=armv8-m.base -c %s -### -mbranch-protection=bti 2>&1 | \
+// RUN: FileCheck %s --check-prefix=INCOMPATIBLE-ARCH
+
+// RUN: %clang -target arm-arm-none-eabi -march=armv8-a -c %s -### -mbranch-protection=bti 2>&1 | \
+// RUN: FileCheck %s --check-prefix=INCOMPATIBLE-ARCH
+
+// RUN: %clang -target arm-arm-none-eabi -march=armv8-r -c %s -### -mbranch-protection=bti 2>&1 | \
+// RUN: FileCheck %s --check-prefix=INCOMPATIBLE-ARCH
+
+// RUN: %clang -target arm-arm-none-eabi -march=armv7-a -c %s -### -mbranch-protection=bti 2>&1 | \
+// RUN: FileCheck %s --check-prefix=INCOMPATIBLE-ARCH
+
+/// RUN: %clang -target arm-arm-none-eabi -march=armv7-a -mthumb -c %s -### -mbranch-protection=bti 2>&1 | \
+/// RUN: FileCheck %s --check-prefix=INCOMPATIBLE-ARCH
+
+// RUN: %clang -target arm-arm-none-eabi -march=armv7-r -c %s -### -mbranch-protection=bti 2>&1 | \
+// RUN: FileCheck %s --check-prefix=INCOMPATIBLE-ARCH
+
 // RA-OFF: "-msign-return-address=none"
 // RA-NON-LEAF: "-msign-return-address=non-leaf"
 // RA-ALL: "-msign-return-address=all"
@@ -57,3 +89,5 @@
 
 // BAD-B-KEY-COMBINATION: invalid branch protection option 'b-key' in '-mbranch-protection={{.*}}'
 // BAD-LEAF-COMBINATION: invalid branch protection option 'leaf' in '-mbranch-protection={{.*}}'
+
+// INCOMPATIBLE-ARCH: ignoring '-mbranch-protection=' option because the '{{.*}}' architecture does not support it
Index: clang/test/Driver/aarch64-security-options.c
===================================================================
--- clang/test/Driver/aarch64-security-options.c
+++ clang/test/Driver/aarch64-security-options.c
@@ -1,31 +1,33 @@
 // Check the -msign-return-address= option, which has a required argument to
 // select scope.
 // RUN: %clang -target aarch64--none-eabi -c %s -### -msign-return-address=none                             2>&1 | \
-// RUN: FileCheck %s --check-prefix=RA-OFF --check-prefix=KEY --check-prefix=BTE-OFF
+// RUN: FileCheck %s --check-prefix=RA-OFF --check-prefix=KEY --check-prefix=BTE-OFF --check-prefix=WARN
 
 // RUN: %clang -target aarch64--none-eabi -c %s -### -msign-return-address=non-leaf                         2>&1 | \
-// RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-A --check-prefix=BTE-OFF
+// RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-A --check-prefix=BTE-OFF --check-prefix=WARN
 
 // RUN: %clang -target aarch64--none-eabi -c %s -### -msign-return-address=all                              2>&1 | \
-// RUN: FileCheck %s --check-prefix=RA-ALL      --check-prefix=KEY-A --check-prefix=BTE-OFF
+// RUN: FileCheck %s --check-prefix=RA-ALL      --check-prefix=KEY-A --check-prefix=BTE-OFF --check-prefix=WARN
 
 // -mbranch-protection with standard
 // RUN: %clang -target aarch64--none-eabi -c %s -### -mbranch-protection=standard                                2>&1 | \
-// RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-A --check-prefix=BTE-ON
+// RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-A --check-prefix=BTE-ON --check-prefix=WARN
 
 // If the -msign-return-address and -mbranch-protection are both used, the
 // right-most one controls return address signing.
 // RUN: %clang -target aarch64--none-eabi -c %s -### -msign-return-address=non-leaf -mbranch-protection=none     2>&1 | \
-// RUN: FileCheck %s --check-prefix=CONFLICT
+// RUN: FileCheck %s --check-prefix=CONFLICT --check-prefix=WARN
 
 // RUN: %clang -target aarch64--none-eabi -c %s -### -mbranch-protection=pac-ret -msign-return-address=none     2>&1 | \
-// RUN: FileCheck %s --check-prefix=CONFLICT
+// RUN: FileCheck %s --check-prefix=CONFLICT --check-prefix=WARN
 
 // RUN: %clang -target aarch64--none-eabi -c %s -### -msign-return-address=foo     2>&1 | \
-// RUN: FileCheck %s --check-prefix=BAD-RA-PROTECTION
+// RUN: FileCheck %s --check-prefix=BAD-RA-PROTECTION --check-prefix=WARN
 
 // RUN: %clang -target aarch64--none-eabi -c %s -### -mbranch-protection=bar     2>&1 | \
-// RUN: FileCheck %s --check-prefix=BAD-BP-PROTECTION
+// RUN: FileCheck %s --check-prefix=BAD-BP-PROTECTION --check-prefix=WARN
+
+// WARN-NOT: warning: ignoring '-mbranch-protection=' option because the 'aarch64' architecture does not support it [-Wbranch-protection]
 
 // RA-OFF: "-msign-return-address=none"
 // RA-NON-LEAF: "-msign-return-address=non-leaf"
Index: clang/test/CodeGen/arm_acle.c
===================================================================
--- clang/test/CodeGen/arm_acle.c
+++ clang/test/CodeGen/arm_acle.c
@@ -1535,12 +1535,12 @@
 /* 10.1 Special register intrinsics */
 // AArch32-LABEL: @test_rsr(
 // AArch32-NEXT:  entry:
-// AArch32-NEXT:    [[TMP0:%.*]] = call i32 @llvm.read_volatile_register.i32(metadata !5)
+// AArch32-NEXT:    [[TMP0:%.*]] = call i32 @llvm.read_volatile_register.i32(metadata [[A32RSR32:!.*]])
 // AArch32-NEXT:    ret i32 [[TMP0]]
 //
 // AArch64-LABEL: @test_rsr(
 // AArch64-NEXT:  entry:
-// AArch64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata !8)
+// AArch64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata [[A64RSR:!.*]])
 // AArch64-NEXT:    [[TMP1:%.*]] = trunc i64 [[TMP0]] to i32
 // AArch64-NEXT:    ret i32 [[TMP1]]
 //
@@ -1554,12 +1554,12 @@
 
 // AArch32-LABEL: @test_rsr64(
 // AArch32-NEXT:  entry:
-// AArch32-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata !6)
+// AArch32-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata [[A32RSR64:!.*]])
 // AArch32-NEXT:    ret i64 [[TMP0]]
 //
 // AArch64-LABEL: @test_rsr64(
 // AArch64-NEXT:  entry:
-// AArch64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata !8)
+// AArch64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata [[A64RSR]])
 // AArch64-NEXT:    ret i64 [[TMP0]]
 //
 uint64_t test_rsr64() {
@@ -1572,13 +1572,13 @@
 
 // AArch32-LABEL: @test_rsrp(
 // AArch32-NEXT:  entry:
-// AArch32-NEXT:    [[TMP0:%.*]] = call i32 @llvm.read_volatile_register.i32(metadata !7)
+// AArch32-NEXT:    [[TMP0:%.*]] = call i32 @llvm.read_volatile_register.i32(metadata [[A32SYSREG:!.*]])
 // AArch32-NEXT:    [[TMP1:%.*]] = inttoptr i32 [[TMP0]] to i8*
 // AArch32-NEXT:    ret i8* [[TMP1]]
 //
 // AArch64-LABEL: @test_rsrp(
 // AArch64-NEXT:  entry:
-// AArch64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata !9)
+// AArch64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata [[A64SYSREG:!.*]])
 // AArch64-NEXT:    [[TMP1:%.*]] = inttoptr i64 [[TMP0]] to i8*
 // AArch64-NEXT:    ret i8* [[TMP1]]
 //
@@ -1588,13 +1588,13 @@
 
 // AArch32-LABEL: @test_wsr(
 // AArch32-NEXT:  entry:
-// AArch32-NEXT:    call void @llvm.write_register.i32(metadata !5, i32 [[V:%.*]])
+// AArch32-NEXT:    call void @llvm.write_register.i32(metadata [[A32RSR32]], i32 [[V:%.*]])
 // AArch32-NEXT:    ret void
 //
 // AArch64-LABEL: @test_wsr(
 // AArch64-NEXT:  entry:
 // AArch64-NEXT:    [[TMP0:%.*]] = zext i32 [[V:%.*]] to i64
-// AArch64-NEXT:    call void @llvm.write_register.i64(metadata !8, i64 [[TMP0]])
+// AArch64-NEXT:    call void @llvm.write_register.i64(metadata [[A64RSR]], i64 [[TMP0]])
 // AArch64-NEXT:    ret void
 //
 void test_wsr(uint32_t v) {
@@ -1607,12 +1607,12 @@
 
 // AArch32-LABEL: @test_wsr64(
 // AArch32-NEXT:  entry:
-// AArch32-NEXT:    call void @llvm.write_register.i64(metadata !6, i64 [[V:%.*]])
+// AArch32-NEXT:    call void @llvm.write_register.i64(metadata [[A32RSR64]], i64 [[V:%.*]])
 // AArch32-NEXT:    ret void
 //
 // AArch64-LABEL: @test_wsr64(
 // AArch64-NEXT:  entry:
-// AArch64-NEXT:    call void @llvm.write_register.i64(metadata !8, i64 [[V:%.*]])
+// AArch64-NEXT:    call void @llvm.write_register.i64(metadata [[A64RSR]], i64 [[V:%.*]])
 // AArch64-NEXT:    ret void
 //
 void test_wsr64(uint64_t v) {
@@ -1626,13 +1626,13 @@
 // AArch32-LABEL: @test_wsrp(
 // AArch32-NEXT:  entry:
 // AArch32-NEXT:    [[TMP0:%.*]] = ptrtoint i8* [[V:%.*]] to i32
-// AArch32-NEXT:    call void @llvm.write_register.i32(metadata !7, i32 [[TMP0]])
+// AArch32-NEXT:    call void @llvm.write_register.i32(metadata [[A32SYSREG]], i32 [[TMP0]])
 // AArch32-NEXT:    ret void
 //
 // AArch64-LABEL: @test_wsrp(
 // AArch64-NEXT:  entry:
 // AArch64-NEXT:    [[TMP0:%.*]] = ptrtoint i8* [[V:%.*]] to i64
-// AArch64-NEXT:    call void @llvm.write_register.i64(metadata !9, i64 [[TMP0]])
+// AArch64-NEXT:    call void @llvm.write_register.i64(metadata [[A64SYSREG]], i64 [[TMP0]])
 // AArch64-NEXT:    ret void
 //
 void test_wsrp(void *v) {
@@ -1642,7 +1642,7 @@
 // AArch32-LABEL: @test_rsrf(
 // AArch32-NEXT:  entry:
 // AArch32-NEXT:    [[REF_TMP:%.*]] = alloca i32, align 4
-// AArch32-NEXT:    [[TMP0:%.*]] = call i32 @llvm.read_volatile_register.i32(metadata !5)
+// AArch32-NEXT:    [[TMP0:%.*]] = call i32 @llvm.read_volatile_register.i32(metadata [[A32RSR32]])
 // AArch32-NEXT:    store i32 [[TMP0]], i32* [[REF_TMP]], align 4
 // AArch32-NEXT:    [[TMP1:%.*]] = bitcast i32* [[REF_TMP]] to float*
 // AArch32-NEXT:    [[TMP2:%.*]] = load float, float* [[TMP1]], align 4
@@ -1651,7 +1651,7 @@
 // AArch64-LABEL: @test_rsrf(
 // AArch64-NEXT:  entry:
 // AArch64-NEXT:    [[REF_TMP:%.*]] = alloca i32, align 4
-// AArch64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata !8)
+// AArch64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata [[A64RSR]])
 // AArch64-NEXT:    [[TMP1:%.*]] = trunc i64 [[TMP0]] to i32
 // AArch64-NEXT:    store i32 [[TMP1]], i32* [[REF_TMP]], align 4
 // AArch64-NEXT:    [[TMP2:%.*]] = bitcast i32* [[REF_TMP]] to float*
@@ -1669,7 +1669,7 @@
 // AArch32-LABEL: @test_rsrf64(
 // AArch32-NEXT:  entry:
 // AArch32-NEXT:    [[REF_TMP:%.*]] = alloca i64, align 8
-// AArch32-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata !6)
+// AArch32-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata [[A32RSR64]])
 // AArch32-NEXT:    store i64 [[TMP0]], i64* [[REF_TMP]], align 8
 // AArch32-NEXT:    [[TMP1:%.*]] = bitcast i64* [[REF_TMP]] to double*
 // AArch32-NEXT:    [[TMP2:%.*]] = load double, double* [[TMP1]], align 8
@@ -1678,7 +1678,7 @@
 // AArch64-LABEL: @test_rsrf64(
 // AArch64-NEXT:  entry:
 // AArch64-NEXT:    [[REF_TMP:%.*]] = alloca i64, align 8
-// AArch64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata !8)
+// AArch64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata [[A64RSR]])
 // AArch64-NEXT:    store i64 [[TMP0]], i64* [[REF_TMP]], align 8
 // AArch64-NEXT:    [[TMP1:%.*]] = bitcast i64* [[REF_TMP]] to double*
 // AArch64-NEXT:    [[TMP2:%.*]] = load double, double* [[TMP1]], align 8
@@ -1698,7 +1698,7 @@
 // AArch32-NEXT:    store float [[V:%.*]], float* [[V_ADDR]], align 4
 // AArch32-NEXT:    [[TMP0:%.*]] = bitcast float* [[V_ADDR]] to i32*
 // AArch32-NEXT:    [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4
-// AArch32-NEXT:    call void @llvm.write_register.i32(metadata !5, i32 [[TMP1]])
+// AArch32-NEXT:    call void @llvm.write_register.i32(metadata [[A32RSR32]], i32 [[TMP1]])
 // AArch32-NEXT:    ret void
 //
 // AArch64-LABEL: @test_wsrf(
@@ -1708,7 +1708,7 @@
 // AArch64-NEXT:    [[TMP0:%.*]] = bitcast float* [[V_ADDR]] to i32*
 // AArch64-NEXT:    [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4
 // AArch64-NEXT:    [[TMP2:%.*]] = zext i32 [[TMP1]] to i64
-// AArch64-NEXT:    call void @llvm.write_register.i64(metadata !8, i64 [[TMP2]])
+// AArch64-NEXT:    call void @llvm.write_register.i64(metadata [[A64RSR]], i64 [[TMP2]])
 // AArch64-NEXT:    ret void
 //
 void test_wsrf(float v) {
@@ -1725,7 +1725,7 @@
 // AArch32-NEXT:    store double [[V:%.*]], double* [[V_ADDR]], align 8
 // AArch32-NEXT:    [[TMP0:%.*]] = bitcast double* [[V_ADDR]] to i64*
 // AArch32-NEXT:    [[TMP1:%.*]] = load i64, i64* [[TMP0]], align 8
-// AArch32-NEXT:    call void @llvm.write_register.i64(metadata !6, i64 [[TMP1]])
+// AArch32-NEXT:    call void @llvm.write_register.i64(metadata [[A32RSR64]], i64 [[TMP1]])
 // AArch32-NEXT:    ret void
 //
 // AArch64-LABEL: @test_wsrf64(
@@ -1734,7 +1734,7 @@
 // AArch64-NEXT:    store double [[V:%.*]], double* [[V_ADDR]], align 8
 // AArch64-NEXT:    [[TMP0:%.*]] = bitcast double* [[V_ADDR]] to i64*
 // AArch64-NEXT:    [[TMP1:%.*]] = load i64, i64* [[TMP0]], align 8
-// AArch64-NEXT:    call void @llvm.write_register.i64(metadata !8, i64 [[TMP1]])
+// AArch64-NEXT:    call void @llvm.write_register.i64(metadata [[A64RSR]], i64 [[TMP1]])
 // AArch64-NEXT:    ret void
 //
 void test_wsrf64(double v) {
@@ -1786,9 +1786,9 @@
 }
 #endif
 
-// AArch32: !5 = !{!"cp1:2:c3:c4:5"}
-// AArch32: !6 = !{!"cp1:2:c3"}
-// AArch32: !7 = !{!"sysreg"}
+// AArch32: [[A32RSR32]] = !{!"cp1:2:c3:c4:5"}
+// AArch32: [[A32RSR64]] = !{!"cp1:2:c3"}
+// AArch32: [[A32SYSREG]] = !{!"sysreg"}
 
-// AArch64: !8 = !{!"1:2:3:4:5"}
-// AArch64: !9 = !{!"sysreg"}
+// AArch64: [[A64RSR]] = !{!"1:2:3:4:5"}
+// AArch64: [[A64SYSREG]] = !{!"sysreg"}
Index: clang/test/CodeGen/arm-branch-protection-attr-2.c
===================================================================
--- clang/test/CodeGen/arm-branch-protection-attr-2.c
+++ clang/test/CodeGen/arm-branch-protection-attr-2.c
@@ -1,9 +1,9 @@
 // REQUIRES: arm-registered-target
-// RUN: %clang -target arm-arm-none-eabi -march=armv7-m -S -emit-llvm -o - -mbranch-protection=none %s          | FileCheck %s --check-prefix=CHECK --check-prefix=NONE
-// RUN: %clang -target arm-arm-none-eabi -march=armv7-m -S -emit-llvm -o - -mbranch-protection=pac-ret       %s | FileCheck %s --check-prefix=CHECK --check-prefix=PART
-// RUN: %clang -target arm-arm-none-eabi -march=armv7-m -S -emit-llvm -o - -mbranch-protection=pac-ret+leaf  %s | FileCheck %s --check-prefix=CHECK --check-prefix=ALL
-// RUN: %clang -target arm-arm-none-eabi -march=armv7-m -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key %s | FileCheck %s --check-prefix=CHECK --check-prefix=PART
-// RUN: %clang -target arm-arm-none-eabi -march=armv7-m -S -emit-llvm -o - -mbranch-protection=bti %s           | FileCheck %s --check-prefix=CHECK --check-prefix=BTE
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -S -emit-llvm -o - -mbranch-protection=none %s          | FileCheck %s --check-prefix=CHECK --check-prefix=NONE
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -S -emit-llvm -o - -mbranch-protection=pac-ret       %s | FileCheck %s --check-prefix=CHECK --check-prefix=PART
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -S -emit-llvm -o - -mbranch-protection=pac-ret+leaf  %s | FileCheck %s --check-prefix=CHECK --check-prefix=ALL
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key %s | FileCheck %s --check-prefix=CHECK --check-prefix=PART
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -S -emit-llvm -o - -mbranch-protection=bti %s           | FileCheck %s --check-prefix=CHECK --check-prefix=BTE
 
 // Check there are no branch protection function attributes
 
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -3393,7 +3393,8 @@
   if (ParsedAttrs.BranchProtection.empty())
     return false;
   if (!Context.getTargetInfo().validateBranchProtection(
-          ParsedAttrs.BranchProtection, BPI, DiagMsg)) {
+          ParsedAttrs.BranchProtection, ParsedAttrs.Architecture, BPI,
+          DiagMsg)) {
     if (DiagMsg.empty())
       return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
              << Unsupported << None << "branch-protection" << Target;
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -1627,7 +1627,7 @@
 }
 }
 
-static void CollectARMPACBTIOptions(const Driver &D, const ArgList &Args,
+static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args,
                                     ArgStringList &CmdArgs, bool isAArch64) {
   const Arg *A = isAArch64
                      ? Args.getLastArg(options::OPT_msign_return_address_EQ,
@@ -1636,6 +1636,12 @@
   if (!A)
     return;
 
+  const Driver &D = TC.getDriver();
+  const llvm::Triple &Triple = TC.getEffectiveTriple();
+  if (!(isAArch64 || (Triple.isArmT32() && Triple.isArmMClass())))
+    D.Diag(diag::warn_target_unsupported_branch_protection_option)
+        << Triple.getArchName();
+
   StringRef Scope, Key;
   bool IndirectBranches;
 
@@ -1713,8 +1719,7 @@
   AddAAPCSVolatileBitfieldArgs(Args, CmdArgs);
 
   // Enable/disable return address signing and indirect branch targets.
-  CollectARMPACBTIOptions(getToolChain().getDriver(), Args, CmdArgs,
-                          false /*isAArch64*/);
+  CollectARMPACBTIOptions(getToolChain(), Args, CmdArgs, false /*isAArch64*/);
 }
 
 void Clang::RenderTargetOptions(const llvm::Triple &EffectiveTriple,
@@ -1841,8 +1846,7 @@
   }
 
   // Enable/disable return address signing and indirect branch targets.
-  CollectARMPACBTIOptions(getToolChain().getDriver(), Args, CmdArgs,
-                          true /*isAArch64*/);
+  CollectARMPACBTIOptions(getToolChain(), Args, CmdArgs, true /*isAArch64*/);
 
   // Handle -msve_vector_bits=<bits>
   if (Arg *A = Args.getLastArg(options::OPT_msve_vector_bits_EQ)) {
Index: clang/lib/CodeGen/TargetInfo.cpp
===================================================================
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -5563,8 +5563,8 @@
 
     TargetInfo::BranchProtectionInfo BPI;
     StringRef Error;
-    (void)CGM.getTarget().validateBranchProtection(Attr.BranchProtection,
-                                                   BPI, Error);
+    (void)CGM.getTarget().validateBranchProtection(
+        Attr.BranchProtection, Attr.Architecture, BPI, Error);
     assert(Error.empty());
 
     auto *Fn = cast<llvm::Function>(GV);
@@ -6377,17 +6377,36 @@
       if (!Attr.BranchProtection.empty()) {
         TargetInfo::BranchProtectionInfo BPI;
         StringRef DiagMsg;
-        (void)CGM.getTarget().validateBranchProtection(Attr.BranchProtection,
-                                                       BPI, DiagMsg);
-
-        static const char *SignReturnAddrStr[] = {"none", "non-leaf", "all"};
-        assert(static_cast<unsigned>(BPI.SignReturnAddr) <= 2 &&
-               "Unexpected SignReturnAddressScopeKind");
-        Fn->addFnAttr("sign-return-address",
-                      SignReturnAddrStr[static_cast<int>(BPI.SignReturnAddr)]);
-
-        Fn->addFnAttr("branch-target-enforcement",
-                      BPI.BranchTargetEnforcement ? "true" : "false");
+        StringRef Arch = Attr.Architecture.empty()
+                             ? CGM.getTarget().getTargetOpts().CPU
+                             : Attr.Architecture;
+        if (!CGM.getTarget().validateBranchProtection(Attr.BranchProtection,
+                                                      Arch, BPI, DiagMsg)) {
+          CGM.getDiags().Report(
+              D->getLocation(),
+              diag::warn_target_unsupported_branch_protection_attribute)
+              << Arch;
+        } else {
+          static const char *SignReturnAddrStr[] = {"none", "non-leaf", "all"};
+          assert(static_cast<unsigned>(BPI.SignReturnAddr) <= 2 &&
+                 "Unexpected SignReturnAddressScopeKind");
+          Fn->addFnAttr(
+              "sign-return-address",
+              SignReturnAddrStr[static_cast<int>(BPI.SignReturnAddr)]);
+
+          Fn->addFnAttr("branch-target-enforcement",
+                        BPI.BranchTargetEnforcement ? "true" : "false");
+        }
+      } else if (CGM.getLangOpts().BranchTargetEnforcement ||
+                 CGM.getLangOpts().hasSignReturnAddress()) {
+        // If the Branch Protection attribute is missing, validate the target
+        // Architecture attribute against Branch Protection command line
+        // settings.
+        if (!CGM.getTarget().isBranchProtectionSupportedArch(Attr.Architecture))
+          CGM.getDiags().Report(
+              D->getLocation(),
+              diag::warn_target_unsupported_branch_protection_attribute)
+              << Attr.Architecture;
       }
     }
 
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -731,6 +731,7 @@
                               "tag-stack-memory-buildattr", 1);
 
   if (Arch == llvm::Triple::thumb || Arch == llvm::Triple::thumbeb ||
+      Arch == llvm::Triple::arm || Arch == llvm::Triple::armeb ||
       Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_32 ||
       Arch == llvm::Triple::aarch64_be) {
     getModule().addModuleFlag(llvm::Module::Error, "branch-target-enforcement",
@@ -742,11 +743,9 @@
     getModule().addModuleFlag(llvm::Module::Error, "sign-return-address-all",
                               LangOpts.isSignReturnAddressScopeAll());
 
-    if (Arch != llvm::Triple::thumb && Arch != llvm::Triple::thumbeb) {
-      getModule().addModuleFlag(llvm::Module::Error,
-                                "sign-return-address-with-bkey",
-                                !LangOpts.isSignReturnAddressWithAKey());
-    }
+    getModule().addModuleFlag(llvm::Module::Error,
+                              "sign-return-address-with-bkey",
+                              !LangOpts.isSignReturnAddressWithAKey());
   }
 
   if (!CodeGenOpts.MemoryProfileOutput.empty()) {
Index: clang/lib/Basic/Targets/ARM.h
===================================================================
--- clang/lib/Basic/Targets/ARM.h
+++ clang/lib/Basic/Targets/ARM.h
@@ -126,8 +126,10 @@
   StringRef getABI() const override;
   bool setABI(const std::string &Name) override;
 
-  bool validateBranchProtection(StringRef, BranchProtectionInfo &,
-                                StringRef &) const override;
+  bool isBranchProtectionSupportedArch(StringRef Arch) const override;
+  bool validateBranchProtection(StringRef Spec, StringRef Arch,
+                                BranchProtectionInfo &BPI,
+                                StringRef &Err) const override;
 
   // FIXME: This should be based on Arch attributes, not CPU names.
   bool
Index: clang/lib/Basic/Targets/ARM.cpp
===================================================================
--- clang/lib/Basic/Targets/ARM.cpp
+++ clang/lib/Basic/Targets/ARM.cpp
@@ -371,13 +371,34 @@
   return false;
 }
 
-bool ARMTargetInfo::validateBranchProtection(StringRef Spec,
+bool ARMTargetInfo::isBranchProtectionSupportedArch(StringRef Arch) const {
+  llvm::ARM::ArchKind CPUArch = llvm::ARM::parseCPUArch(Arch);
+  if (CPUArch == llvm::ARM::ArchKind::INVALID)
+    CPUArch = llvm::ARM::parseArch(getTriple().getArchName());
+
+  if (CPUArch == llvm::ARM::ArchKind::INVALID)
+    return false;
+
+  StringRef ArchFeature = llvm::ARM::getArchName(CPUArch);
+  auto a =
+      llvm::Triple(ArchFeature, getTriple().getVendorName(),
+                   getTriple().getOSName(), getTriple().getEnvironmentName());
+
+  StringRef SubArch = llvm::ARM::getSubArch(CPUArch);
+  llvm::ARM::ProfileKind Profile = llvm::ARM::parseArchProfile(SubArch);
+  return a.isArmT32() && (Profile == llvm::ARM::ProfileKind::M);
+}
+
+bool ARMTargetInfo::validateBranchProtection(StringRef Spec, StringRef Arch,
                                              BranchProtectionInfo &BPI,
                                              StringRef &Err) const {
   llvm::ARM::ParsedBranchProtection PBP;
   if (!llvm::ARM::parseBranchProtection(Spec, PBP, Err))
     return false;
 
+  if (!isBranchProtectionSupportedArch(Arch))
+    return false;
+
   BPI.SignReturnAddr =
       llvm::StringSwitch<LangOptions::SignReturnAddressScopeKind>(PBP.Scope)
           .Case("non-leaf", LangOptions::SignReturnAddressScopeKind::NonLeaf)
Index: clang/lib/Basic/Targets/AArch64.h
===================================================================
--- clang/lib/Basic/Targets/AArch64.h
+++ clang/lib/Basic/Targets/AArch64.h
@@ -70,8 +70,9 @@
   StringRef getABI() const override;
   bool setABI(const std::string &Name) override;
 
-  bool validateBranchProtection(StringRef, BranchProtectionInfo &,
-                                StringRef &) const override;
+  bool validateBranchProtection(StringRef Spec, StringRef Arch,
+                                BranchProtectionInfo &BPI,
+                                StringRef &Err) const override;
 
   bool isValidCPUName(StringRef Name) const override;
   void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
Index: clang/lib/Basic/Targets/AArch64.cpp
===================================================================
--- clang/lib/Basic/Targets/AArch64.cpp
+++ clang/lib/Basic/Targets/AArch64.cpp
@@ -138,7 +138,7 @@
   return true;
 }
 
-bool AArch64TargetInfo::validateBranchProtection(StringRef Spec,
+bool AArch64TargetInfo::validateBranchProtection(StringRef Spec, StringRef,
                                                  BranchProtectionInfo &BPI,
                                                  StringRef &Err) const {
   llvm::ARM::ParsedBranchProtection PBP;
Index: clang/include/clang/Basic/TargetInfo.h
===================================================================
--- clang/include/clang/Basic/TargetInfo.h
+++ clang/include/clang/Basic/TargetInfo.h
@@ -1289,9 +1289,15 @@
     bool BranchTargetEnforcement = false;
   };
 
+  /// Determine if the Architecture in this TargetInfo supports branch
+  /// protection
+  virtual bool isBranchProtectionSupportedArch(StringRef Arch) const {
+    return false;
+  }
+
   /// Determine if this TargetInfo supports the given branch protection
   /// specification
-  virtual bool validateBranchProtection(StringRef Spec,
+  virtual bool validateBranchProtection(StringRef Spec, StringRef Arch,
                                         BranchProtectionInfo &BPI,
                                         StringRef &Err) const {
     Err = "";
Index: clang/include/clang/Basic/DiagnosticCommonKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticCommonKinds.td
+++ clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -145,6 +145,13 @@
 def err_nullability_conflicting : Error<
   "nullability specifier %0 conflicts with existing specifier %1">;
 
+def warn_target_unsupported_branch_protection_option: Warning <
+  "ignoring '-mbranch-protection=' option because the '%0' architecture does not support it">,
+  InGroup<BranchProtection>;
+
+def warn_target_unsupported_branch_protection_attribute: Warning <
+  "ignoring the 'branch-protection' attribute because the '%0' architecture does not support it">,
+  InGroup<BranchProtection>;
 }
 
 // OpenCL Section 6.8.g
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to