Adding -fshort-wchar option.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86167 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td
index ae8b923..a3d7906 100644
--- a/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -162,6 +162,9 @@
 def warn_pch_char_signed : Error<
     "char was %select{unsigned|signed}0 in the PCH file but "
     "is currently %select{unsigned|signed}1">;
+def warn_pch_short_wchar : Error<
+    "-fshort-wchar was %select{disabled|enabled}0 in the PCH file but "
+    "is currently %select{disabled|enabled}1">;
 
 def err_not_a_pch_file : Error<
     "'%0' does not appear to be a precompiled header file">, DefaultFatal;
diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h
index d4d3fe5..a63edd5 100644
--- a/include/clang/Basic/LangOptions.h
+++ b/include/clang/Basic/LangOptions.h
@@ -83,6 +83,7 @@
   unsigned AccessControl     : 1; // Whether C++ access control should
                                   // be enabled.
   unsigned CharIsSigned      : 1; // Whether char is a signed or unsigned type
+  unsigned ShortWChar        : 1; // Force wchar_t to be unsigned short int.
 
   unsigned OpenCL            : 1; // OpenCL C99 language extensions.
 
@@ -159,6 +160,7 @@
     NoInline = 0;
 
     CharIsSigned = 1;
+	ShortWChar = 0;
 
     MainFileName = 0;
   }
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index e61ef92..23c7532 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -346,6 +346,11 @@
   /// options.
   virtual void getDefaultLangOptions(LangOptions &Opts) {}
 
+  /// setForcedLangOptions - Set forced language options.
+  /// Apply changes to the target information with respect to certain
+  /// language options which change the target configuration.
+  virtual void setForcedLangOptions(LangOptions &Opts);
+
   /// getDefaultFeatures - Get the default set of target features for
   /// the \args CPU; this should include all legal feature strings on
   /// the target.
diff --git a/include/clang/Driver/Options.def b/include/clang/Driver/Options.def
index 5370114..d47b0e9 100644
--- a/include/clang/Driver/Options.def
+++ b/include/clang/Driver/Options.def
@@ -463,6 +463,7 @@
 OPTION("-fprofile-generate", fprofile_generate, Flag, f_Group, INVALID, "", 0, 0, 0)
 OPTION("-framework", framework, Separate, INVALID, INVALID, "l", 0, 0, 0)
 OPTION("-frtti", frtti, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fshort-wchar", fshort_wchar, Flag, f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fshow-source-location", fshow_source_location, Flag, f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fsigned-bitfields", fsigned_bitfields, Flag, f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fsigned-char", fsigned_char, Flag, f_Group, INVALID, "", 0, 0, 0)
diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp
index 12caf0c..e965b9a 100644
--- a/lib/Basic/TargetInfo.cpp
+++ b/lib/Basic/TargetInfo.cpp
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/LangOptions.h"
 #include "llvm/ADT/APFloat.h"
 #include "llvm/ADT/STLExtras.h"
 #include <cstdlib>
@@ -124,6 +125,15 @@
   };
 }
 
+/// setForcedLangOptions - Set forced language options.
+/// Apply changes to the target information with respect to certain
+/// language options which change the target configuration.
+void TargetInfo::setForcedLangOptions(LangOptions &Opts) {
+	if (Opts.ShortWChar) {
+    WCharType = UnsignedShort;
+    WCharWidth = WCharAlign = 16;
+	}
+}
 
 //===----------------------------------------------------------------------===//
 
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 808c31c..c35ad7c 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -922,6 +922,13 @@
       CmdArgs.push_back("-fsigned-char=0");
   }
 
+  // -fshort-wchar default varies depending on platform; only
+  // pass if specified.
+  if (Arg *A = Args.getLastArg(options::OPT_fshort_wchar)) {
+    if (A->getOption().matches(options::OPT_fshort_wchar))
+      CmdArgs.push_back("-fshort-wchar");
+  }
+
   // -fno-pascal-strings is default, only pass non-default. If the tool chain
   // happened to translate to -mpascal-strings, we want to back translate here.
   //
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 26f426b..a812604 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -104,6 +104,7 @@
   PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline);
   PARSE_LANGOPT_IMPORTANT(AccessControl, diag::warn_pch_access_control);
   PARSE_LANGOPT_IMPORTANT(CharIsSigned, diag::warn_pch_char_signed);
+  PARSE_LANGOPT_IMPORTANT(ShortWChar, diag::warn_pch_short_wchar);
   if ((PPLangOpts.getGCMode() != 0) != (LangOpts.getGCMode() != 0)) {
     Reader.Diag(diag::warn_pch_gc_mode)
       << LangOpts.getGCMode() << PPLangOpts.getGCMode();
@@ -1741,6 +1742,7 @@
     PARSE_LANGOPT(NoInline);
     PARSE_LANGOPT(AccessControl);
     PARSE_LANGOPT(CharIsSigned);
+    PARSE_LANGOPT(ShortWChar);
     LangOpts.setGCMode((LangOptions::GCMode)Record[Idx]);
     ++Idx;
     LangOpts.setVisibilityMode((LangOptions::VisibilityMode)Record[Idx]);
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index de56166..436428b 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -765,6 +765,7 @@
                                             // be enabled.
   Record.push_back(LangOpts.CharIsSigned); // Whether char is a signed or
                                            // unsigned type
+  Record.push_back(LangOpts.ShortWChar);  // force wchar_t to be unsigned short
   Record.push_back(LangOpts.getGCMode());
   Record.push_back(LangOpts.getVisibilityMode());
   Record.push_back(LangOpts.getStackProtectorMode());
diff --git a/test/Driver/clang_f_opts.c b/test/Driver/clang_f_opts.c
index 8266f77..7aecbac 100644
--- a/test/Driver/clang_f_opts.c
+++ b/test/Driver/clang_f_opts.c
@@ -2,10 +2,11 @@
 // RUN: grep -F '"-fblocks"' %t &&
 // RUN: grep -F '"--fmath-errno=1"' %t &&
 // RUN: grep -F '"-fpascal-strings"' %t &&
-// RUN: clang -### -S -x c /dev/null -fblocks -fbuiltin -fmath-errno -fcommon -fpascal-strings -fno-blocks -fno-builtin -fno-math-errno -fno-common -fno-pascal-strings -fno-show-source-location %s 2> %t &&
+// RUN: clang -### -S -x c /dev/null -fblocks -fbuiltin -fmath-errno -fcommon -fpascal-strings -fno-blocks -fno-builtin -fno-math-errno -fno-common -fno-pascal-strings -fno-show-source-location -fshort-wchar %s 2> %t &&
 // RUN: grep -F '"-fblocks=0"' %t &&
 // RUN: grep -F '"-fbuiltin=0"' %t &&
 // RUN: grep -F '"-fno-common"' %t &&
 // RUN: grep -F '"--fmath-errno=0"' %t &&
 // RUN: grep -F '"-fno-show-source-location"' %t &&
+// RUN: grep -F '"-fshort-wchar"' %t &&
 // RUN: true
diff --git a/test/Sema/wchar.c b/test/Sema/wchar.c
index 1637600..bf1996b 100644
--- a/test/Sema/wchar.c
+++ b/test/Sema/wchar.c
@@ -1,12 +1,20 @@
-// RUN: clang-cc %s -fsyntax-only -verify 
+// RUN: clang-cc %s -fsyntax-only -verify &&
+// RUN: clang-cc %s -fsyntax-only -fshort-wchar -verify -DSHORT_WCHAR
+ 
 #include <wchar.h>
-
+ 
+#if defined(_WIN32) || defined(_M_IX86) || defined(__CYGWIN__) \
+ || defined(_M_X64) || defined(SHORT_WCHAR)
+  #define WCHAR_T_TYPE unsigned short
+#else
+  #define WCHAR_T_TYPE int
+#endif
+ 
 int check_wchar_size[sizeof(*L"") == sizeof(wchar_t) ? 1 : -1];
-
+ 
 void foo() {
-  int t1[] = L"x";
+  WCHAR_T_TYPE t1[] = L"x";
   wchar_t tab[] = L"x";
-
-  int t2[] = "x";     // expected-error {{initialization}}
+  WCHAR_T_TYPE t2[] = "x";     // expected-error {{initialization}}
   char t3[] = L"x";   // expected-error {{initialization}}
 }
diff --git a/tools/clang-cc/clang-cc.cpp b/tools/clang-cc/clang-cc.cpp
index 26ba42d..a7e8f51 100644
--- a/tools/clang-cc/clang-cc.cpp
+++ b/tools/clang-cc/clang-cc.cpp
@@ -611,6 +611,10 @@
 CharIsSigned("fsigned-char",
     llvm::cl::desc("Force char to be a signed/unsigned type"));
 
+static llvm::cl::opt<bool>
+ShortWChar("fshort-wchar",
+    llvm::cl::desc("Force wchar_t to be a short unsigned int"));
+
 
 static llvm::cl::opt<bool>
 Trigraphs("trigraphs", llvm::cl::desc("Process trigraph sequences"));
@@ -813,6 +817,8 @@
     Options.Blocks = EnableBlocks;
   if (CharIsSigned.getPosition())
     Options.CharIsSigned = CharIsSigned;
+	if (ShortWChar.getPosition())
+		Options.ShortWChar = ShortWChar;
 
   if (!AllowBuiltins)
     Options.NoBuiltin = 1;
@@ -877,6 +883,8 @@
 
   if (MainFileName.getPosition())
     Options.setMainFileName(MainFileName.c_str());
+
+	Target->setForcedLangOptions(Options);
 }
 
 //===----------------------------------------------------------------------===//