r280825 - Parsing MS pragma intrinsic

Reid Kleckner via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 7 09:38:32 PDT 2016


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>}}




More information about the cfe-commits mailing list