[clang] [LifetimeSafety] Prefer macro spelling for lifetimebound fix-its (PR #204045)
Zeyi Xu via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 15 19:02:54 PDT 2026
https://github.com/zeyi2 created https://github.com/llvm/llvm-project/pull/204045
None
>From 1ee4bc273b8a1ecc17e8645a13ee97986d397ab2 Mon Sep 17 00:00:00 2001
From: Zeyi Xu <mitchell.xu2 at gmail.com>
Date: Tue, 16 Jun 2026 10:02:39 +0800
Subject: [PATCH] [LifetimeSafety] Prefer macro spelling for lifetimebound
fix-its
---
clang/lib/Sema/SemaLifetimeSafety.h | 26 ++++++++++----
.../test/Sema/warn-lifetime-safety-fixits.cpp | 34 +++++++++++++++++++
2 files changed, 54 insertions(+), 6 deletions(-)
diff --git a/clang/lib/Sema/SemaLifetimeSafety.h b/clang/lib/Sema/SemaLifetimeSafety.h
index 6da4953dea56d..f76fb6a58b8f9 100644
--- a/clang/lib/Sema/SemaLifetimeSafety.h
+++ b/clang/lib/Sema/SemaLifetimeSafety.h
@@ -19,6 +19,7 @@
#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h"
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Sema.h"
#include <string>
@@ -403,27 +404,39 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
}
private:
- std::pair<SourceLocation, StringRef>
+ std::string getLifetimeBoundFixItText(SourceLocation Loc, bool LeadingSpace) {
+ const Preprocessor &PP = S.getPreprocessor();
+ const StringRef Spelling = PP.getLastMacroWithSpelling(
+ Loc, {tok::l_square, tok::l_square, PP.getIdentifierInfo("clang"),
+ tok::coloncolon, PP.getIdentifierInfo("lifetimebound"),
+ tok::r_square, tok::r_square});
+ const std::string Text =
+ Spelling.empty() ? "[[clang::lifetimebound]]" : Spelling.str();
+ return LeadingSpace ? " " + Text : Text + " ";
+ }
+
+ std::pair<SourceLocation, std::string>
getLifetimeBoundFixIt(const ParmVarDecl *Decl) {
SourceLocation InsertionPoint = Lexer::getLocForEndOfToken(
Decl->getEndLoc(), 0, S.getSourceManager(), S.getLangOpts());
- StringRef FixItText = " [[clang::lifetimebound]]";
+ bool LeadingSpace = true;
if (!Decl->getIdentifier()) {
// For unnamed parameters, placing attributes after the type would be
// parsed as a type attribute, not a parameter attribute.
InsertionPoint = Decl->getBeginLoc();
- FixItText = "[[clang::lifetimebound]] ";
+ LeadingSpace = false;
} else if (Decl->hasDefaultArg()) {
// If the parameter has a default argument, place the attribute after the
// named argument.
InsertionPoint = Lexer::getLocForEndOfToken(
Decl->getLocation(), 0, S.getSourceManager(), S.getLangOpts());
}
- return {InsertionPoint, FixItText};
+ return {InsertionPoint,
+ getLifetimeBoundFixItText(InsertionPoint, LeadingSpace)};
}
- std::pair<SourceLocation, StringRef>
+ std::pair<SourceLocation, std::string>
getLifetimeBoundFixIt(const CXXMethodDecl *MD) {
const auto MDL = MD->getTypeSourceInfo()->getTypeLoc();
SourceLocation InsertionPoint = Lexer::getLocForEndOfToken(
@@ -444,7 +457,8 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
->getLocation(),
0, S.getSourceManager(), S.getLangOpts());
}
- return {InsertionPoint, " [[clang::lifetimebound]]"};
+ return {InsertionPoint, getLifetimeBoundFixItText(InsertionPoint,
+ /*LeadingSpace=*/true)};
}
std::string getDiagSubjectDescription(const ValueDecl *VD) {
diff --git a/clang/test/Sema/warn-lifetime-safety-fixits.cpp b/clang/test/Sema/warn-lifetime-safety-fixits.cpp
index d9c7e8d3f0519..e1a89f9047457 100644
--- a/clang/test/Sema/warn-lifetime-safety-fixits.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-fixits.cpp
@@ -174,3 +174,37 @@ struct TrailingReturn {
return data;
}
};
+
+#define MY_LIFETIMEBOUND_MACRO [[clang::lifetimebound]]
+
+View unnamed_macro(View);
+// CHECK: :[[@LINE-1]]:20: warning: parameter in intra-TU function should be marked
+// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:20-[[@LINE-2]]:20}:"MY_LIFETIMEBOUND_MACRO "
+View unnamed_macro(View a) {
+ return a;
+}
+
+View return_view_with_macro(View a) {
+ // CHECK: :[[@LINE-1]]:29: warning: parameter in intra-TU function should be marked
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:35-[[@LINE-2]]:35}:" MY_LIFETIMEBOUND_MACRO"
+ return a;
+}
+
+#define FIRST_LIFETIMEBOUND_MACRO [[clang::lifetimebound]]
+#define SECOND_LIFETIMEBOUND_MACRO [[clang::lifetimebound]]
+
+View return_view_with_latest_macro(View a) {
+ // CHECK: :[[@LINE-1]]:36: warning: parameter in intra-TU function should be marked
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:42-[[@LINE-2]]:42}:" SECOND_LIFETIMEBOUND_MACRO"
+ return a;
+}
+
+struct MacroMember {
+ MyObj data;
+
+ View get_view() {
+ // CHECK: :[[@LINE-1]]:18: warning: implicit this in intra-TU function should be marked
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:18-[[@LINE-2]]:18}:" SECOND_LIFETIMEBOUND_MACRO"
+ return data;
+ }
+};
More information about the cfe-commits
mailing list