diff options
| author | Reid Kleckner <rnk@google.com> | 2016-09-07 16:38:32 +0000 |
|---|---|---|
| committer | Reid Kleckner <rnk@google.com> | 2016-09-07 16:38:32 +0000 |
| commit | 3f1ec62a8397062b27f2f849ace22e7c97b248f4 (patch) | |
| tree | ef80dd543d21b42464ea1d0772b9330583b59f77 /clang | |
| parent | cd637012453bf35c9aacf7558138f80f13b2d629 (diff) | |
| download | bcm5719-llvm-3f1ec62a8397062b27f2f849ace22e7c97b248f4.tar.gz bcm5719-llvm-3f1ec62a8397062b27f2f849ace22e7c97b248f4.zip | |
Parsing MS pragma intrinsic
Parse pragma intrinsic, display warning if the function isn't a builtin
function in clang and suggest including intrin.h.
Patch by Albert Gutowski!
Reviewers: aaron.ballman, rnk
Subscribers: aaron.ballman, cfe-commits
Differential Revision: https://reviews.llvm.org/D23944
llvm-svn: 280825
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticParseKinds.td | 4 | ||||
| -rw-r--r-- | clang/include/clang/Basic/IdentifierTable.h | 3 | ||||
| -rw-r--r-- | clang/include/clang/Parse/Parser.h | 1 | ||||
| -rw-r--r-- | clang/lib/Parse/ParsePragma.cpp | 60 | ||||
| -rw-r--r-- | clang/test/Preprocessor/pragma_microsoft.c | 16 |
5 files changed, 82 insertions, 2 deletions
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 513820727a0..1ee2510196a 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -911,6 +911,10 @@ def warn_pragma_invalid_action : Warning< def warn_pragma_pack_malformed : Warning< "expected integer or identifier in '#pragma pack' - ignored">, InGroup<IgnoredPragmas>; +// - #pragma intrinsic +def warn_pragma_intrinsic_builtin : Warning< + "%0 is not a recognized builtin%select{|; consider including <intrin.h> to access non-builtin intrinsics}1">, + InGroup<IgnoredPragmas>; // - #pragma unused def warn_pragma_unused_expected_var : Warning< "expected '#pragma unused' argument to be a variable name">, diff --git a/clang/include/clang/Basic/IdentifierTable.h b/clang/include/clang/Basic/IdentifierTable.h index fffb50493bf..f9dec7917a1 100644 --- a/clang/include/clang/Basic/IdentifierTable.h +++ b/clang/include/clang/Basic/IdentifierTable.h @@ -205,8 +205,7 @@ public: /// \brief Return a value indicating whether this is a builtin function. /// - /// 0 is not-built-in. 1 is builtin-for-some-nonprimary-target. - /// 2+ are specific builtin functions. + /// 0 is not-built-in. 1+ are specific builtin functions. unsigned getBuiltinID() const { if (ObjCOrBuiltinID >= tok::NUM_OBJC_KEYWORDS) return ObjCOrBuiltinID - tok::NUM_OBJC_KEYWORDS; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index dae0757978a..d5d885f7fdd 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -172,6 +172,7 @@ class Parser : public CodeCompletionHandler { std::unique_ptr<PragmaHandler> MSCodeSeg; std::unique_ptr<PragmaHandler> MSSection; std::unique_ptr<PragmaHandler> MSRuntimeChecks; + std::unique_ptr<PragmaHandler> MSIntrinsic; std::unique_ptr<PragmaHandler> OptimizeHandler; std::unique_ptr<PragmaHandler> LoopHintHandler; std::unique_ptr<PragmaHandler> UnrollHintHandler; diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index bff5d1170fe..7ae03af2b16 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -161,6 +161,12 @@ struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler { PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {} }; +struct PragmaMSIntrinsicHandler : public PragmaHandler { + PragmaMSIntrinsicHandler() : PragmaHandler("intrinsic") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +}; + } // end namespace void Parser::initializePragmaHandlers() { @@ -229,6 +235,8 @@ void Parser::initializePragmaHandlers() { PP.AddPragmaHandler(MSSection.get()); MSRuntimeChecks.reset(new PragmaMSRuntimeChecksHandler()); PP.AddPragmaHandler(MSRuntimeChecks.get()); + MSIntrinsic.reset(new PragmaMSIntrinsicHandler()); + PP.AddPragmaHandler(MSIntrinsic.get()); } OptimizeHandler.reset(new PragmaOptimizeHandler(Actions)); @@ -297,6 +305,8 @@ void Parser::resetPragmaHandlers() { MSSection.reset(); PP.RemovePragmaHandler(MSRuntimeChecks.get()); MSRuntimeChecks.reset(); + PP.RemovePragmaHandler(MSIntrinsic.get()); + MSIntrinsic.reset(); } PP.RemovePragmaHandler("STDC", FPContractHandler.get()); @@ -2127,3 +2137,53 @@ void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP, PP.EnterTokenStream(std::move(TokenArray), 1, /*DisableMacroExpansion=*/false); } + +/// \brief Handle the Microsoft \#pragma intrinsic extension. +/// +/// The syntax is: +/// \code +/// #pragma intrinsic(memset) +/// #pragma intrinsic(strlen, memcpy) +/// \endcode +/// +/// Pragma intrisic tells the compiler to use a builtin version of the +/// function. Clang does it anyway, so the pragma doesn't really do anything. +/// Anyway, we emit a warning if the function specified in \#pragma intrinsic +/// isn't an intrinsic in clang and suggest to include intrin.h. +void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &Tok) { + PP.Lex(Tok); + + if (Tok.isNot(tok::l_paren)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) + << "intrinsic"; + return; + } + PP.Lex(Tok); + + bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H"); + + while (Tok.is(tok::identifier)) { + IdentifierInfo *II = Tok.getIdentifierInfo(); + if (!II->getBuiltinID()) + PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin) + << II << SuggestIntrinH; + + PP.Lex(Tok); + if (Tok.isNot(tok::comma)) + break; + PP.Lex(Tok); + } + + if (Tok.isNot(tok::r_paren)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) + << "intrinsic"; + return; + } + PP.Lex(Tok); + + if (Tok.isNot(tok::eod)) + PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) + << "intrinsic"; +} diff --git a/clang/test/Preprocessor/pragma_microsoft.c b/clang/test/Preprocessor/pragma_microsoft.c index 2a9e7bab35b..31b907a477c 100644 --- a/clang/test/Preprocessor/pragma_microsoft.c +++ b/clang/test/Preprocessor/pragma_microsoft.c @@ -162,3 +162,19 @@ void g() {} // Test that runtime_checks is parsed but ignored. #pragma runtime_checks("sc", restore) // no-warning + +// Test pragma intrinsic +#pragma intrinsic(memset) // no-warning +#pragma intrinsic(memcpy, strlen, strlen) // no-warning +#pragma intrinsic() // no-warning +#pragma intrinsic(asdf) // expected-warning {{'asdf' is not a recognized builtin; consider including <intrin.h>}} +#pragma intrinsic(main) // expected-warning {{'main' is not a recognized builtin; consider including <intrin.h>}} +#pragma intrinsic( // expected-warning {{missing ')' after}} +#pragma intrinsic(int) // expected-warning {{missing ')' after}} +#pragma intrinsic(strcmp) asdf // expected-warning {{extra tokens at end}} + +#define __INTRIN_H // there should be no notes after defining __INTRIN_H +#pragma intrinsic(asdf) // expected-warning-re {{'asdf' is not a recognized builtin{{$}}}} +#pragma intrinsic(memset) // no-warning +#undef __INTRIN_H +#pragma intrinsic(asdf) // expected-warning {{'asdf' is not a recognized builtin; consider including <intrin.h>}} |

