Author: rnk Date: Wed Sep 7 11:38:32 2016 New Revision: 280825 URL: http://llvm.org/viewvc/llvm-project?rev=280825&view=rev Log: 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 Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td cfe/trunk/include/clang/Basic/IdentifierTable.h cfe/trunk/include/clang/Parse/Parser.h cfe/trunk/lib/Parse/ParsePragma.cpp cfe/trunk/test/Preprocessor/pragma_microsoft.c Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=280825&r1=280824&r2=280825&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Wed Sep 7 11:38:32 2016 @@ -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">, Modified: cfe/trunk/include/clang/Basic/IdentifierTable.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/IdentifierTable.h?rev=280825&r1=280824&r2=280825&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/IdentifierTable.h (original) +++ cfe/trunk/include/clang/Basic/IdentifierTable.h Wed Sep 7 11:38:32 2016 @@ -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; Modified: cfe/trunk/include/clang/Parse/Parser.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=280825&r1=280824&r2=280825&view=diff ============================================================================== --- cfe/trunk/include/clang/Parse/Parser.h (original) +++ cfe/trunk/include/clang/Parse/Parser.h Wed Sep 7 11:38:32 2016 @@ -172,6 +172,7 @@ class Parser : public CodeCompletionHand 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; Modified: cfe/trunk/lib/Parse/ParsePragma.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParsePragma.cpp?rev=280825&r1=280824&r2=280825&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParsePragma.cpp (original) +++ cfe/trunk/lib/Parse/ParsePragma.cpp Wed Sep 7 11:38:32 2016 @@ -161,6 +161,12 @@ struct PragmaMSRuntimeChecksHandler : pu 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::HandlePrag 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"; +} Modified: cfe/trunk/test/Preprocessor/pragma_microsoft.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/pragma_microsoft.c?rev=280825&r1=280824&r2=280825&view=diff ============================================================================== --- cfe/trunk/test/Preprocessor/pragma_microsoft.c (original) +++ cfe/trunk/test/Preprocessor/pragma_microsoft.c Wed Sep 7 11:38:32 2016 @@ -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>}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits