Author: Dan Blackwell
Date: 2026-01-22T14:22:44Z
New Revision: c63a744f3fbc91f0f544d79a50ae91e860d092b7

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

LOG: [CodeGen][InstCombine][Sanitizers] Emit lifetimes when compiling with 
memtag-stack (#177130)

Currently we do not emit lifetimes by default when compiling with
memtag-stack - which means we don't catch use-after-scope (when
compiling without optimization).

This patch fixes that by mirroring ASan, HWASan and MSan, and always
emitting lifetime markers. The patch is based on the changes made in
aeca569.

rdar://163713381

Added: 
    

Modified: 
    clang/lib/CodeGen/CGExpr.cpp
    clang/lib/CodeGen/CodeGenFunction.cpp
    clang/test/CodeGen/lifetime-sanitizer.c
    clang/test/CodeGenCXX/lifetime-sanitizer.cpp
    llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
    llvm/test/Transforms/InstCombine/lifetime-sanitizer.ll

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 2a5ae8da72512..76a3939cd28eb 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -620,6 +620,7 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr 
*M) {
       if (isInConditionalBranch() && !E->getType().isDestructedType() &&
           ((!SanOpts.has(SanitizerKind::HWAddress) &&
             !SanOpts.has(SanitizerKind::Memory) &&
+            !SanOpts.has(SanitizerKind::MemtagStack) &&
             !CGM.getCodeGenOpts().SanitizeAddressUseAfterScope) ||
            inSuspendBlock())) {
         OldConditional = OutermostConditional;

diff  --git a/clang/lib/CodeGen/CodeGenFunction.cpp 
b/clang/lib/CodeGen/CodeGenFunction.cpp
index bec359eb2b6b3..1ddcfbbe6461b 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -69,7 +69,8 @@ static bool shouldEmitLifetimeMarkers(const CodeGenOptions 
&CGOpts,
   // Sanitizers may use markers.
   if (CGOpts.SanitizeAddressUseAfterScope ||
       LangOpts.Sanitize.has(SanitizerKind::HWAddress) ||
-      LangOpts.Sanitize.has(SanitizerKind::Memory))
+      LangOpts.Sanitize.has(SanitizerKind::Memory) ||
+      LangOpts.Sanitize.has(SanitizerKind::MemtagStack))
     return true;
 
   // For now, only in optimized builds.

diff  --git a/clang/test/CodeGen/lifetime-sanitizer.c 
b/clang/test/CodeGen/lifetime-sanitizer.c
index 4d36bd7a9fee5..e529dccc35cc4 100644
--- a/clang/test/CodeGen/lifetime-sanitizer.c
+++ b/clang/test/CodeGen/lifetime-sanitizer.c
@@ -12,6 +12,9 @@
 // RUN: %clang -target aarch64-linux-gnu -S -emit-llvm -o - -O0 \
 // RUN:     -fsanitize=hwaddress -Xclang -disable-llvm-passes %s | \
 // RUN:     FileCheck %s -check-prefix=LIFETIME
+// RUN: %clang -target aarch64-linux-gnu -S -emit-llvm -o - -O0 \
+// RUN:     -fsanitize=memtag-stack -march=armv8a+memtag -Xclang 
-disable-llvm-passes %s | \
+// RUN:     FileCheck %s -check-prefix=LIFETIME
 
 extern int bar(char *A, int n);
 

diff  --git a/clang/test/CodeGenCXX/lifetime-sanitizer.cpp 
b/clang/test/CodeGenCXX/lifetime-sanitizer.cpp
index 225d5e28921b8..a1557b03082b6 100644
--- a/clang/test/CodeGenCXX/lifetime-sanitizer.cpp
+++ b/clang/test/CodeGenCXX/lifetime-sanitizer.cpp
@@ -13,6 +13,9 @@
 // RUN: %clang -w -target aarch64-linux-gnu -S -emit-llvm -o - -fno-exceptions 
-O0 \
 // RUN:     -fsanitize=hwaddress -Xclang -disable-llvm-passes %s | \
 // RUN:     FileCheck %s -check-prefixes=CHECK,LIFETIME
+// RUN: %clang -w -target aarch64-linux-gnu -S -emit-llvm -o - -fno-exceptions 
-O0 \
+// RUN:     -fsanitize=memtag-stack -march=armv8a+memtag -Xclang 
-disable-llvm-passes %s | \
+// RUN:     FileCheck %s -check-prefixes=CHECK,LIFETIME
 
 extern int bar(char *A, int n);
 

diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index b870ac259d3b0..00b45545178ae 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -3524,7 +3524,8 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst 
&CI) {
     // even for empty lifetime range.
     if (II->getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
         II->getFunction()->hasFnAttribute(Attribute::SanitizeMemory) ||
-        II->getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress))
+        II->getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress) ||
+        II->getFunction()->hasFnAttribute(Attribute::SanitizeMemTag))
       break;
 
     if (removeTriviallyEmptyRange(*II, *this, [](const IntrinsicInst &I) {

diff  --git a/llvm/test/Transforms/InstCombine/lifetime-sanitizer.ll 
b/llvm/test/Transforms/InstCombine/lifetime-sanitizer.ll
index fd45fe2dd27d7..2f4e3e3528a2e 100644
--- a/llvm/test/Transforms/InstCombine/lifetime-sanitizer.ll
+++ b/llvm/test/Transforms/InstCombine/lifetime-sanitizer.ll
@@ -34,6 +34,21 @@ entry:
   ret void
 }
 
+define void @memtag() sanitize_memtag {
+entry:
+  ; CHECK-LABEL: @memtag(
+  %text = alloca i8, align 1
+
+  call void @llvm.lifetime.start.p0(ptr %text)
+  call void @llvm.lifetime.end.p0(ptr %text)
+  ; CHECK: call void @llvm.lifetime.start
+  ; CHECK-NEXT: call void @llvm.lifetime.end
+
+  call void @foo(ptr %text) ; Keep alloca alive
+
+  ret void
+}
+
 define void @msan() sanitize_memory {
 entry:
   ; CHECK-LABEL: @msan(


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

Reply via email to