https://github.com/philnik777 updated 
https://github.com/llvm/llvm-project/pull/168041

>From c64e4dbf78300fb0021ddbad976f13237d4b2870 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <[email protected]>
Date: Fri, 14 Nov 2025 11:54:12 +0100
Subject: [PATCH] [Clang] Add #pragma deprecated_header

---
 .../include/clang/Basic/DiagnosticLexKinds.td |  5 +++
 clang/include/clang/Lex/HeaderSearch.h        | 25 +++++++++--
 clang/include/clang/Lex/Preprocessor.h        |  1 +
 clang/lib/Lex/PPDirectives.cpp                |  9 ++++
 clang/lib/Lex/PPLexerChange.cpp               | 12 ++++++
 clang/lib/Lex/Pragma.cpp                      | 41 +++++++++++++++++++
 clang/test/Lexer/deprecated-header-msg.h      |  6 +++
 clang/test/Lexer/deprecated-header.c          | 13 ++++++
 clang/test/Lexer/deprecated-header.h          |  6 +++
 9 files changed, 115 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/Lexer/deprecated-header-msg.h
 create mode 100644 clang/test/Lexer/deprecated-header.c
 create mode 100644 clang/test/Lexer/deprecated-header.h

diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td 
b/clang/include/clang/Basic/DiagnosticLexKinds.td
index 417187222e448..c587a0e861949 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -666,6 +666,11 @@ def warn_pragma_deprecated_macro_use :
   ExtWarn<"macro %0 has been marked as deprecated%select{|: %2}1">,
   InGroup<DeprecatedPragma>;
 
+// - #pragma depcreated_header
+def warn_pragma_deprecated_header : Warning<
+  "header is deprecated%select{|: %1}0">,
+  InGroup<Deprecated>;
+
 // - #pragma clang restrict_expansion(...)
 def warn_pragma_restrict_expansion_macro_use :
   ExtWarn<"macro %0 has been marked as unsafe for use in headers"
