Date: Thursday, May 19, 2022 @ 19:03:54 Author: foutrelis Revision: 446100
upgpkg: llvm 13.0.1-4: backport no_stack_protector fix Fixes Chromium spamming "*** stack smashing detected ***: terminated". Added: llvm/trunk/don-t-override-__attribute__-no_stack_protector.patch Modified: llvm/trunk/PKGBUILD -------------------------------------------------------+ PKGBUILD | 9 don-t-override-__attribute__-no_stack_protector.patch | 540 ++++++++++++++++ 2 files changed, 548 insertions(+), 1 deletion(-) Modified: PKGBUILD =================================================================== --- PKGBUILD 2022-05-19 18:11:05 UTC (rev 446099) +++ PKGBUILD 2022-05-19 19:03:54 UTC (rev 446100) @@ -3,7 +3,7 @@ pkgname=('llvm' 'llvm-libs' 'llvm-ocaml') pkgver=13.0.1 -pkgrel=3 +pkgrel=4 _ocaml_ver=4.13.1 arch=('x86_64') url="https://llvm.org/" @@ -16,6 +16,7 @@ _source_base=https://github.com/llvm/llvm-project/releases/download/llvmorg-$pkgver source=($_source_base/$pkgname-$pkgver.src.tar.xz{,.sig} don-t-accept-nullptr-as-GEP-element-type.patch + don-t-override-__attribute__-no_stack_protector.patch don-t-move-DBG_VALUE-instructions.patch no-strict-aliasing-DwarfCompileUnit.patch disable-A-B-A-B-and-BSWAP-in-InstCombine.patch @@ -24,6 +25,7 @@ sha256sums=('ec6b80d82c384acad2dc192903a6cf2cdbaffb889b84bfb98da9d71e630fc834' 'SKIP' 'a7e902a7612d0fdabe436a917468b043cc296bc89d8954bfc3126f737beb9ac4' + '9f0a4578b94eb8853b83af2f65e92705254b4b56d96f9a941714d174b932f465' 'f7d69f84241416398fdb3df8bb44f9fae3c49d89889c7ffa3b37aa2e9d78f708' 'd1eff24508e35aae6c26a943dbaa3ef5acb60a145b008fd1ef9ac6f6c4faa662' '34cc0d79a30599cb2287b47b4e9a1a5bf03d57a1f8bb35be3fe976ffc4a604f6' @@ -39,6 +41,11 @@ # https://github.com/intel/intel-graphics-compiler/issues/204 patch -Rp2 -i ../don-t-accept-nullptr-as-GEP-element-type.patch + # Fixes Chromium error "*** stack smashing detected ***: terminated" + # (which also goes away with "--change-stack-guard-on-fork=disabled") + # https://reviews.llvm.org/D116589 + patch -Np2 -i ../don-t-override-__attribute__-no_stack_protector.patch + # https://github.com/llvm/llvm-project/issues/53243 # https://github.com/rust-lang/rust/issues/92869 patch -Np2 -i ../don-t-move-DBG_VALUE-instructions.patch Added: don-t-override-__attribute__-no_stack_protector.patch =================================================================== --- don-t-override-__attribute__-no_stack_protector.patch (rev 0) +++ don-t-override-__attribute__-no_stack_protector.patch 2022-05-19 19:03:54 UTC (rev 446100) @@ -0,0 +1,540 @@ +From 4a7c9b7d6f4a183fef8f43aef004ec865c37bbd8 Mon Sep 17 00:00:00 2001 +From: Hans Wennborg <h...@chromium.org> +Date: Thu, 13 Jan 2022 11:31:11 +0100 +Subject: [PATCH 1/2] Simplify llvm/test/Transforms/Inline/inline_ssp.ll (NFC) + +The nounwind and uwtable attributes were just cluttering up the test. +Using regexes to give symbolic names to the attribute lists make the +test more readable. + +This is pre-committing parts of D116589. + +(cherry picked from commit 2eb7d8d749997e5f3048d39201a4d38b6b8d6455) +--- + llvm/test/Transforms/Inline/inline_ssp.ll | 81 +++++++++++------------ + 1 file changed, 40 insertions(+), 41 deletions(-) + +diff --git a/llvm/test/Transforms/Inline/inline_ssp.ll b/llvm/test/Transforms/Inline/inline_ssp.ll +index 2bf93d322842..ccfe93453159 100644 +--- a/llvm/test/Transforms/Inline/inline_ssp.ll ++++ b/llvm/test/Transforms/Inline/inline_ssp.ll +@@ -12,150 +12,149 @@ + ; propagated correctly. The caller should have its SSP attribute set as: + ; strictest(caller-ssp-attr, callee-ssp-attr), where strictness is ordered as: + ; sspreq > sspstrong > ssp > [no ssp] +-define internal void @fun_sspreq() nounwind sspreq uwtable { ++define internal void @fun_sspreq() sspreq { + entry: + %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str3, i32 0, i32 0)) + ret void + } + +-define internal void @fun_sspstrong() nounwind sspstrong uwtable { ++define internal void @fun_sspstrong() sspstrong { + entry: + %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str2, i32 0, i32 0)) + ret void + } + +-define internal void @fun_ssp() nounwind ssp uwtable { ++define internal void @fun_ssp() ssp { + entry: + %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str1, i32 0, i32 0)) + ret void + } + +-define internal void @fun_nossp() nounwind uwtable { ++define internal void @fun_nossp() { + entry: + %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0)) + ret void + } + +-; Tests start below ++; Tests start below. + +-define void @inline_req_req() nounwind sspreq uwtable { ++define void @inline_req_req() sspreq { + entry: +-; CHECK: @inline_req_req() #0 ++; CHECK: @inline_req_req() #[[SSPREQ:[0-9]]] + call void @fun_sspreq() + ret void + } + +-define void @inline_req_strong() nounwind sspstrong uwtable { ++define void @inline_req_strong() sspstrong { + entry: +-; CHECK: @inline_req_strong() #0 ++; CHECK: @inline_req_strong() #[[SSPREQ]] + call void @fun_sspreq() + ret void + } + +-define void @inline_req_ssp() nounwind ssp uwtable { ++define void @inline_req_ssp() ssp { + entry: +-; CHECK: @inline_req_ssp() #0 ++; CHECK: @inline_req_ssp() #[[SSPREQ]] + call void @fun_sspreq() + ret void + } + +-define void @inline_req_nossp() nounwind uwtable { ++define void @inline_req_nossp() { + entry: +-; CHECK: @inline_req_nossp() #3 ++; CHECK: @inline_req_nossp() { + call void @fun_sspreq() + ret void + } + +-define void @inline_strong_req() nounwind sspreq uwtable { ++define void @inline_strong_req() sspreq { + entry: +-; CHECK: @inline_strong_req() #0 ++; CHECK: @inline_strong_req() #[[SSPREQ]] + call void @fun_sspstrong() + ret void + } + + +-define void @inline_strong_strong() nounwind sspstrong uwtable { ++define void @inline_strong_strong() sspstrong { + entry: +-; CHECK: @inline_strong_strong() #1 ++; CHECK: @inline_strong_strong() #[[SSPSTRONG:[0-9]]] + call void @fun_sspstrong() + ret void + } + +-define void @inline_strong_ssp() nounwind ssp uwtable { ++define void @inline_strong_ssp() ssp { + entry: +-; CHECK: @inline_strong_ssp() #1 ++; CHECK: @inline_strong_ssp() #[[SSPSTRONG]] + call void @fun_sspstrong() + ret void + } + +-define void @inline_strong_nossp() nounwind uwtable { ++define void @inline_strong_nossp() { + entry: +-; CHECK: @inline_strong_nossp() #3 ++; CHECK: @inline_strong_nossp() { + call void @fun_sspstrong() + ret void + } + +-define void @inline_ssp_req() nounwind sspreq uwtable { ++define void @inline_ssp_req() sspreq { + entry: +-; CHECK: @inline_ssp_req() #0 ++; CHECK: @inline_ssp_req() #[[SSPREQ]] + call void @fun_ssp() + ret void + } + + +-define void @inline_ssp_strong() nounwind sspstrong uwtable { ++define void @inline_ssp_strong() sspstrong { + entry: +-; CHECK: @inline_ssp_strong() #1 ++; CHECK: @inline_ssp_strong() #[[SSPSTRONG]] + call void @fun_ssp() + ret void + } + +-define void @inline_ssp_ssp() nounwind ssp uwtable { ++define void @inline_ssp_ssp() ssp { + entry: +-; CHECK: @inline_ssp_ssp() #2 ++; CHECK: @inline_ssp_ssp() #[[SSP:[0-9]]] + call void @fun_ssp() + ret void + } + +-define void @inline_ssp_nossp() nounwind uwtable { ++define void @inline_ssp_nossp() { + entry: +-; CHECK: @inline_ssp_nossp() #3 ++; CHECK: @inline_ssp_nossp() { + call void @fun_ssp() + ret void + } + +-define void @inline_nossp_req() nounwind uwtable sspreq { ++define void @inline_nossp_req() sspreq { + entry: +-; CHECK: @inline_nossp_req() #0 ++; CHECK: @inline_nossp_req() #[[SSPREQ]] + call void @fun_nossp() + ret void + } + + +-define void @inline_nossp_strong() nounwind sspstrong uwtable { ++define void @inline_nossp_strong() sspstrong { + entry: +-; CHECK: @inline_nossp_strong() #1 ++; CHECK: @inline_nossp_strong() #[[SSPSTRONG]] + call void @fun_nossp() + ret void + } + +-define void @inline_nossp_ssp() nounwind ssp uwtable { ++define void @inline_nossp_ssp() ssp { + entry: +-; CHECK: @inline_nossp_ssp() #2 ++; CHECK: @inline_nossp_ssp() #[[SSP]] + call void @fun_nossp() + ret void + } + +-define void @inline_nossp_nossp() nounwind uwtable { ++define void @inline_nossp_nossp() { + entry: +-; CHECK: @inline_nossp_nossp() #3 ++; CHECK: @inline_nossp_nossp() { + call void @fun_nossp() + ret void + } + + declare i32 @printf(i8*, ...) + +-; CHECK: attributes #0 = { nounwind sspreq uwtable } +-; CHECK: attributes #1 = { nounwind sspstrong uwtable } +-; CHECK: attributes #2 = { nounwind ssp uwtable } +-; CHECK: attributes #3 = { nounwind uwtable } ++; CHECK: attributes #[[SSPREQ]] = { sspreq } ++; CHECK: attributes #[[SSPSTRONG]] = { sspstrong } ++; CHECK: attributes #[[SSP]] = { ssp } + +From b52296ecaa3878648ceeb3aa39df05dc71e44597 Mon Sep 17 00:00:00 2001 +From: Hans Wennborg <h...@chromium.org> +Date: Mon, 3 Jan 2022 18:03:43 +0100 +Subject: [PATCH 2/2] Don't override __attribute__((no_stack_protector)) by + inlining (PR52886) + +Since 26c6a3e736d3, LLVM's inliner will "upgrade" the caller's stack protector +attribute based on the callee. This lead to surprising results with Clang's +no_stack_protector attribute added in 4fbf84c1732f (D46300). Consider the +following code compiled with clang -fstack-protector-strong -Os +(https://godbolt.org/z/7s3rW7a1q). + + extern void h(int* p); + + inline __attribute__((always_inline)) int g() { + return 0; + } + + int __attribute__((__no_stack_protector__)) f() { + int a[1]; + h(a); + return g(); + } + +LLVM will inline g() into f(), and f() would get a stack protector, against the +users explicit wishes, potentially breaking the program e.g. if h() changes the +value of the stack cookie. That's a miscompile. + +More recently, bc044a88ee3c (D91816) addressed this problem by preventing +inlining when the stack protector is disabled in the caller and enabled in the +callee or vice versa. However, the problem remained if the callee is marked +always_inline as in the example above. This affected users, see e.g. +http://crbug.com/1274129 and http://llvm.org/pr52886. + +One way to fix this would be to prevent inlining also in the always_inline +case. Despite the name, always_inline does not guarantee inlining, so this +would be legal but potentially surprising to users. + +However, I think the better fix is to not enable the stack protector in a +caller based on the callee. The motivation for the old behaviour is unclear, it +seems counter-intuitive, and causes real problems as we've seen. + +This commit implements that fix, which means in the example above, g() gets +inlined into f() (also without always_inline), and f() is emitted without stack +protector. I think that matches most developers' expectations, and that's also +what GCC does. + +Another effect of this change is that a no_stack_protector function can now be +inlined into a stack protected function, e.g. (https://godbolt.org/z/hafP6W856): + + extern void h(int* p); + + inline int __attribute__((__no_stack_protector__)) __attribute__((always_inline)) g() { + return 0; + } + + int f() { + int a[1]; + h(a); + return g(); + } + +I think that's fine. Such code would be unusual since no_stack_protector is +normally applied to a program entry point which sets up the stack canary. And +even if such code exists, inlining doesn't change the semantics: there is still +no stack cookie setup/check around entry/exit of the g() code region, but there +may be in the surrounding context, as there was before inlining. This also +matches GCC. + +See also the discussion at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94722 + +Differential revision: https://reviews.llvm.org/D116589 + +(cherry picked from commit 2bc57d85ebf244f19a3046295b58eb8c667f947d) +--- + llvm/docs/LangRef.rst | 26 +++++------ + llvm/lib/Analysis/InlineCost.cpp | 9 ---- + llvm/lib/IR/Attributes.cpp | 6 +++ + llvm/test/ThinLTO/X86/nossp.ll | 23 ++++++---- + llvm/test/Transforms/Inline/inline_nossp.ll | 50 --------------------- + llvm/test/Transforms/Inline/inline_ssp.ll | 19 +++++++- + 6 files changed, 48 insertions(+), 85 deletions(-) + delete mode 100644 llvm/test/Transforms/Inline/inline_nossp.ll + +diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst +index 36e09355e485..69393eba3906 100644 +--- a/llvm/docs/LangRef.rst ++++ b/llvm/docs/LangRef.rst +@@ -1965,11 +1965,9 @@ example: + Variables that are identified as requiring a protector will be arranged + on the stack such that they are adjacent to the stack protector guard. + +- A function with the ``ssp`` attribute but without the ``alwaysinline`` +- attribute cannot be inlined into a function without a +- ``ssp/sspreq/sspstrong`` attribute. If inlined, the caller will get the +- ``ssp`` attribute. ``call``, ``invoke``, and ``callbr`` instructions with +- the ``alwaysinline`` attribute force inlining. ++ If a function with an ``ssp`` attribute is inlined into a calling function, ++ the attribute is not carried over to the calling function. ++ + ``sspstrong`` + This attribute indicates that the function should emit a stack smashing + protector. This attribute causes a strong heuristic to be used when +@@ -1994,12 +1992,10 @@ example: + + This overrides the ``ssp`` function attribute. + +- A function with the ``sspstrong`` attribute but without the +- ``alwaysinline`` attribute cannot be inlined into a function without a +- ``ssp/sspstrong/sspreq`` attribute. If inlined, the caller will get the +- ``sspstrong`` attribute unless the ``sspreq`` attribute exists. ``call``, +- ``invoke``, and ``callbr`` instructions with the ``alwaysinline`` attribute +- force inlining. ++ If a function with an ``sspstrong`` attribute is inlined into a calling ++ function which has an ``ssp`` attribute, the calling function's attribute ++ will be upgraded to ``sspstrong``. ++ + ``sspreq`` + This attribute indicates that the function should *always* emit a stack + smashing protector. This overrides the ``ssp`` and ``sspstrong`` function +@@ -2016,11 +2012,9 @@ example: + #. Variables that have had their address taken are 3rd closest to the + protector. + +- A function with the ``sspreq`` attribute but without the ``alwaysinline`` +- attribute cannot be inlined into a function without a +- ``ssp/sspstrong/sspreq`` attribute. If inlined, the caller will get the +- ``sspreq`` attribute. ``call``, ``invoke``, and ``callbr`` instructions +- with the ``alwaysinline`` attribute force inlining. ++ If a function with an ``sspreq`` attribute is inlined into a calling ++ function which has an ``ssp`` or ``sspstrong`` attribute, the calling ++ function's attribute will be upgraded to ``sspreq``. + + ``strictfp`` + This attribute indicates that the function was called from a scope that +diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp +index e8f79a28a8e8..1e68ec8ff7d6 100644 +--- a/llvm/lib/Analysis/InlineCost.cpp ++++ b/llvm/lib/Analysis/InlineCost.cpp +@@ -2823,15 +2823,6 @@ Optional<InlineResult> llvm::getAttributeBasedInliningDecision( + if (Call.isNoInline()) + return InlineResult::failure("noinline call site attribute"); + +- // Don't inline functions if one does not have any stack protector attribute +- // but the other does. +- if (Caller->hasStackProtectorFnAttr() && !Callee->hasStackProtectorFnAttr()) +- return InlineResult::failure( +- "stack protected caller but callee requested no stack protector"); +- if (Callee->hasStackProtectorFnAttr() && !Caller->hasStackProtectorFnAttr()) +- return InlineResult::failure( +- "stack protected callee but caller requested no stack protector"); +- + return None; + } + +diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp +index 5cd1bafccc47..eec4629aa725 100644 +--- a/llvm/lib/IR/Attributes.cpp ++++ b/llvm/lib/IR/Attributes.cpp +@@ -1957,6 +1957,12 @@ static void setOR(Function &Caller, const Function &Callee) { + /// If the inlined function had a higher stack protection level than the + /// calling function, then bump up the caller's stack protection level. + static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) { ++ // If the calling function has *no* stack protection level (e.g. it was built ++ // with Clang's -fno-stack-protector or no_stack_protector attribute), don't ++ // change it as that could change the program's semantics. ++ if (!Caller.hasStackProtectorFnAttr()) ++ return; ++ + // If upgrading the SSP attribute, clear out the old SSP Attributes first. + // Having multiple SSP attributes doesn't actually hurt, but it adds useless + // clutter to the IR. +diff --git a/llvm/test/ThinLTO/X86/nossp.ll b/llvm/test/ThinLTO/X86/nossp.ll +index c542a85c6f74..cfc54d595ad7 100644 +--- a/llvm/test/ThinLTO/X86/nossp.ll ++++ b/llvm/test/ThinLTO/X86/nossp.ll +@@ -23,7 +23,8 @@ declare void @ssp_callee() ssp + + ; nossp caller should be able to inline nossp callee. + define void @nossp_caller() { +-; CHECK-LABEL: @nossp_caller ++; CHECK-LABEL: define void @nossp_caller() ++; CHECK-NOT: #0 + ; CHECK-NEXT: tail call void @foo + tail call void @nossp_callee() + ret void +@@ -31,28 +32,34 @@ define void @nossp_caller() { + + ; ssp caller should be able to inline ssp callee. + define void @ssp_caller() ssp { +-; CHECK-LABEL: @ssp_caller ++; CHECK-LABEL: define void @ssp_caller() ++; CHECK-SAME: #0 + ; CHECK-NEXT: tail call void @foo + tail call void @ssp_callee() + ret void + } + +-; nossp caller should *NOT* be able to inline ssp callee. ++; nossp caller should be able to inline ssp callee. ++; the ssp attribute is not propagated. + define void @nossp_caller2() { +-; CHECK-LABEL: @nossp_caller2 +-; CHECK-NEXT: tail call void @ssp_callee ++; CHECK-LABEL: define void @nossp_caller2() ++; CHECK-NOT: #0 ++; CHECK-NEXT: tail call void @foo + tail call void @ssp_callee() + ret void + } + +-; ssp caller should *NOT* be able to inline nossp callee. ++; ssp caller should be able to inline nossp callee. + define void @ssp_caller2() ssp { +-; CHECK-LABEL: @ssp_caller2 +-; CHECK-NEXT: tail call void @nossp_callee ++; CHECK-LABEL: define void @ssp_caller2() ++; CHECK-SAME: #0 ++; CHECK-NEXT: tail call void @foo + tail call void @nossp_callee() + ret void + } + ++; CHECK: attributes #0 = { ssp } ++ + ;--- b.ll + target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + target triple = "x86_64-pc-linux-gnu" +diff --git a/llvm/test/Transforms/Inline/inline_nossp.ll b/llvm/test/Transforms/Inline/inline_nossp.ll +deleted file mode 100644 +index 24fdab0b9f13..000000000000 +--- a/llvm/test/Transforms/Inline/inline_nossp.ll ++++ /dev/null +@@ -1,50 +0,0 @@ +-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +-; RUN: opt -passes='cgscc(inline)' %s -S -pass-remarks-missed=inline 2>&1 | FileCheck --check-prefixes=CHECK,CHECK-INLINE %s +-; RUN: opt -passes=always-inline -o - -S %s | FileCheck %s +- +-; CHECK-INLINE: ssp not inlined into nossp_caller because it should never be inlined (cost=never): stack protected callee but caller requested no stack protector +-; CHECK-INLINE: nossp not inlined into ssp_caller because it should never be inlined (cost=never): stack protected caller but callee requested no stack protector +- +-; Not interesting to test. +-define i32 @nossp() { ret i32 41 } +-define i32 @ssp() sspstrong { ret i32 42 } +-define i32 @nossp_alwaysinline() alwaysinline { ret i32 43 } +-define i32 @ssp_alwaysinline() sspstrong alwaysinline { ret i32 44 } +- +-; @ssp should not be inlined due to mismatch stack protector. +-; @ssp_alwaysinline should be inlined due to alwaysinline. +-define i32 @nossp_caller() { +-; CHECK-LABEL: @nossp_caller( +-; CHECK-NEXT: [[TMP1:%.*]] = call i32 @ssp() +-; CHECK-NEXT: ret i32 44 +-; +- call i32 @ssp() +- %2 = call i32 @ssp_alwaysinline() +- ret i32 %2 +-} +-; @nossp should not be inlined due to mismatch stack protector. +-; @nossp_alwaysinline should be inlined due to alwaysinline. +-define i32 @ssp_caller() sspstrong { +-; CHECK-LABEL: @ssp_caller( +-; CHECK-NEXT: [[TMP1:%.*]] = call i32 @nossp() +-; CHECK-NEXT: ret i32 43 +-; +- call i32 @nossp() +- %2 = call i32 @nossp_alwaysinline() +- ret i32 %2 +-} +- +-; The alwaysinline attribute can also appear on the CallBase (ie. the call +-; site), ie. when __attribute__((flatten)) is used on the caller. Treat this +-; the same as if the caller had the fn attr alwaysinline and permit inline +-; substitution, despite the mismatch between caller and callee on ssp attrs. +-; +-; Curiously, the always_inline attribute on a CallInst is only expanded by the +-; inline pass, but not always_inline pass! +-define i32 @nossp_alwaysinline_caller() { +-; CHECK-INLINE-LABEL: @nossp_alwaysinline_caller( +-; CHECK-INLINE-NEXT: ret i32 42 +-; +- %1 = call i32 @ssp() alwaysinline +- ret i32 %1 +-} +diff --git a/llvm/test/Transforms/Inline/inline_ssp.ll b/llvm/test/Transforms/Inline/inline_ssp.ll +index ccfe93453159..a4f73f4dcd5a 100644 +--- a/llvm/test/Transforms/Inline/inline_ssp.ll ++++ b/llvm/test/Transforms/Inline/inline_ssp.ll +@@ -9,15 +9,23 @@ + + ; These first four functions (@fun_sspreq, @fun_sspstrong, @fun_ssp, @fun_nossp) + ; are used by the remaining functions to ensure that the SSP attributes are +-; propagated correctly. The caller should have its SSP attribute set as: ++; propagated correctly. If the caller had an SSP attribute before inlining, it ++; should have its new SSP attribute set as: + ; strictest(caller-ssp-attr, callee-ssp-attr), where strictness is ordered as: +-; sspreq > sspstrong > ssp > [no ssp] ++; sspreq > sspstrong > ssp ++ + define internal void @fun_sspreq() sspreq { + entry: + %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str3, i32 0, i32 0)) + ret void + } + ++define internal void @fun_sspreq_alwaysinline() sspreq alwaysinline { ++entry: ++ %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str3, i32 0, i32 0)) ++ ret void ++} ++ + define internal void @fun_sspstrong() sspstrong { + entry: + %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str2, i32 0, i32 0)) +@@ -66,6 +74,13 @@ entry: + ret void + } + ++define void @alwaysinline_req_nossp() { ++entry: ++; CHECK: @alwaysinline_req_nossp() { ++ call void @fun_sspreq_alwaysinline() ++ ret void ++} ++ + define void @inline_strong_req() sspreq { + entry: + ; CHECK: @inline_strong_req() #[[SSPREQ]]