]> granicus.if.org Git - clang/commitdiff
Add PragmaHandler for MSVC pragma execution_character_set
authorReid Kleckner <rnk@google.com>
Thu, 14 Mar 2019 18:12:17 +0000 (18:12 +0000)
committerReid Kleckner <rnk@google.com>
Thu, 14 Mar 2019 18:12:17 +0000 (18:12 +0000)
__pragma(execution_character_set(push, "UTF-8")) is used in
TraceLoggingProvider.h. This commit implements a no-op handler for
compatability, similar to how the flag -fexec_charset is handled.

Patch by Matt Gardner!

Differential Revision: https://reviews.llvm.org/D58530

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@356185 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticLexKinds.td
include/clang/Lex/PPCallbacks.h
lib/Frontend/PrintPreprocessedOutput.cpp
lib/Lex/Pragma.cpp
test/Preprocessor/pragma_microsoft.c

index da73e62c9d2e8fa5a2052b7bfcfa0ed99e190e01..45e50c9a8cdba182978fd2bf92ed30b3255dca38 100644 (file)
@@ -506,6 +506,17 @@ def warn_pragma_warning_expected_number :
   ExtWarn<"#pragma warning expected a warning number">,
   InGroup<UnknownPragmas>;
 
+// - #pragma execution_character_set(...)
+def warn_pragma_exec_charset_expected :
+  ExtWarn<"#pragma execution_character_set expected '%0'">,
+  InGroup<UnknownPragmas>;
+def warn_pragma_exec_charset_spec_invalid :
+  ExtWarn<"#pragma execution_character_set expected 'push' or 'pop'">,
+  InGroup<UnknownPragmas>;
+def warn_pragma_exec_charset_push_invalid :
+   ExtWarn<"#pragma execution_character_set invalid value '%0', only 'UTF-8' is supported">,
+   InGroup<UnknownPragmas>;
+
 def err__Pragma_malformed : Error<
   "_Pragma takes a parenthesized string literal">;
 def err_pragma_message_malformed : Error<
index 92943bdd0145cf3807c55ddc030567d25c325917..33f3c804db4320c4cee53002933c0e0d9e0f8d52 100644 (file)
@@ -239,6 +239,14 @@ public:
   virtual void PragmaWarningPop(SourceLocation Loc) {
   }
 
+  /// Callback invoked when a \#pragma execution_character_set(push) directive
+  /// is read.
+  virtual void PragmaExecCharsetPush(SourceLocation Loc, StringRef Str) {}
+
+  /// Callback invoked when a \#pragma execution_character_set(pop) directive
+  /// is read.
+  virtual void PragmaExecCharsetPop(SourceLocation Loc) {}
+
   /// Callback invoked when a \#pragma clang assume_nonnull begin directive
   /// is read.
   virtual void PragmaAssumeNonNullBegin(SourceLocation Loc) {}
@@ -477,6 +485,16 @@ public:
     Second->PragmaWarningPop(Loc);
   }
 
+  void PragmaExecCharsetPush(SourceLocation Loc, StringRef Str) override {
+    First->PragmaExecCharsetPush(Loc, Str);
+    Second->PragmaExecCharsetPush(Loc, Str);
+  }
+
+  void PragmaExecCharsetPop(SourceLocation Loc) override {
+    First->PragmaExecCharsetPop(Loc);
+    Second->PragmaExecCharsetPop(Loc);
+  }
+
   void PragmaAssumeNonNullBegin(SourceLocation Loc) override {
     First->PragmaAssumeNonNullBegin(Loc);
     Second->PragmaAssumeNonNullBegin(Loc);
index 490830c52415eecd26c2ef8ee5f3760cd679645f..e8162ec95f6f88ef1e5f9ff10875ea6708141d0b 100644 (file)
@@ -143,6 +143,8 @@ public:
                      ArrayRef<int> Ids) override;
   void PragmaWarningPush(SourceLocation Loc, int Level) override;
   void PragmaWarningPop(SourceLocation Loc) override;
+  void PragmaExecCharsetPush(SourceLocation Loc, StringRef Str) override;
+  void PragmaExecCharsetPop(SourceLocation Loc) override;
   void PragmaAssumeNonNullBegin(SourceLocation Loc) override;
   void PragmaAssumeNonNullEnd(SourceLocation Loc) override;
 
@@ -553,6 +555,24 @@ void PrintPPOutputPPCallbacks::PragmaWarningPop(SourceLocation Loc) {
   setEmittedDirectiveOnThisLine();
 }
 
+void PrintPPOutputPPCallbacks::PragmaExecCharsetPush(SourceLocation Loc,
+                                                     StringRef Str) {
+  startNewLineIfNeeded();
+  MoveToLine(Loc);
+  OS << "#pragma character_execution_set(push";
+  if (!Str.empty())
+    OS << ", " << Str;
+  OS << ')';
+  setEmittedDirectiveOnThisLine();
+}
+
+void PrintPPOutputPPCallbacks::PragmaExecCharsetPop(SourceLocation Loc) {
+  startNewLineIfNeeded();
+  MoveToLine(Loc);
+  OS << "#pragma character_execution_set(pop)";
+  setEmittedDirectiveOnThisLine();
+}
+
 void PrintPPOutputPPCallbacks::
 PragmaAssumeNonNullBegin(SourceLocation Loc) {
   startNewLineIfNeeded();
index c82b53173721b3303ea28ac3bdbe78ebdc45b7e8..5564c0c40a09c38b7177da3dbb1a07daa93fb05d 100644 (file)
@@ -1368,6 +1368,70 @@ struct PragmaWarningHandler : public PragmaHandler {
   }
 };
 
