https://github.com/higher-performance updated https://github.com/llvm/llvm-project/pull/222094
>From ea2f441985a7cfa327775afb8ec3368455c2e153 Mon Sep 17 00:00:00 2001 From: higher-performance <[email protected]> Date: Tue, 8 Sep 2026 14:08:35 -0400 Subject: [PATCH] [clang] Fix deprecation attribute being ignored when used inside other attributes that are already applied to a deprecated symbol --- clang/include/clang/Sema/DelayedDiagnostic.h | 21 ++++++---- clang/include/clang/Sema/Sema.h | 9 +++++ clang/lib/Sema/DelayedDiagnostic.cpp | 16 ++++---- clang/lib/Sema/SemaAvailability.cpp | 40 +++++++++++--------- clang/test/SemaCXX/attr-deprecated.cpp | 27 +++++++++++++ 5 files changed, 78 insertions(+), 35 deletions(-) diff --git a/clang/include/clang/Sema/DelayedDiagnostic.h b/clang/include/clang/Sema/DelayedDiagnostic.h index 0105089a393f1..f4cae24e7bee4 100644 --- a/clang/include/clang/Sema/DelayedDiagnostic.h +++ b/clang/include/clang/Sema/DelayedDiagnostic.h @@ -134,14 +134,13 @@ class DelayedDiagnostic { void Destroy(); - static DelayedDiagnostic makeAvailability(AvailabilityResult AR, - ArrayRef<SourceLocation> Locs, - const NamedDecl *ReferringDecl, - const NamedDecl *OffendingDecl, - const ObjCInterfaceDecl *UnknownObjCClass, - const ObjCPropertyDecl *ObjCProperty, - StringRef Msg, - bool ObjCPropertyAccess); + static DelayedDiagnostic + makeAvailability(AvailabilityResult AR, ArrayRef<SourceLocation> Locs, + const NamedDecl *ReferringDecl, + const NamedDecl *OffendingDecl, + const ObjCInterfaceDecl *UnknownObjCClass, + const ObjCPropertyDecl *ObjCProperty, StringRef Msg, + bool ObjCPropertyAccess, bool InAttrArg); static DelayedDiagnostic makeAccess(SourceLocation Loc, const AccessedEntity &Entity) { @@ -232,6 +231,11 @@ class DelayedDiagnostic { return AvailabilityData.ObjCPropertyAccess; } + bool getAvailabilityInAttrArg() const { + assert(Kind == Availability && "Not an availability diagnostic."); + return AvailabilityData.InAttrArg; + } + private: struct AD { const NamedDecl *ReferringDecl; @@ -244,6 +248,7 @@ class DelayedDiagnostic { size_t NumSelectorLocs; AvailabilityResult AR; bool ObjCPropertyAccess; + bool InAttrArg; }; struct FTD { diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 4ff4c669a6b70..b2d600ba3ab61 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -6989,6 +6989,15 @@ class Sema final : public SemaBase { ExpressionEvaluationContextRecord::ExpressionKind::EK_AttrArgument; } + bool isInsideAttrContext() const { + for (const auto &Record : ExprEvalContexts) { + if (Record.ExprContext == + ExpressionEvaluationContextRecord::ExpressionKind::EK_AttrArgument) + return true; + } + return false; + } + /// Increment when we find a reference; decrement when we find an ignored /// assignment. Ultimately the value is 0 if every reference is an ignored /// assignment. diff --git a/clang/lib/Sema/DelayedDiagnostic.cpp b/clang/lib/Sema/DelayedDiagnostic.cpp index cb2721b92090e..42f9fd0f73c17 100644 --- a/clang/lib/Sema/DelayedDiagnostic.cpp +++ b/clang/lib/Sema/DelayedDiagnostic.cpp @@ -20,15 +20,12 @@ using namespace clang; using namespace sema; -DelayedDiagnostic -DelayedDiagnostic::makeAvailability(AvailabilityResult AR, - ArrayRef<SourceLocation> Locs, - const NamedDecl *ReferringDecl, - const NamedDecl *OffendingDecl, - const ObjCInterfaceDecl *UnknownObjCClass, - const ObjCPropertyDecl *ObjCProperty, - StringRef Msg, - bool ObjCPropertyAccess) { +DelayedDiagnostic DelayedDiagnostic::makeAvailability( + AvailabilityResult AR, ArrayRef<SourceLocation> Locs, + const NamedDecl *ReferringDecl, const NamedDecl *OffendingDecl, + const ObjCInterfaceDecl *UnknownObjCClass, + const ObjCPropertyDecl *ObjCProperty, StringRef Msg, + bool ObjCPropertyAccess, bool InAttrArg) { assert(!Locs.empty()); DelayedDiagnostic DD; DD.Kind = Availability; @@ -53,6 +50,7 @@ DelayedDiagnostic::makeAvailability(AvailabilityResult AR, DD.AvailabilityData.AR = AR; DD.AvailabilityData.ObjCPropertyAccess = ObjCPropertyAccess; + DD.AvailabilityData.InAttrArg = InAttrArg; return DD; } diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp index 6ae08b0783f40..609970efc4728 100644 --- a/clang/lib/Sema/SemaAvailability.cpp +++ b/clang/lib/Sema/SemaAvailability.cpp @@ -163,9 +163,12 @@ Sema::ShouldDiagnoseAvailabilityOfDecl(const NamedDecl *D, std::string *Message, /// whether we should emit a diagnostic for \c K and \c DeclVersion in /// the context of \c Ctx. For example, we should emit an unavailable diagnostic /// in a deprecated context, but not the other way around. -static bool ShouldDiagnoseAvailabilityInContext( - Sema &S, AvailabilityResult K, VersionTuple DeclVersion, - const IdentifierInfo *DeclEnv, Decl *Ctx, const NamedDecl *OffendingDecl) { +static bool ShouldDiagnoseAvailabilityInContext(Sema &S, AvailabilityResult K, + VersionTuple DeclVersion, + const IdentifierInfo *DeclEnv, + Decl *Ctx, + const NamedDecl *OffendingDecl, + bool InAttrArg) { assert(K != AR_Available && "Expected an unavailable declaration here!"); // If this was defined using CF_OPTIONS, etc. then ignore the diagnostic. @@ -210,7 +213,7 @@ static bool ShouldDiagnoseAvailabilityInContext( AA->getEffectiveEnvironment() == DeclEnv) return true; } else if (K == AR_Deprecated) { - if (C->isDeprecated()) + if (!InAttrArg && C->isDeprecated()) return true; // Don't emit deprecated warnings when defining special member functions. if (const auto *FD = dyn_cast<FunctionDecl>(C); FD && FD->isDefaulted()) @@ -227,7 +230,7 @@ static bool ShouldDiagnoseAvailabilityInContext( } } - if (C->isUnavailable()) + if (!InAttrArg && C->isUnavailable()) return true; return false; }; @@ -408,14 +411,14 @@ createAttributeInsertion(const NamedDecl *D, const SourceManager &SM, /// may not be the same as ReferringDecl, i.e. if an EnumDecl is annotated and /// we refer to a member EnumConstantDecl, ReferringDecl is the EnumConstantDecl /// and OffendingDecl is the EnumDecl. -static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K, - Decl *Ctx, const NamedDecl *ReferringDecl, +static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K, Decl *Ctx, + const NamedDecl *ReferringDecl, const NamedDecl *OffendingDecl, StringRef Message, ArrayRef<SourceLocation> Locs, const ObjCInterfaceDecl *UnknownObjCClass, const ObjCPropertyDecl *ObjCProperty, - bool ObjCPropertyAccess) { + bool ObjCPropertyAccess, bool InAttrArg) { // Diagnostics for deprecated or unavailable. unsigned diag, diag_message, diag_fwdclass_message; unsigned diag_available_here = diag::note_availability_specified_here; @@ -436,7 +439,7 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K, } if (!ShouldDiagnoseAvailabilityInContext(S, K, DeclVersion, IIEnv, Ctx, - OffendingDecl)) + OffendingDecl, InAttrArg)) return; SourceLocation Loc = Locs.front(); @@ -712,7 +715,7 @@ void Sema::handleDelayedAvailabilityCheck(DelayedDiagnostic &DD, Decl *Ctx) { *this, DD.getAvailabilityResult(), Ctx, DD.getAvailabilityReferringDecl(), DD.getAvailabilityOffendingDecl(), DD.getAvailabilityMessage(), DD.getAvailabilitySelectorLocs(), DD.getUnknownObjCClass(), - DD.getObjCProperty(), false); + DD.getObjCProperty(), false, DD.getAvailabilityInAttrArg()); } static void EmitAvailabilityWarning(Sema &S, AvailabilityResult AR, @@ -723,19 +726,19 @@ static void EmitAvailabilityWarning(Sema &S, AvailabilityResult AR, const ObjCInterfaceDecl *UnknownObjCClass, const ObjCPropertyDecl *ObjCProperty, bool ObjCPropertyAccess) { + bool InAttrArg = S.isInsideAttrContext(); // Delay if we're currently parsing a declaration. if (S.DelayedDiagnostics.shouldDelayDiagnostics()) { - S.DelayedDiagnostics.add( - DelayedDiagnostic::makeAvailability( - AR, Locs, ReferringDecl, OffendingDecl, UnknownObjCClass, - ObjCProperty, Message, ObjCPropertyAccess)); + S.DelayedDiagnostics.add(DelayedDiagnostic::makeAvailability( + AR, Locs, ReferringDecl, OffendingDecl, UnknownObjCClass, ObjCProperty, + Message, ObjCPropertyAccess, InAttrArg)); return; } Decl *Ctx = cast<Decl>(S.getCurLexicalContext()); - DoEmitAvailabilityWarning(S, AR, Ctx, ReferringDecl, OffendingDecl, - Message, Locs, UnknownObjCClass, ObjCProperty, - ObjCPropertyAccess); + DoEmitAvailabilityWarning(S, AR, Ctx, ReferringDecl, OffendingDecl, Message, + Locs, UnknownObjCClass, ObjCProperty, + ObjCPropertyAccess, InAttrArg); } namespace { @@ -905,7 +908,8 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability( // emit a diagnostic. if (!ShouldDiagnoseAvailabilityInContext(SemaRef, Result, Introduced, AA->getEffectiveEnvironment(), Ctx, - OffendingDecl)) + OffendingDecl, + /*InAttrArg=*/false)) return; const TargetInfo &TI = SemaRef.getASTContext().getTargetInfo(); diff --git a/clang/test/SemaCXX/attr-deprecated.cpp b/clang/test/SemaCXX/attr-deprecated.cpp index 0286cb0cfc09a..19f1ce7e531ee 100644 --- a/clang/test/SemaCXX/attr-deprecated.cpp +++ b/clang/test/SemaCXX/attr-deprecated.cpp @@ -266,3 +266,30 @@ template <typename T> struct D : T { }; D<A> da; // expected-note {{in instantiation of template class}} } // namespace test8 + +namespace test9 { +__attribute__((deprecated)) const char check = 1; // #TEST9_CHECK + +#define DIAGNOSE_IF(Expr) \ + __attribute__((diagnose_if(Expr, "", "warning"))) __attribute__((deprecated)) + +// expected-note@#TEST9_CHECK {{'check' has been explicitly marked deprecated here}} +// expected-warning@+1 {{'check' is deprecated}} +DIAGNOSE_IF(check != 1) void old_func(); + +namespace inner { +// expected-note@#TEST9_CHECK {{'check' has been explicitly marked deprecated here}} +// expected-warning@+1 {{'check' is deprecated}} +DIAGNOSE_IF(check != 1) void old_inner_func(); +} // namespace inner + +struct S { + // expected-note@#TEST9_CHECK {{'check' has been explicitly marked deprecated here}} + // expected-warning@+1 {{'check' is deprecated}} + DIAGNOSE_IF(check != 1) void old_member(); +}; + +// expected-note@#TEST9_CHECK {{'check' has been explicitly marked deprecated here}} +// expected-warning@+1 {{'check' is deprecated}} +template <typename T> DIAGNOSE_IF(check != 1) void old_tmpl(); +} // namespace test9 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
