Add support for '-fgnu-keywords' and '-fasm' to Clang's driver. They are not
implemented precisely the same as GCC, but the distinction GCC makes isn't
useful to represent. This allows parsing code which uses GCC-specific keywords
('asm', etc.) without parsing in a fully GNU mode.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101667 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index cb227b7..932481f 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -473,6 +473,10 @@
   //   BCPLComment, C99, CPlusPlus0x, Digraphs, GNUInline, ImplicitInt, GNUMode
   if (Opts.DollarIdents)
     Res.push_back("-fdollars-in-identifiers");
+  if (Opts.GNUMode && !Opts.GNUKeywords)
+    Res.push_back("-fno-gnu-keywords");
+  if (!Opts.GNUMode && Opts.GNUKeywords)
+    Res.push_back("-fgnu-keywords");
   if (Opts.Microsoft)
     Res.push_back("-fms-extensions");
   if (Opts.ObjCNonFragileABI)
@@ -1151,6 +1155,14 @@
   // OpenCL and C++ both have bool, true, false keywords.
   Opts.Bool = Opts.OpenCL || Opts.CPlusPlus;
 
+  // We abuse '-f[no-]gnu-keywords' to force overriding all GNU-extension
+  // keywords. This behavior is provided by GCC's poorly named '-fasm' flag,
+  // while a subset (the non-C++ GNU keywords) is provided by GCC's
+  // '-fgnu-keywords'. Clang conflates the two for simplicity under the single
+  // name, as it doesn't seem a useful distinction.
+  Opts.GNUKeywords = Args.hasFlag(OPT_fgnu_keywords, OPT_fno_gnu_keywords,
+                                  Opts.GNUMode);
+
   if (Opts.CPlusPlus)
     Opts.CXXOperatorNames = !Args.hasArg(OPT_fno_operator_names);
 
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 578c047..bed9403 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -62,6 +62,7 @@
   PARSE_LANGOPT_BENIGN(DollarIdents);
   PARSE_LANGOPT_BENIGN(AsmPreprocessor);
   PARSE_LANGOPT_IMPORTANT(GNUMode, diag::warn_pch_gnu_extensions);
+  PARSE_LANGOPT_IMPORTANT(GNUKeywords, diag::warn_pch_gnu_keywords);
   PARSE_LANGOPT_BENIGN(ImplicitInt);
   PARSE_LANGOPT_BENIGN(Digraphs);
   PARSE_LANGOPT_BENIGN(HexFloats);
@@ -1885,6 +1886,7 @@
     PARSE_LANGOPT(DollarIdents);
     PARSE_LANGOPT(AsmPreprocessor);
     PARSE_LANGOPT(GNUMode);
+    PARSE_LANGOPT(GNUKeywords);
     PARSE_LANGOPT(ImplicitInt);
     PARSE_LANGOPT(Digraphs);
     PARSE_LANGOPT(HexFloats);
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index 4dd8dc3..a6faf9b 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -745,6 +745,7 @@
   Record.push_back(LangOpts.DollarIdents);  // '$' allowed in identifiers.
   Record.push_back(LangOpts.AsmPreprocessor);  // Preprocessor in asm mode.
   Record.push_back(LangOpts.GNUMode);  // True in gnu99 mode false in c99 mode (etc)
+  Record.push_back(LangOpts.GNUKeywords);  // Allow GNU-extension keywords
   Record.push_back(LangOpts.ImplicitInt);  // C89 implicit 'int'.
   Record.push_back(LangOpts.Digraphs);  // C94, C99 and C++
   Record.push_back(LangOpts.HexFloats);  // C99 Hexadecimal float constants.