+/// "\#pragma execution_character_set(...)". MSVC supports this pragma only
+/// for "UTF-8". We parse it and ignore it if UTF-8 is provided and warn
+/// otherwise to avoid -Wunknown-pragma warnings.
+struct PragmaExecCharsetHandler : public PragmaHandler {
+  PragmaExecCharsetHandler() : PragmaHandler("execution_character_set") {}
+
+  void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+                    Token &Tok) override {
+    // Parse things like:
+    // execution_character_set(push, "UTF-8")
+    // execution_character_set(pop)
+    SourceLocation DiagLoc = Tok.getLocation();
+    PPCallbacks *Callbacks = PP.getPPCallbacks();
+
+    PP.Lex(Tok);
+    if (Tok.isNot(tok::l_paren)) {
+      PP.Diag(Tok, diag::warn_pragma_exec_charset_expected) << "(";
+      return;
+    }
+
+    PP.Lex(Tok);
+    IdentifierInfo *II = Tok.getIdentifierInfo();
+
+    if (II && II->isStr("push")) {
+      // #pragma execution_character_set( push[ , string ] )
+      PP.Lex(Tok);
+      if (Tok.is(tok::comma)) {
+        PP.Lex(Tok);
+
+        std::string ExecCharset;
+        if (!PP.FinishLexStringLiteral(Tok, ExecCharset,
+                                       "pragma execution_character_set",
+                                       /*MacroExpansion=*/false))
+          return;
+
+        // MSVC supports either of these, but nothing else.
+        if (ExecCharset != "UTF-8" && ExecCharset != "utf-8") {
+          PP.Diag(Tok, diag::warn_pragma_exec_charset_push_invalid) << ExecCharset;
+          return;
+        }
+      }
+      if (Callbacks)
+        Callbacks->PragmaExecCharsetPush(DiagLoc, "UTF-8");
+    } else if (II && II->isStr("pop")) {
+      // #pragma execution_character_set( pop )
+      PP.Lex(Tok);
+      if (Callbacks)
+        Callbacks->PragmaExecCharsetPop(DiagLoc);
+    } else {
+      PP.Diag(Tok, diag::warn_pragma_exec_charset_spec_invalid);
+      return;
+    }
+
+    if (Tok.isNot(tok::r_paren)) {
+      PP.Diag(Tok, diag::warn_pragma_exec_charset_expected) << ")";
+      return;
+    }
+
+    PP.Lex(Tok);
+    if (Tok.isNot(tok::eod))
+      PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma execution_character_set";
+  }
+};
+
 /// PragmaIncludeAliasHandler - "\#pragma include_alias("...")".
 struct PragmaIncludeAliasHandler : public PragmaHandler {
   PragmaIncludeAliasHandler() : PragmaHandler("include_alias") {}
@@ -1823,6 +1887,7 @@ void Preprocessor::RegisterBuiltinPragmas() {
   // MS extensions.
   if (LangOpts.MicrosoftExt) {
     AddPragmaHandler(new PragmaWarningHandler());
+    AddPragmaHandler(new PragmaExecCharsetHandler());
     AddPragmaHandler(new PragmaIncludeAliasHandler());
     AddPragmaHandler(new PragmaHdrstopHandler());
   }
index 4105e41af44bb335b428155c0c341b5021a2f6b0..0e1f1dbd1c32a418be0305c917212478ac90e5e7 100644 (file)
@@ -198,3 +198,21 @@ void g() {}
 #pragma optimize("g",     // expected-warning{{missing argument to '#pragma optimize'; expected 'on' or 'off'}}
 #pragma optimize("g",xyz  // expected-warning{{unexpected argument 'xyz' to '#pragma optimize'; expected 'on' or 'off'}}
 #pragma optimize("g",on)  // expected-warning{{#pragma optimize' is not supported}}
+
+#pragma execution_character_set                 // expected-warning {{expected '('}}
+#pragma execution_character_set(                // expected-warning {{expected 'push' or 'pop'}}
+#pragma execution_character_set()               // expected-warning {{expected 'push' or 'pop'}}
+#pragma execution_character_set(asdf            // expected-warning {{expected 'push' or 'pop'}}
+#pragma execution_character_set(asdf)           // expected-warning {{expected 'push' or 'pop'}}
+#pragma execution_character_set(push            // expected-warning {{expected ')'}}
+#pragma execution_character_set(pop,)           // expected-warning {{expected ')'}}
+#pragma execution_character_set(pop,"asdf")     // expected-warning {{expected ')'}}
+#pragma execution_character_set(push,           // expected-error {{expected string literal}}
+#pragma execution_character_set(push,)          // expected-error {{expected string literal}}
+#pragma execution_character_set(push,asdf)      // expected-error {{expected string literal}}
+#pragma execution_character_set(push, "asdf")   // expected-warning {{only 'UTF-8' is supported}}
+
+#pragma execution_character_set(push)
+#pragma execution_character_set(push, "utf-8")
+#pragma execution_character_set(push, "UTF-8")
+#pragma execution_character_set(pop)
\ No newline at end of file