diff --git a/clang/include/clang/Lex/HeaderSearch.h 
b/clang/include/clang/Lex/HeaderSearch.h
index 850aea41c4c3b..3a3d5498a2d44 100644
--- a/clang/include/clang/Lex/HeaderSearch.h
+++ b/clang/include/clang/Lex/HeaderSearch.h
@@ -80,6 +80,9 @@ struct HeaderFileInfo {
   LLVM_PREFERRED_TYPE(SrcMgr::CharacteristicKind)
   unsigned DirInfo : 3;
 
+  LLVM_PREFERRED_TYPE(bool)
+  unsigned IsDeprecated : 1;
+
   /// Whether this header file info was supplied by an external source,
   /// and has not changed since.
   LLVM_PREFERRED_TYPE(bool)
@@ -124,9 +127,9 @@ struct HeaderFileInfo {
 
   HeaderFileInfo()
       : IsLocallyIncluded(false), isImport(false), isPragmaOnce(false),
-        DirInfo(SrcMgr::C_User), External(false), isModuleHeader(false),
-        isTextualModuleHeader(false), isCompilingModuleHeader(false),
-        Resolved(false), IsValid(false) {}
+        DirInfo(SrcMgr::C_User), IsDeprecated(false), External(false),
+        isModuleHeader(false), isTextualModuleHeader(false),
+        isCompilingModuleHeader(false), Resolved(false), IsValid(false) {}
 
   /// Retrieve the controlling macro for this header file, if
   /// any.
@@ -356,6 +359,9 @@ class HeaderSearch {
   // A map of discovered headers with their associated include file name.
   llvm::DenseMap<const FileEntry *, llvm::SmallString<64>> IncludeNames;
 
+  // A map from a file to its deprecation message
+  llvm::DenseMap<const FileEntry *, std::string> DeprecationMessages;
+
   /// Uniqued set of framework names, which is used to track which
   /// headers were included as framework headers.
   llvm::StringSet<llvm::BumpPtrAllocator> FrameworkNames;
@@ -563,6 +569,12 @@ class HeaderSearch {
     getFileInfo(File).DirInfo = SrcMgr::C_System;
   }
 
+  void MarkFileDeprecated(FileEntryRef File, std::string DeprecationMessage) {
+    getFileInfo(File).IsDeprecated = true;
+    DeprecationMessages.emplace_or_assign(&File.getFileEntry(),
+                                          std::move(DeprecationMessage));
+  }
+
   /// Mark the specified file as part of a module.
   void MarkFileModuleHeader(FileEntryRef FE, ModuleMap::ModuleHeaderRole Role,
                             bool isCompilingModuleHeader);
@@ -652,6 +664,13 @@ class HeaderSearch {
   std::string getCachedModuleFileName(StringRef ModuleName,
                                       StringRef ModuleMapPath);
 
+  std::optional<std::string_view>
+  getHeaderDeprecationMessage(FileEntryRef File) {
+    if (!getFileInfo(File).IsDeprecated)
+      return std::nullopt;
+    return DeprecationMessages.at(File);
+  }
+
   /// Lookup a module Search for a module with the given name.
   ///
   /// \param ModuleName The name of the module we're looking for.
diff --git a/clang/include/clang/Lex/Preprocessor.h 
b/clang/include/clang/Lex/Preprocessor.h
index b1c648e647f41..3324996c59554 100644
--- a/clang/include/clang/Lex/Preprocessor.h
+++ b/clang/include/clang/Lex/Preprocessor.h
@@ -2943,6 +2943,7 @@ class Preprocessor {
   void HandlePragmaMark(Token &MarkTok);
   void HandlePragmaPoison();
   void HandlePragmaSystemHeader(Token &SysHeaderTok);
+  void HandlePragmaDeprecatedHeader(Token &Tok, std::string 
DeprecationMessage);
   void HandlePragmaDependency(Token &DependencyTok);
   void HandlePragmaPushMacro(Token &Tok);
   void HandlePragmaPopMacro(Token &Tok);
diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp
index 891c8ab7f3155..0ea2b412502c2 100644
--- a/clang/lib/Lex/PPDirectives.cpp
+++ b/clang/lib/Lex/PPDirectives.cpp
@@ -2509,6 +2509,15 @@ Preprocessor::ImportAction 
Preprocessor::HandleHeaderIncludeOrImport(
       Action = TrackGMFState.inGMF() ? Import : Skip;
     else
       Action = (ModuleToImport && !getLangOpts().CompilingPCH) ? Import : Skip;
+
+    // If we're not entering the header, it might have been marked deprecated
+    // the first time it was included.
+    if (auto MaybeMessage = HeaderInfo.getHeaderDeprecationMessage(*File);
+        MaybeMessage) {
+      std::string_view Message = *MaybeMessage;
+      Diag(FilenameTok, diag::warn_pragma_deprecated_header)
+          << !Message.empty() << Message;
+    }
   }
 
   // Check for circular inclusion of the main file.
diff --git a/clang/lib/Lex/PPLexerChange.cpp b/clang/lib/Lex/PPLexerChange.cpp
index b014124153c83..52a19d1a3428a 100644
--- a/clang/lib/Lex/PPLexerChange.cpp
+++ b/clang/lib/Lex/PPLexerChange.cpp
@@ -490,6 +490,18 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool 
isEndOfMacro) {
             SourceMgr.getFileEntryForID(CurPPLexer->getFileID())))
       FoundPCHThroughHeader = true;
 
+    if (CurPPLexer) {
+      if (OptionalFileEntryRef File = CurPPLexer->getFileEntry()) {
+        if (auto MaybeMessage = HeaderInfo.getHeaderDeprecationMessage(*File);
+            MaybeMessage) {
+          std::string_view Message = *MaybeMessage;
+          Diag(SourceMgr.getIncludeLoc(CurPPLexer->getFileID()),
+               diag::warn_pragma_deprecated_header)
+              << !Message.empty() << Message;
+        }
+      }
+    }
+
     // We're done with the #included file.
     RemoveTopOfLexerStack();
 
diff --git a/clang/lib/Lex/Pragma.cpp b/clang/lib/Lex/Pragma.cpp
index bba3c89bed38f..47f0974d3aeef 100644
--- a/clang/lib/Lex/Pragma.cpp
+++ b/clang/lib/Lex/Pragma.cpp
@@ -508,6 +508,13 @@ void Preprocessor::HandlePragmaSystemHeader(Token 
&SysHeaderTok) {
                         SrcMgr::C_System);
 }
 
+void Preprocessor::HandlePragmaDeprecatedHeader(
+    Token &Tok, std::string DeprecationMessage) {
+  PreprocessorLexer *TheLexer = getCurrentFileLexer();
+  HeaderInfo.MarkFileDeprecated(*TheLexer->getFileEntry(),
+                                std::move(DeprecationMessage));
+}
+
 /// HandlePragmaDependency - Handle \#pragma GCC dependency "foo" blah.
 void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
   Token FilenameTok;
@@ -2084,6 +2091,39 @@ struct PragmaDeprecatedHandler : public PragmaHandler {
   }
 };
 
+/// "\#pragma clang deprecated_header"
+struct PragmaDeprecatedHeaderHandler : PragmaHandler {
+  PragmaDeprecatedHeaderHandler() : PragmaHandler("deprecated_header") {}
+
+  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
+                    Token &Tok) override {
+    std::string MessageString;
+
+    PP.Lex(Tok);
+    if (!Tok.is(tok::eod)) {
+      if (!Tok.is(tok::l_paren)) {
+        PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol)
+            << "pragma clang deprecated_header";
+      } else {
+        PP.Lex(Tok);
+        if (PP.FinishLexStringLiteral(Tok, MessageString,
+                                      "#pragma clang deprecated_header",
+                                      /*AllowMacroExpansion=*/true)) {
+          if (Tok.isNot(tok::r_paren)) {
+            PP.Diag(Tok, diag::err_expected) << ")";
+          } else {
+            PP.Lex(Tok);
+            if (!Tok.is(tok::eod))
+              PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol)
+                  << "pragma clang deprecated_header";
+          }
+        }
+      }
+    }
+    PP.HandlePragmaDeprecatedHeader(Tok, MessageString);
+  }
+};
+
 /// "\#pragma clang restrict_expansion(...)"
 ///
 /// The syntax is
@@ -2174,6 +2214,7 @@ void Preprocessor::RegisterBuiltinPragmas() {
   AddPragmaHandler("clang", new PragmaARCCFCodeAuditedHandler());
   AddPragmaHandler("clang", new PragmaAssumeNonNullHandler());
   AddPragmaHandler("clang", new PragmaDeprecatedHandler());
+  AddPragmaHandler("clang", new PragmaDeprecatedHeaderHandler());
   AddPragmaHandler("clang", new PragmaRestrictExpansionHandler());
   AddPragmaHandler("clang", new PragmaFinalHandler());
 
diff --git a/clang/test/Lexer/deprecated-header-msg.h 
b/clang/test/Lexer/deprecated-header-msg.h
new file mode 100644
index 0000000000000..6295affba3f7b
--- /dev/null
+++ b/clang/test/Lexer/deprecated-header-msg.h
@@ -0,0 +1,6 @@
+#ifndef DEPRECATED_HEADER_MSG_H
+#define DEPRECATED_HEADER_MSG_H
+
+#pragma clang deprecated_header("This is a shitty header")
+
+#endif // DEPRECATED_HEADER_MSG_H
diff --git a/clang/test/Lexer/deprecated-header.c 
b/clang/test/Lexer/deprecated-header.c
new file mode 100644
index 0000000000000..caff6b2d09345
--- /dev/null
+++ b/clang/test/Lexer/deprecated-header.c
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -Wdeprecated %s -fsyntax-only -verify -Wunknown-pragmas 
-Wextra-tokens
+
+#pragma clang deprecated_header( // expected-error {{expected string literal 
in #pragma clang deprecated_header}}
+#pragma clang deprecated_header() // expected-error {{expected string literal 
in #pragma clang deprecated_header}}
+#pragma clang deprecated_header("" // expected-error {{expected )}}
+#pragma clang deprecated_header something // expected-warning {{extra tokens 
at end of #pragma clang deprecated_header directive}}
+#pragma clang deprecated_header("") something // expected-warning {{extra 
tokens at end of #pragma clang deprecated_header directive}}
+
+#include "deprecated-header.h" // expected-warning {{header is deprecated}}
+#include "deprecated-header.h" // expected-warning {{header is deprecated}}
+
+#include "deprecated-header-msg.h" // expected-warning {{header is deprecated: 
This is a shitty header}}
+#include "deprecated-header-msg.h" // expected-warning {{header is deprecated: 
This is a shitty header}}
diff --git a/clang/test/Lexer/deprecated-header.h 
b/clang/test/Lexer/deprecated-header.h
new file mode 100644
index 0000000000000..81884b5630b9c
--- /dev/null
+++ b/clang/test/Lexer/deprecated-header.h
@@ -0,0 +1,6 @@
+#ifndef DEPRECATED_HEADER_H
+#define DEPRECATED_HEADER_H
+
+#pragma clang deprecated_header
+
+#endif // DEPRECATED_HEADER_H

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

Reply via email to