summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2016-09-07 16:38:32 +0000
committerReid Kleckner <rnk@google.com>2016-09-07 16:38:32 +0000
commit3f1ec62a8397062b27f2f849ace22e7c97b248f4 (patch)
treeef80dd543d21b42464ea1d0772b9330583b59f77 /clang
parentcd637012453bf35c9aacf7558138f80f13b2d629 (diff)
downloadbcm5719-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.td4
-rw-r--r--clang/include/clang/Basic/IdentifierTable.h3
-rw-r--r--clang/include/clang/Parse/Parser.h1
-rw-r--r--clang/lib/Parse/ParsePragma.cpp60
-rw-r--r--clang/test/Preprocessor/pragma_microsoft.c16
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>}}
OpenPOWER on IntegriCloud