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.sar...@intel.com> Date: Thu, 1 May 2025 14:47:45 -0700 Subject: [PATCH 1/3] [clang][Sema] Don't warn for implicit uses of builtins in system headers Signed-off-by: Sarnie, Nick <nick.sar...@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.sar...@intel.com> Date: Fri, 16 May 2025 12:58:34 -0700 Subject: [PATCH 2/3] rework change to rely on pragma intrinsic Signed-off-by: Sarnie, Nick <nick.sar...@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@+10 {{call to undeclared library function '_InterlockedOr64'}} +// expected-note@+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); -} >From 81e57222cce50d137d54d8f7743b5c43fa4a7beb Mon Sep 17 00:00:00 2001 From: "Sarnie, Nick" <nick.sar...@intel.com> Date: Mon, 19 May 2025 11:15:48 -0700 Subject: [PATCH 3/3] declare the builtin if needed Signed-off-by: Sarnie, Nick <nick.sar...@intel.com> --- clang/include/clang/Sema/Sema.h | 10 ---------- clang/lib/Parse/ParsePragma.cpp | 13 +++++++++---- clang/lib/Sema/SemaDecl.cpp | 25 ++++--------------------- 3 files changed, 13 insertions(+), 35 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 7fc97d78390aa..14f9304b99030 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1825,11 +1825,6 @@ 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); @@ -4350,11 +4345,6 @@ 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 c465dc1449ce8..ec064e441a5f8 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -3807,10 +3807,15 @@ 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()); + // If the builtin hasn't already been declared, declare it now. + DeclarationNameInfo NameInfo(II, Tok.getLocation()); + LookupResult Previous(Actions, NameInfo, Sema::LookupOrdinaryName, + Actions.forRedeclarationInCurContext()); + Actions.LookupName(Previous, Actions.getCurScope(), + /*CreateBuiltins*/ false); + if (Previous.empty()) + Actions.LazilyCreateBuiltin(II, II->getBuiltinID(), Actions.getCurScope(), + /*ForRedeclaration*/ true, 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 48b89663069c5..a3285e8f6f5a2 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2299,21 +2299,6 @@ 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(); @@ -2385,17 +2370,15 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, // Generally, we emit a warning that the declaration requires the // appropriate header. - if (!isBuiltinSpecifiedInPragmaIntrinsic(ID, Loc)) - Diag(Loc, diag::warn_implicit_decl_requires_sysheader) - << getHeaderName(Context.BuiltinInfo, ID, Error) - << Context.BuiltinInfo.getName(ID); + Diag(Loc, diag::warn_implicit_decl_requires_sysheader) + << getHeaderName(Context.BuiltinInfo, ID, Error) + << Context.BuiltinInfo.getName(ID); return nullptr; } if (!ForRedeclaration && (Context.BuiltinInfo.isPredefinedLibFunction(ID) || - Context.BuiltinInfo.isHeaderDependentFunction(ID)) && - !isBuiltinSpecifiedInPragmaIntrinsic(ID, Loc)) { + Context.BuiltinInfo.isHeaderDependentFunction(ID))) { Diag(Loc, LangOpts.C99 ? diag::ext_implicit_lib_function_decl_c99 : diag::ext_implicit_lib_function_decl) << Context.BuiltinInfo.getName(ID) << R; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits