[clang] [clang][Sema] Don't warn for implicit uses of builtins in system headers (PR #138205)
Nick Sarnie via cfe-commits
cfe-commits at lists.llvm.org
Fri May 16 14:20:33 PDT 2025
https://github.com/sarnex updated https://github.com/llvm/llvm-project/pull/138205
>From c66ec11d8170a0e4c0b2fc50bdae039fd9c208fb Mon Sep 17 00:00:00 2001
From: "Sarnie, Nick" <nick.sarnie at intel.com>
Date: Thu, 1 May 2025 14:47:45 -0700
Subject: [PATCH 1/2] [clang][Sema] Don't warn for implicit uses of builtins in
system headers
Signed-off-by: Sarnie, Nick <nick.sarnie at intel.com>
---
clang/lib/Sema/SemaDecl.cpp | 7 ++++++-
clang/test/Sema/Inputs/builtin-system-header.h | 1 +
clang/test/Sema/builtin-system-header.c | 8 ++++++++
3 files changed, 15 insertions(+), 1 deletion(-)
create mode 100644 clang/test/Sema/Inputs/builtin-system-header.h
create mode 100644 clang/test/Sema/builtin-system-header.c
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index a3285e8f6f5a2..37008f9eb3235 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -2376,9 +2376,14 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
return nullptr;
}
+ // Warn for implicit uses of header dependent libraries,
+ // except in system headers.
if (!ForRedeclaration &&
(Context.BuiltinInfo.isPredefinedLibFunction(ID) ||
- Context.BuiltinInfo.isHeaderDependentFunction(ID))) {
+ Context.BuiltinInfo.isHeaderDependentFunction(ID)) &&
+ (!getDiagnostics().getSuppressSystemWarnings() ||
+ !Context.getSourceManager().isInSystemHeader(
+ Context.getSourceManager().getSpellingLoc(Loc)))) {
Diag(Loc, LangOpts.C99 ? diag::ext_implicit_lib_function_decl_c99
: diag::ext_implicit_lib_function_decl)
<< Context.BuiltinInfo.getName(ID) << R;
diff --git a/clang/test/Sema/Inputs/builtin-system-header.h b/clang/test/Sema/Inputs/builtin-system-header.h
new file mode 100644
index 0000000000000..ebd5655e6f8ef
--- /dev/null
+++ b/clang/test/Sema/Inputs/builtin-system-header.h
@@ -0,0 +1 @@
+#define MACRO(x,y) _InterlockedOr64(x,y);
diff --git a/clang/test/Sema/builtin-system-header.c b/clang/test/Sema/builtin-system-header.c
new file mode 100644
index 0000000000000..83c3c15e314a7
--- /dev/null
+++ b/clang/test/Sema/builtin-system-header.c
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify -triple arm64-windows -isystem %S/Inputs %s
+
+// expected-no-diagnostics
+#include <builtin-system-header.h>
+
+void foo() {
+ MACRO(0,0);
+}
>From 36e8a8632e21604b42e3e87168edd648572cfc89 Mon Sep 17 00:00:00 2001
From: "Sarnie, Nick" <nick.sarnie at intel.com>
Date: Fri, 16 May 2025 12:58:34 -0700
Subject: [PATCH 2/2] rework change to rely on pragma intrinsic
Signed-off-by: Sarnie, Nick <nick.sarnie at intel.com>
---
clang/include/clang/Sema/Sema.h | 10 +++++++
clang/lib/Parse/ParsePragma.cpp | 13 +++++++--
clang/lib/Sema/SemaDecl.cpp | 28 +++++++++++++------
.../test/Sema/Inputs/builtin-system-header.h | 8 ++++++
clang/test/Sema/builtin-pragma-intrinsic.c | 25 +++++++++++++++++
clang/test/Sema/builtin-system-header.c | 8 ------
6 files changed, 73 insertions(+), 19 deletions(-)
create mode 100644 clang/test/Sema/builtin-pragma-intrinsic.c
delete mode 100644 clang/test/Sema/builtin-system-header.c
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 14f9304b99030..7fc97d78390aa 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -1825,6 +1825,11 @@ class Sema final : public SemaBase {
/// Set of no-builtin functions listed by \#pragma function.
llvm::SmallSetVector<StringRef, 4> MSFunctionNoBuiltins;
+ /// Map of BuiltinIDs to source locations that have #pragma intrinsic calls
+ /// that refer to them.
+ llvm::DenseMap<unsigned, llvm::SmallSetVector<SourceLocation, 4>>
+ PragmaIntrinsicBuiltinIDMap;
+
/// AddAlignmentAttributesForRecord - Adds any needed alignment attributes to
/// a the record decl, to handle '\#pragma pack' and '\#pragma options align'.
void AddAlignmentAttributesForRecord(RecordDecl *RD);
@@ -4345,6 +4350,11 @@ class Sema final : public SemaBase {
/// contain non-field names.
Scope *getNonFieldDeclScope(Scope *S);
+ // Determine if the given builtin usage at the given source location
+ // was previously specified in a #pragma intrinsic.
+ bool isBuiltinSpecifiedInPragmaIntrinsic(unsigned BuiltinID,
+ SourceLocation UsageLoc) const;
+
FunctionDecl *CreateBuiltin(IdentifierInfo *II, QualType Type, unsigned ID,
SourceLocation Loc);
diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp
index 9f9e4bb92af8c..c465dc1449ce8 100644
--- a/clang/lib/Parse/ParsePragma.cpp
+++ b/clang/lib/Parse/ParsePragma.cpp
@@ -301,9 +301,13 @@ struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler {
};
struct PragmaMSIntrinsicHandler : public PragmaHandler {
- PragmaMSIntrinsicHandler() : PragmaHandler("intrinsic") {}
+ PragmaMSIntrinsicHandler(Sema &Actions)
+ : PragmaHandler("intrinsic"), Actions(Actions) {}
void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Token &FirstToken) override;
+
+private:
+ Sema &Actions;
};
// "\#pragma fenv_access (on)".
@@ -517,7 +521,7 @@ void Parser::initializePragmaHandlers() {
PP.AddPragmaHandler(MSOptimize.get());
MSRuntimeChecks = std::make_unique<PragmaMSRuntimeChecksHandler>();
PP.AddPragmaHandler(MSRuntimeChecks.get());
- MSIntrinsic = std::make_unique<PragmaMSIntrinsicHandler>();
+ MSIntrinsic = std::make_unique<PragmaMSIntrinsicHandler>(Actions);
PP.AddPragmaHandler(MSIntrinsic.get());
MSFenvAccess = std::make_unique<PragmaMSFenvAccessHandler>();
PP.AddPragmaHandler(MSFenvAccess.get());
@@ -3803,7 +3807,10 @@ void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP,
if (!II->getBuiltinID())
PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
<< II << SuggestIntrinH;
-
+ /// Store the location at which the builtin was used in a #pragma intrinsic
+ /// so we don't emit a missing header warning later.
+ Actions.PragmaIntrinsicBuiltinIDMap[II->getBuiltinID()].insert(
+ Tok.getLocation());
PP.Lex(Tok);
if (Tok.isNot(tok::comma))
break;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 37008f9eb3235..48b89663069c5 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -2299,6 +2299,21 @@ static StringRef getHeaderName(Builtin::Context &BuiltinInfo, unsigned ID,
llvm_unreachable("unhandled error kind");
}
+bool Sema::isBuiltinSpecifiedInPragmaIntrinsic(unsigned BuiltinID,
+ SourceLocation UsageLoc) const {
+ assert(Context.BuiltinInfo(BuiltinID) && "Invalid builtin id");
+ assert(UsageLoc.isValid() && "Invalid source location");
+ auto It = PragmaIntrinsicBuiltinIDMap.find(BuiltinID);
+ if (It == PragmaIntrinsicBuiltinIDMap.end())
+ return false;
+ for (const SourceLocation &PragmaIntrinLoc : It->second) {
+ if (Context.getSourceManager().isBeforeInTranslationUnit(PragmaIntrinLoc,
+ UsageLoc))
+ return true;
+ }
+ return false;
+}
+
FunctionDecl *Sema::CreateBuiltin(IdentifierInfo *II, QualType Type,
unsigned ID, SourceLocation Loc) {
DeclContext *Parent = Context.getTranslationUnitDecl();
@@ -2370,20 +2385,17 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
// Generally, we emit a warning that the declaration requires the
// appropriate header.
- Diag(Loc, diag::warn_implicit_decl_requires_sysheader)
- << getHeaderName(Context.BuiltinInfo, ID, Error)
- << Context.BuiltinInfo.getName(ID);
+ if (!isBuiltinSpecifiedInPragmaIntrinsic(ID, Loc))
+ Diag(Loc, diag::warn_implicit_decl_requires_sysheader)
+ << getHeaderName(Context.BuiltinInfo, ID, Error)
+ << Context.BuiltinInfo.getName(ID);
return nullptr;
}
- // Warn for implicit uses of header dependent libraries,
- // except in system headers.
if (!ForRedeclaration &&
(Context.BuiltinInfo.isPredefinedLibFunction(ID) ||
Context.BuiltinInfo.isHeaderDependentFunction(ID)) &&
- (!getDiagnostics().getSuppressSystemWarnings() ||
- !Context.getSourceManager().isInSystemHeader(
- Context.getSourceManager().getSpellingLoc(Loc)))) {
+ !isBuiltinSpecifiedInPragmaIntrinsic(ID, Loc)) {
Diag(Loc, LangOpts.C99 ? diag::ext_implicit_lib_function_decl_c99
: diag::ext_implicit_lib_function_decl)
<< Context.BuiltinInfo.getName(ID) << R;
diff --git a/clang/test/Sema/Inputs/builtin-system-header.h b/clang/test/Sema/Inputs/builtin-system-header.h
index ebd5655e6f8ef..7eeb8d811fcfa 100644
--- a/clang/test/Sema/Inputs/builtin-system-header.h
+++ b/clang/test/Sema/Inputs/builtin-system-header.h
@@ -1 +1,9 @@
+#ifdef USE_PRAGMA_BEFORE
+#pragma intrinsic(_InterlockedOr64)
+#endif
+
#define MACRO(x,y) _InterlockedOr64(x,y);
+
+#ifdef USE_PRAGMA_AFTER
+#pragma intrinsic(_InterlockedOr64)
+#endif
diff --git a/clang/test/Sema/builtin-pragma-intrinsic.c b/clang/test/Sema/builtin-pragma-intrinsic.c
new file mode 100644
index 0000000000000..1e8507bfd37df
--- /dev/null
+++ b/clang/test/Sema/builtin-pragma-intrinsic.c
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify -triple arm64-windows -isystem %S/Inputs %s -DUSE_PRAGMA_BEFORE
+// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify -triple arm64-windows -isystem %S/Inputs %s -DUSE_PRAGMA_AFTER
+// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify -triple arm64-windows -isystem %S/Inputs %s -DUSE_PRAGMA_AFTER_USE
+// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify -triple arm64-windows -isystem %S/Inputs %s -DUSE_PRAGMA_SAME_FILE
+// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify -triple arm64-windows -isystem %S/Inputs %s
+
+#if defined(USE_PRAGMA_BEFORE) || defined(USE_PRAGMA_AFTER) || defined(USE_PRAGMA_SAME_FILE)
+// expected-no-diagnostics
+#else
+// expected-error at +10 {{call to undeclared library function '_InterlockedOr64'}}
+// expected-note at +9 {{include the header <intrin.h> or explicitly provide a declaration for '_InterlockedOr64'}}
+#endif
+#include <builtin-system-header.h>
+
+#ifdef USE_PRAGMA_SAME_FILE
+#pragma intrinsic(_InterlockedOr64)
+#endif
+
+void foo() {
+ MACRO(0,0);
+}
+
+#ifdef USE_PRAGMA_AFTER_USE
+#pragma intrinsic(_InterlockedOr64)
+#endif
diff --git a/clang/test/Sema/builtin-system-header.c b/clang/test/Sema/builtin-system-header.c
deleted file mode 100644
index 83c3c15e314a7..0000000000000
--- a/clang/test/Sema/builtin-system-header.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify -triple arm64-windows -isystem %S/Inputs %s
-
-// expected-no-diagnostics
-#include <builtin-system-header.h>
-
-void foo() {
- MACRO(0,0);
-}
More information about the cfe-commits
mailing list