diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index 9f9e4bb92af8c..ec064e441a5f8 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(); PP.AddPragmaHandler(MSRuntimeChecks.get()); - MSIntrinsic = std::make_unique(); + MSIntrinsic = std::make_unique(Actions); PP.AddPragmaHandler(MSIntrinsic.get()); MSFenvAccess = std::make_unique(); PP.AddPragmaHandler(MSFenvAccess.get()); @@ -3803,7 +3807,15 @@ void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP, if (!II->getBuiltinID()) PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin) << II << SuggestIntrinH; - + // 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/test/Sema/Inputs/builtin-system-header.h b/clang/test/Sema/Inputs/builtin-system-header.h new file mode 100644 index 0000000000000..7eeb8d811fcfa --- /dev/null +++ b/clang/test/Sema/Inputs/builtin-system-header.h @@ -0,0 +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 or explicitly provide a declaration for '_InterlockedOr64'}} +#endif +#include + +#ifdef USE_PRAGMA_SAME_FILE +#pragma intrinsic(_InterlockedOr64) +#endif + +void foo() { + MACRO(0,0); +} + +#ifdef USE_PRAGMA_AFTER_USE +#pragma intrinsic(_InterlockedOr64) +#endif