]> granicus.if.org Git - clang/commitdiff
Support __wchar_t in -fms-extensions and -fms-compatibility modes.
authorHans Wennborg <hans@hanshq.net>
Fri, 3 May 2013 09:10:16 +0000 (09:10 +0000)
committerHans Wennborg <hans@hanshq.net>
Fri, 3 May 2013 09:10:16 +0000 (09:10 +0000)
MSVC provides __wchar_t, either as an alias for the built-in wchar_t
type, or as a separate type depending on language (C vs C++) and flags
(-fno-wchar).

In -fms-extensions, Clang will simply accept __wchar_t as an alias for
whatever type is used for wide character literals. In -fms-compatibility, we
try to mimic MSVC's behavior by always making __wchar_t a builtin type.

This fixes PR15815.

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

include/clang/AST/PrettyPrinter.h
include/clang/Basic/TokenKinds.def
lib/AST/ASTContext.cpp
lib/AST/Type.cpp
test/Lexer/ms-compatibility-wchar.c [new file with mode: 0644]
test/Lexer/ms-extensions-wchar.c [new file with mode: 0644]

index e3c09e7b418f3930b3dc47e92fe5d3bf527209fb..36e90724d9f5e6af3d2e649fd2ec3654c2c6071c 100644 (file)
@@ -40,7 +40,8 @@ struct PrintingPolicy {
       SuppressUnwrittenScope(false), SuppressInitializers(false),
       ConstantArraySizeAsWritten(false), AnonymousTagLocations(true),
       SuppressStrongLifetime(false), Bool(LO.Bool),
-      TerseOutput(false), PolishForDeclaration(false) { }
+      TerseOutput(false), PolishForDeclaration(false),
+      MSWChar(LO.MicrosoftMode && !LO.WChar) { }
 
   /// \brief What language we're printing.
   LangOptions LangOpts;
@@ -146,6 +147,10 @@ struct PrintingPolicy {
   /// declaration tag; such as, do not print attributes attached to the declaration.
   ///
   unsigned PolishForDeclaration : 1;
+
+  /// \brief When true, print the built-in wchar_t type as __wchar_t. For use in
+  /// Microsoft mode when wchar_t is not available.
+  unsigned MSWChar : 1;
 };
 
 } // end namespace clang
index bcf0f31dcbf6f4b0830a81cbe3082aafd3b0d50b..0dbff81d3423bf631430b6340a1155550c488b99 100644 (file)
@@ -524,6 +524,7 @@ KEYWORD(__interface                   , KEYMS)
 ALIAS("__int8"           , char       , KEYMS)
 ALIAS("__int16"          , short      , KEYMS)
 ALIAS("__int32"          , int        , KEYMS)
+ALIAS("__wchar_t"        , wchar_t    , KEYMS)
 ALIAS("_asm"             , asm        , KEYMS)
 ALIAS("_alignof"         , __alignof  , KEYMS)
 ALIAS("__builtin_alignof", __alignof  , KEYMS)
index 5e9a87c58a7d3c754f8f69d79a51198600eb9761..f4e53e6105856ec61953addd46467f59e473088d 100644 (file)
@@ -897,12 +897,13 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) {
   InitBuiltinType(Int128Ty,            BuiltinType::Int128);
   InitBuiltinType(UnsignedInt128Ty,    BuiltinType::UInt128);
 
-  if (LangOpts.CPlusPlus && LangOpts.WChar) { // C++ 3.9.1p5
+  if ((LangOpts.CPlusPlus && LangOpts.WChar) || LangOpts.MicrosoftMode) {
+    // C++ 3.9.1p5 or -fms-compatibility.
     if (TargetInfo::isTypeSigned(Target.getWCharType()))
       InitBuiltinType(WCharTy,           BuiltinType::WChar_S);
     else  // -fshort-wchar makes wchar_t be unsigned.
       InitBuiltinType(WCharTy,           BuiltinType::WChar_U);
-  } else // C99 (or C++ using -fno-wchar)
+  } else // C99 (or C++ using -fno-wchar) in non-MicrosoftMode.
     WCharTy = getFromTargetType(Target.getWCharType());
 
   WIntTy = getFromTargetType(Target.getWIntType());
index fa16facb634fda7e372a0de9dfad37cf61863b35..a1f0b08494b014857d30f225aa552f2e4f8d10e0 100644 (file)
@@ -1521,7 +1521,7 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
   case Double:            return "double";
   case LongDouble:        return "long double";
   case WChar_S:
-  case WChar_U:           return "wchar_t";
+  case WChar_U:           return Policy.MSWChar ? "__wchar_t" : "wchar_t";
   case Char16:            return "char16_t";
   case Char32:            return "char32_t";
   case NullPtr:           return "nullptr_t";
diff --git a/test/Lexer/ms-compatibility-wchar.c b/test/Lexer/ms-compatibility-wchar.c
new file mode 100644 (file)
index 0000000..966292e
--- /dev/null
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -fms-compatibility -triple i386-pc-win32 %s
+
+// C++ mode with -fno-wchar works the same as C mode for wchar_t.
+// RUN: %clang_cc1 -x c++ -fno-wchar -fsyntax-only -verify -fms-compatibility -triple i386-pc-win32 %s
+
+wchar_t f(); // expected-error{{unknown type name 'wchar_t'}}
+
+// __wchar_t is available as an MS extension.
+__wchar_t g; // expected-note {{previous}}
+
+// __wchar_t is a distinct type, separate from the target's integer type for wide chars.
+unsigned short g; // expected-error {{redefinition of 'g' with a different type: 'unsigned short' vs '__wchar_t'}}
diff --git a/test/Lexer/ms-extensions-wchar.c b/test/Lexer/ms-extensions-wchar.c
new file mode 100644 (file)
index 0000000..9321c3a
--- /dev/null
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions -triple i386-pc-win32 %s
+
+// C++ mode with -fno-wchar works the same as C mode for wchar_t.
+// RUN: %clang_cc1 -x c++ -fno-wchar -fsyntax-only -verify -fms-extensions -triple i386-pc-win32 %s
+
+wchar_t f(); // expected-error{{unknown type name 'wchar_t'}}
+
+// __wchar_t is available as an MS extension.
+__wchar_t g(); // No error.
+
+// __wchar_t is the same as the target's integer type for wide chars.
+unsigned short g(); // No error.