danielkiss updated this revision to Diff 254761.
danielkiss added a comment.
The patched is rebased and the hopefully the logic is now simpler.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D75181/new/
https://reviews.llvm.org/D75181
Files:
clang/lib/CodeGen/CGCall.cpp
clang/lib/CodeGen/CodeGenModule.cpp
clang/lib/CodeGen/TargetInfo.cpp
clang/test/CodeGen/aarch64-branch-protection-attr.c
clang/test/CodeGenCXX/aarch64-branch-target_clang_call_terminate.cpp
llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
llvm/lib/Target/AArch64/AArch64BranchTargets.cpp
llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-0.ll
llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-1.ll
llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-2.ll
llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-3.ll
llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-4.ll
llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-5.ll
llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-6.ll
llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-7.ll
llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-8.ll
llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-9.ll
Index: llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-9.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-9.ll
@@ -0,0 +1,27 @@
+; RUN: llc -mtriple=aarch64-linux %s -o - | \
+; RUN: FileCheck %s --check-prefix=ASM
+; RUN: llc -mtriple=aarch64-linux %s -filetype=obj -o - | \
+; RUN: llvm-readelf --notes | FileCheck %s --check-prefix=OBJ
+
+define dso_local i32 @f() #0 {
+entry:
+ ret i32 0
+}
+
+define dso_local i32 @g() {
+entry:
+ ret i32 0
+}
+
+attributes #0 = { "branch-target-enforcement" }
+
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 4, !"branch-target-enforcement", i32 1}
+
+; Only the common atttribute (BTI)
+; ASM: .word 3221225472
+; ASM-NEXT: .word 4
+; ASM-NEXT .word 1
+
+; OBJ: Properties: aarch64 feature: BTI
Index: llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-8.ll
===================================================================
--- llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-8.ll
+++ llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-8.ll
@@ -13,6 +13,10 @@
attributes #0 = { "branch-target-enforcement" }
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 4, !"branch-target-enforcement", i32 1}
+
; Declarations don't prevent setting BTI
; ASM: .word 3221225472
; ASM-NEXT: .word 4
Index: llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-7.ll
===================================================================
--- llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-7.ll
+++ llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-7.ll
@@ -13,10 +13,14 @@
ret i32 0
}
-attributes #0 = { "sign-return-address"="non-leaf" }
+attributes #0 = { "ignore-branch-target-enforcement" "sign-return-address"="non-leaf" }
attributes #1 = { "branch-target-enforcement" }
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 4, !"branch-target-enforcement", i32 1}
+
; No common attribute, no note section
; ASM: warning: not setting BTI in feature flags
; ASM-NOT: .note.gnu.property
Index: llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-6.ll
===================================================================
--- llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-6.ll
+++ llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-6.ll
@@ -17,6 +17,11 @@
attributes #1 = { "sign-return-address"="none" }
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 4, !"sign-return-address", !"non-leaf"}
+
+
; No common attribute, no note section
; ASM-NOT: .note.gnu.property
; OBJ-NOT: .note.gnu.property
Index: llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-5.ll
===================================================================
--- llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-5.ll
+++ llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-5.ll
@@ -15,7 +15,13 @@
attributes #0 = { "branch-target-enforcement" "sign-return-address"="non-leaf" }
-attributes #1 = { "sign-return-address"="all" }
+attributes #1 = { "ignore-branch-target-enforcement" "sign-return-address"="all" }
+
+!llvm.module.flags = !{!0, !1}
+
+!0 = !{i32 4, !"branch-target-enforcement", i32 1}
+!1 = !{i32 4, !"sign-return-address", !"all"}
+
; Only the common atttribute (PAC)
; ASM: warning: not setting BTI in feature flags
Index: llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-4.ll
===================================================================
--- llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-4.ll
+++ llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-4.ll
@@ -17,6 +17,10 @@
attributes #1 = { "branch-target-enforcement" }
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 4, !"branch-target-enforcement", i32 1}
+
; Only the common atttribute (BTI)
; ASM: .word 3221225472
; ASM-NEXT: .word 4
Index: llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-3.ll
===================================================================
--- llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-3.ll
+++ llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-3.ll
@@ -10,6 +10,11 @@
attributes #0 = { "branch-target-enforcement" "sign-return-address"="non-leaf" }
+!llvm.module.flags = !{!0, !1}
+
+!0 = !{i32 4, !"branch-target-enforcement", i32 1}
+!1 = !{i32 4, !"sign-return-address", !"non-leaf"}
+
; Both attribute present
; ASM: .word 3221225472
; ASM-NEXT: .word 4
Index: llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-2.ll
===================================================================
--- llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-2.ll
+++ llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-2.ll
@@ -10,6 +10,10 @@
attributes #0 = { "sign-return-address"="all" }
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 4, !"sign-return-address", !"all"}
+
; PAC attribute present
; ASM: .word 3221225472
; ASM-NEXT: .word 4
Index: llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-1.ll
===================================================================
--- llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-1.ll
+++ llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-1.ll
@@ -10,6 +10,10 @@
attributes #0 = { "branch-target-enforcement" }
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 4, !"branch-target-enforcement", i32 1}
+
; BTI attribute present
; ASM: .word 3221225472
; ASM-NEXT: .word 4
Index: llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-0.ll
===================================================================
--- llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-0.ll
+++ llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-0.ll
@@ -6,6 +6,11 @@
attributes #0 = { "branch-target-enforcement" }
+!llvm.module.flags = !{!0, !1}
+
+!0 = !{i32 4, !"branch-target-enforcement", i32 1}
+!1 = !{i32 4, !"sign-return-address", !"all"}
+
; Both attributes present in a file with no functions.
; ASM: .word 3221225472
; ASM-NEXT: .word 4
Index: llvm/lib/Target/AArch64/AArch64BranchTargets.cpp
===================================================================
--- llvm/lib/Target/AArch64/AArch64BranchTargets.cpp
+++ llvm/lib/Target/AArch64/AArch64BranchTargets.cpp
@@ -58,7 +58,14 @@
bool AArch64BranchTargets::runOnMachineFunction(MachineFunction &MF) {
const Function &F = MF.getFunction();
- if (!F.hasFnAttribute("branch-target-enforcement"))
+
+ // Explicitly requested to not generate BTI.
+ if (F.hasFnAttribute("ignore-branch-target-enforcement"))
+ return false;
+ // Add BTI if function is compiled with it or in case of generated functions
+ // fallback to the module flag.
+ if (!F.hasFnAttribute("branch-target-enforcement") &&
+ !MF.getMMI().getModule()->getModuleFlag("branch-target-enforcement"))
return false;
LLVM_DEBUG(
Index: llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
===================================================================
--- llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -187,12 +187,19 @@
return;
// Assemble feature flags that may require creation of a note section.
- unsigned Flags = ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI |
- ELF::GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
+ unsigned Flags = 0;
+ if (M.getModuleFlag("branch-target-enforcement"))
+ Flags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
+ if (M.getModuleFlag("sign-return-address"))
+ Flags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
+
+ if (Flags == 0)
+ return;
if (any_of(M, [](const Function &F) {
- return !F.isDeclaration() &&
- !F.hasFnAttribute("branch-target-enforcement");
+ if (F.isDeclaration())
+ return false;
+ return F.hasFnAttribute("ignore-branch-target-enforcement");
})) {
Flags &= ~ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
}
Index: clang/test/CodeGenCXX/aarch64-branch-target_clang_call_terminate.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/aarch64-branch-target_clang_call_terminate.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang -target aarch64-linux-android -mbranch-protection=none -c %s -o - | \
+// RUN: llvm-objdump -d --mattr=+bti - | FileCheck %s --check-prefix=CHECK-NONE
+// RUN: %clang -target aarch64-linux-android -mbranch-protection=pac-ret -c %s -o - | \
+// RUN: llvm-objdump -d --mattr=+bti - | FileCheck %s --check-prefix=CHECK-NONE
+// RUN: %clang -target aarch64-linux-android -mbranch-protection=pac-ret+leaf -c %s -o - | \
+// RUN: llvm-objdump -d --mattr=+bti - | FileCheck %s --check-prefix=CHECK-NONE
+// RUN: %clang -target aarch64-linux-android -mbranch-protection=pac-ret+b-key -c %s -o - | \
+// RUN: llvm-objdump -d --mattr=+bti - | FileCheck %s --check-prefix=CHECK-NONE
+// RUN: %clang -target aarch64-linux-android -mbranch-protection=pac-ret+b-key+leaf -c %s -o - | \
+// RUN: llvm-objdump -d --mattr=+bti - | FileCheck %s --check-prefix=CHECK-NONE
+// RUN: %clang -target aarch64-linux-android -mbranch-protection=standard -c %s -o - | \
+// RUN: llvm-objdump -d --mattr=+bti - | FileCheck %s --check-prefix=CHECK-BTI
+// RUN: %clang -target aarch64-linux-android -mbranch-protection=bti -c %s -o - | \
+// RUN: llvm-objdump -d --mattr=+bti - | FileCheck %s --check-prefix=CHECK-BTI
+// RUN: %clang -target aarch64-linux-android -mbranch-protection=pac-ret+b-key+leaf+bti -c %s -o - | \
+// RUN: llvm-objdump -d --mattr=+bti - | FileCheck %s --check-prefix=CHECK-BTI
+
+void a();
+void d();
+
+void c() {
+ try {
+ d();
+ } catch (...) {
+ a();
+ }
+}
+
+// CHECK-BTI: 0000000000000000 <__clang_call_terminate>:
+// CHECK-BTI-NEXT: bti c
+// CHECK-BTI-NEXT: str x30, [sp, #-16]!
+
+// CHECK-NONE: 0000000000000000 <__clang_call_terminate>:
+// CHECK-NONE-NEXT: str x30, [sp, #-16]!
Index: clang/test/CodeGen/aarch64-branch-protection-attr.c
===================================================================
--- clang/test/CodeGen/aarch64-branch-protection-attr.c
+++ clang/test/CodeGen/aarch64-branch-protection-attr.c
@@ -11,10 +11,10 @@
__attribute__ ((target("branch-protection=none")))
void none() {}
-// NO-OVERRIDE: define void @none() #[[#NONE]]
+// NO-OVERRIDE: define void @none() #[[#NONE:]]
// OVERRIDE: define void @none() #[[#NONE:]]
- __attribute__ ((target("branch-protection=standard")))
+__attribute__ ((target("branch-protection=standard")))
void std() {}
// NO-OVERRIDE: define void @std() #[[#STD:]]
// OVERRIDE: define void @std() #[[#STD]]
@@ -36,8 +36,8 @@
__attribute__ ((target("branch-protection=bti+pac-ret")))
void pacbti1() {}
-// NO-OVERRIDE: define void @pacbti1() #[[#PACBTI]]
-// OVERRIDE: define void @pacbti1() #[[#PACBTI]]
+// NO-OVERRIDE: define void @pacbti1() #[[#PACBTI:]]
+// OVERRIDE: define void @pacbti1() #[[#PACBTI:]]
__attribute__ ((target("branch-protection=pac-ret+leaf")))
void leaf() {}
@@ -56,26 +56,31 @@
__attribute__ ((target("branch-protection=pac-ret+leaf+b-key")))
void bkeyleaf1() {}
-// NO-OVERRIDE: define void @bkeyleaf1() #[[#PACBKEYLEAF]]
-// OVERRIDE: define void @bkeyleaf1() #[[#PACBKEYLEAF]]
+// NO-OVERRIDE: define void @bkeyleaf1() #[[#PACBKEYLEAF:]]
+// OVERRIDE: define void @bkeyleaf1() #[[#PACBKEYLEAF:]]
__attribute__ ((target("branch-protection=pac-ret+leaf+bti")))
void btileaf() {}
// NO-OVERRIDE: define void @btileaf() #[[#BTIPACLEAF:]]
// OVERRIDE: define void @btileaf() #[[#BTIPACLEAF:]]
-// CHECK-DAG: attributes #[[#NONE]]
+// NO-OVERRIDE-DAG: attributes #[[#NONE]] = { {{.*}}
+// OVERRIDE-DAG: attributes #[[#NONE]] = { {{.*}} "ignore-branch-target-enforcement"
// CHECK-DAG: attributes #[[#STD]] = { {{.*}} "branch-target-enforcement" {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key"
-// CHECK-DAG: attributes #[[#BTI]] = { {{.*}}"branch-target-enforcement"
+// CHECK-DAG: attributes #[[#BTI]] = { {{.*}} "branch-target-enforcement"
-// CHECK-DAG: attributes #[[#PAC]] = { {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key"
+// NO-OVERRIDE-DAG: attributes #[[#PAC]] = { {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key"
+// OVERRIDE-DAG: attributes #[[#PAC]] = { {{.*}} "ignore-branch-target-enforcement" {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key"
-// CHECK-DAG: attributes #[[#PACLEAF]] = { {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key"
+// NO-OVERRIDE-DAG: attributes #[[#PACLEAF]] = { {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key"
+// OVERRIDE-DAG: attributes #[[#PACLEAF]] = { {{.*}} "ignore-branch-target-enforcement" {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key"
-// CHECK-DAG: attributes #[[#PACBKEY]] = { {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="b_key"
+// NO-OVERRIDE-DAG: attributes #[[#PACBKEY]] = { {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="b_key"
+// OVERRIDE: attributes #[[#PACBKEY]] = { {{.*}} "ignore-branch-target-enforcement" {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="b_key"
-// CHECK-DAG: attributes #[[#PACBKEYLEAF]] = { {{.*}} "sign-return-address"="all" "sign-return-address-key"="b_key"
+// NO-OVERRIDE-DAG: attributes #[[#PACBKEYLEAF]] = { {{.*}} "sign-return-address"="all" "sign-return-address-key"="b_key"
+// OVERRIDE-DAG: attributes #[[#PACBKEYLEAF]] = { {{.*}} "ignore-branch-target-enforcement" {{.*}} "sign-return-address"="all" "sign-return-address-key"="b_key"
-// CHECK-DAG: attributes #[[#BTIPACLEAF]] = { {{.*}}"branch-target-enforcement" {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key"
+// CHECK-DAG: attributes #[[#BTIPACLEAF]] = { {{.*}} "branch-target-enforcement" {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key"
Index: clang/lib/CodeGen/TargetInfo.cpp
===================================================================
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -5107,40 +5107,52 @@
if (!FD)
return;
- LangOptions::SignReturnAddressScopeKind Scope =
- CGM.getLangOpts().getSignReturnAddressScope();
- LangOptions::SignReturnAddressKeyKind Key =
- CGM.getLangOpts().getSignReturnAddressKey();
- bool BranchTargetEnforcement = CGM.getLangOpts().BranchTargetEnforcement;
if (const auto *TA = FD->getAttr<TargetAttr>()) {
ParsedTargetAttr Attr = TA->parse();
if (!Attr.BranchProtection.empty()) {
TargetInfo::BranchProtectionInfo BPI;
StringRef Error;
+ LangOptions::SignReturnAddressScopeKind Scope =
+ CGM.getLangOpts().getSignReturnAddressScope();
+ LangOptions::SignReturnAddressKeyKind Key =
+ CGM.getLangOpts().getSignReturnAddressKey();
+
(void)CGM.getTarget().validateBranchProtection(Attr.BranchProtection,
BPI, Error);
assert(Error.empty());
- Scope = BPI.SignReturnAddr;
- Key = BPI.SignKey;
- BranchTargetEnforcement = BPI.BranchTargetEnforcement;
- }
- }
-
- auto *Fn = cast<llvm::Function>(GV);
- if (Scope != LangOptions::SignReturnAddressScopeKind::None) {
- Fn->addFnAttr("sign-return-address",
- Scope == LangOptions::SignReturnAddressScopeKind::All
- ? "all"
- : "non-leaf");
+ auto *Fn = cast<llvm::Function>(GV);
+
+ // Update flags only when differ from the codegen flags.
+ if (Scope != BPI.SignReturnAddr || Key != BPI.SignKey) {
+ Scope = BPI.SignReturnAddr;
+ Key = BPI.SignKey;
+ if (Scope != LangOptions::SignReturnAddressScopeKind::None) {
+ Fn->addFnAttr("sign-return-address",
+ Scope == LangOptions::SignReturnAddressScopeKind::All
+ ? "all"
+ : "non-leaf");
+
+ Fn->addFnAttr("sign-return-address-key",
+ Key == LangOptions::SignReturnAddressKeyKind::AKey
+ ? "a_key"
+ : "b_key");
+ } else {
+ Fn->removeAttribute(llvm::AttributeList::FunctionIndex,
+ "sign-return-address");
+ Fn->removeAttribute(llvm::AttributeList::FunctionIndex,
+ "sign-return-address-key");
+ }
+ }
- Fn->addFnAttr("sign-return-address-key",
- Key == LangOptions::SignReturnAddressKeyKind::AKey
- ? "a_key"
- : "b_key");
+ if (!BPI.BranchTargetEnforcement) {
+ Fn->addFnAttr("ignore-branch-target-enforcement");
+ Fn->removeAttribute(llvm::AttributeList::FunctionIndex,
+ "branch-target-enforcement");
+ } else {
+ Fn->addFnAttr("branch-target-enforcement");
+ }
+ }
}
-
- if (BranchTargetEnforcement)
- Fn->addFnAttr("branch-target-enforcement");
}
};
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -588,6 +588,27 @@
1);
}
+ if (Context.getLangOpts().BranchTargetEnforcement) {
+ getModule().addModuleFlag(llvm::Module::Override,
+ "branch-target-enforcement", 1);
+ }
+
+ LangOptions::SignReturnAddressScopeKind Scope =
+ Context.getLangOpts().getSignReturnAddressScope();
+ if (Scope != LangOptions::SignReturnAddressScopeKind::None) {
+ getModule().addModuleFlag(
+ llvm::Module::Override, "sign-return-address",
+ Scope == LangOptions::SignReturnAddressScopeKind::All
+ ? llvm::MDString::get(VMContext, "all")
+ : llvm::MDString::get(VMContext, "non-leaf"));
+ getModule().addModuleFlag(
+ llvm::Module::Override, "sign-return-address-key",
+ Context.getLangOpts().getSignReturnAddressKey() ==
+ LangOptions::SignReturnAddressKeyKind::AKey
+ ? llvm::MDString::get(VMContext, "a_key")
+ : llvm::MDString::get(VMContext, "b_key"));
+ }
+
if (LangOpts.CUDAIsDevice && getTriple().isNVPTX()) {
// Indicate whether __nvvm_reflect should be configured to flush denormal
// floating point values to 0. (This corresponds to its "__CUDA_FTZ"
Index: clang/lib/CodeGen/CGCall.cpp
===================================================================
--- clang/lib/CodeGen/CGCall.cpp
+++ clang/lib/CodeGen/CGCall.cpp
@@ -1823,6 +1823,22 @@
std::tie(Var, Value) = Attr.split('=');
FuncAttrs.addAttribute(Var, Value);
}
+
+ auto RASignKind = getLangOpts().getSignReturnAddressScope();
+ if (RASignKind != LangOptions::SignReturnAddressScopeKind::None) {
+ FuncAttrs.addAttribute("sign-return-address",
+ RASignKind ==
+ LangOptions::SignReturnAddressScopeKind::All
+ ? "all"
+ : "non-leaf");
+ auto RASignKey = getLangOpts().getSignReturnAddressKey();
+ FuncAttrs.addAttribute(
+ "sign-return-address-key",
+ RASignKey == LangOptions::SignReturnAddressKeyKind::AKey ? "a_key"
+ : "b_key");
+ }
+ if (getLangOpts().BranchTargetEnforcement)
+ FuncAttrs.addAttribute("branch-target-enforcement");
}
void CodeGenModule::AddDefaultFnAttrs(llvm::Function &F) {
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits