r181587 - Add support for __wchar_t in -fms-extensions mode.

Hans Wennborg hans at hanshq.net
Fri May 10 03:08:40 PDT 2013


Author: hans
Date: Fri May 10 05:08:40 2013
New Revision: 181587

URL: http://llvm.org/viewvc/llvm-project?rev=181587&view=rev
Log:
Add support for __wchar_t in -fms-extensions mode.

MSVC provides __wchar_t. This is the same as the built-in wchar_t type
from C++, but it is also available with -fno-wchar and in C.

The commit changes ASTContext to have two different types for this:

  - WCharTy is the built-in type used for wchar_t in C++ and __wchar_t.

  - WideCharTy is the type of a wide character literal. In C++ this is
    the same as WCharTy, and in C  it is an integer type compatible with
    the type in <stddef.h>.

This fixes PR15815.

Added:
    cfe/trunk/test/Sema/ms-wchar.c
    cfe/trunk/test/SemaCXX/ms-wchar.cpp
Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/PrettyPrinter.h
    cfe/trunk/include/clang/Basic/TokenKinds.def
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/lib/Analysis/FormatString.cpp
    cfe/trunk/lib/Analysis/PrintfFormatString.cpp
    cfe/trunk/lib/Analysis/ScanfFormatString.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprObjC.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=181587&r1=181586&r2=181587&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Fri May 10 05:08:40 2013
@@ -740,7 +740,8 @@ public:
   CanQualType VoidTy;
   CanQualType BoolTy;
   CanQualType CharTy;
-  CanQualType WCharTy;  // [C++ 3.9.1p5], integer type in C99.
+  CanQualType WCharTy;  // [C++ 3.9.1p5].
+  CanQualType WideCharTy; // Same as WCharTy in C++, integer type in C99.
   CanQualType WIntTy;   // [C99 7.24.1], integer type unchanged by default promotions.
   CanQualType Char16Ty; // [C++0x 3.9.1p5], integer type in C99.
   CanQualType Char32Ty; // [C++0x 3.9.1p5], integer type in C99.
@@ -1130,11 +1131,15 @@ public:
   /// <stdint.h>.
   CanQualType getUIntMaxType() const;
 
-  /// \brief In C++, this returns the unique wchar_t type.  In C99, this
-  /// returns a type compatible with the type defined in <stddef.h> as defined
-  /// by the target.
+  /// \brief Return the unique wchar_t type available in C++ (and available as
+  /// __wchar_t as a Microsoft extension).
   QualType getWCharType() const { return WCharTy; }
 
+  /// \brief Return the type of wide characters. In C++, this returns the
+  /// unique wchar_t type. In C99, this returns a type compatible with the type
+  /// defined in <stddef.h> as defined by the target.
+  QualType getWideCharType() const { return WideCharTy; }
+
   /// \brief Return the type of "signed wchar_t".
   ///
   /// Used when in C++, as a GCC extension.

Modified: cfe/trunk/include/clang/AST/PrettyPrinter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/PrettyPrinter.h?rev=181587&r1=181586&r2=181587&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/PrettyPrinter.h (original)
+++ cfe/trunk/include/clang/AST/PrettyPrinter.h Fri May 10 05:08:40 2013
@@ -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.MicrosoftExt && !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

Modified: cfe/trunk/include/clang/Basic/TokenKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=181587&r1=181586&r2=181587&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TokenKinds.def (original)
+++ cfe/trunk/include/clang/Basic/TokenKinds.def Fri May 10 05:08:40 2013
@@ -524,6 +524,7 @@ KEYWORD(__interface                   ,
 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)

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=181587&r1=181586&r2=181587&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Fri May 10 05:08:40 2013
@@ -897,13 +897,17 @@ void ASTContext::InitBuiltinTypes(const
   InitBuiltinType(Int128Ty,            BuiltinType::Int128);
   InitBuiltinType(UnsignedInt128Ty,    BuiltinType::UInt128);
 
-  if (LangOpts.CPlusPlus && LangOpts.WChar) { // C++ 3.9.1p5
-    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)
-    WCharTy = getFromTargetType(Target.getWCharType());
+  // C++ 3.9.1p5
+  if (TargetInfo::isTypeSigned(Target.getWCharType()))
+    InitBuiltinType(WCharTy,           BuiltinType::WChar_S);
+  else  // -fshort-wchar makes wchar_t be unsigned.
+    InitBuiltinType(WCharTy,           BuiltinType::WChar_U);
+  if (LangOpts.CPlusPlus && LangOpts.WChar)
+    WideCharTy = WCharTy;
+  else {
+    // C99 (or C++ using -fno-wchar).
+    WideCharTy = getFromTargetType(Target.getWCharType());
+  }
 
   WIntTy = getFromTargetType(Target.getWIntType());
 

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=181587&r1=181586&r2=181587&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Fri May 10 05:08:40 2013
@@ -1521,7 +1521,7 @@ StringRef BuiltinType::getName(const Pri
   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";

Modified: cfe/trunk/lib/Analysis/FormatString.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/FormatString.cpp?rev=181587&r1=181586&r2=181587&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/FormatString.cpp (original)
+++ cfe/trunk/lib/Analysis/FormatString.cpp Fri May 10 05:08:40 2013
@@ -334,7 +334,7 @@ bool ArgType::matchesType(ASTContext &C,
         return false;
       QualType pointeeTy =
         C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType();
-      return pointeeTy == C.getWCharType();
+      return pointeeTy == C.getWideCharType();
     }
     
     case WIntTy: {
@@ -398,7 +398,7 @@ QualType ArgType::getRepresentativeType(
       Res = C.getPointerType(C.CharTy);
       break;
     case WCStrTy:
-      Res = C.getPointerType(C.getWCharType());
+      Res = C.getPointerType(C.getWideCharType());
       break;
     case ObjCPointerTy:
       Res = C.ObjCBuiltinIdTy;

Modified: cfe/trunk/lib/Analysis/PrintfFormatString.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/PrintfFormatString.cpp?rev=181587&r1=181586&r2=181587&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/PrintfFormatString.cpp (original)
+++ cfe/trunk/lib/Analysis/PrintfFormatString.cpp Fri May 10 05:08:40 2013
@@ -372,7 +372,7 @@ ArgType PrintfSpecifier::getArgType(ASTC
     case ConversionSpecifier::CArg:
       if (IsObjCLiteral)
         return ArgType(Ctx.UnsignedShortTy, "unichar");
-      return ArgType(Ctx.WCharTy, "wchar_t");
+      return ArgType(Ctx.WideCharTy, "wchar_t");
     case ConversionSpecifier::pArg:
       return ArgType::CPointerTy;
     case ConversionSpecifier::ObjCObjArg:

Modified: cfe/trunk/lib/Analysis/ScanfFormatString.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ScanfFormatString.cpp?rev=181587&r1=181586&r2=181587&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/ScanfFormatString.cpp (original)
+++ cfe/trunk/lib/Analysis/ScanfFormatString.cpp Fri May 10 05:08:40 2013
@@ -311,7 +311,7 @@ ArgType ScanfSpecifier::getArgType(ASTCo
         case LengthModifier::None:
           return ArgType::PtrTo(ArgType::AnyCharTy);
         case LengthModifier::AsLong:
-          return ArgType::PtrTo(ArgType(Ctx.getWCharType(), "wchar_t"));
+          return ArgType::PtrTo(ArgType(Ctx.getWideCharType(), "wchar_t"));
         case LengthModifier::AsAllocate:
         case LengthModifier::AsMAllocate:
           return ArgType::PtrTo(ArgType::CStrTy);
@@ -323,7 +323,7 @@ ArgType ScanfSpecifier::getArgType(ASTCo
       // FIXME: Mac OS X specific?
       switch (LM.getKind()) {
         case LengthModifier::None:
-          return ArgType::PtrTo(ArgType(Ctx.getWCharType(), "wchar_t"));
+          return ArgType::PtrTo(ArgType(Ctx.getWideCharType(), "wchar_t"));
         case LengthModifier::AsAllocate:
         case LengthModifier::AsMAllocate:
           return ArgType::PtrTo(ArgType(ArgType::WCStrTy, "wchar_t *"));

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=181587&r1=181586&r2=181587&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri May 10 05:08:40 2013
@@ -10408,7 +10408,7 @@ bool Sema::CheckLiteralOperatorDeclarati
     if (Context.hasSameType(T, Context.UnsignedLongLongTy) ||
         Context.hasSameType(T, Context.LongDoubleTy) ||
         Context.hasSameType(T, Context.CharTy) ||
-        Context.hasSameType(T, Context.WCharTy) ||
+        Context.hasSameType(T, Context.WideCharTy) ||
         Context.hasSameType(T, Context.Char16Ty) ||
         Context.hasSameType(T, Context.Char32Ty)) {
       if (++Param == FnDecl->param_end())
@@ -10438,7 +10438,7 @@ bool Sema::CheckLiteralOperatorDeclarati
     // const char *, const wchar_t*, const char16_t*, and const char32_t*
     // are allowed as the first parameter to a two-parameter function
     if (!(Context.hasSameType(T, Context.CharTy) ||
-          Context.hasSameType(T, Context.WCharTy) ||
+          Context.hasSameType(T, Context.WideCharTy) ||
           Context.hasSameType(T, Context.Char16Ty) ||
           Context.hasSameType(T, Context.Char32Ty)))
       goto FinishedParams;

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=181587&r1=181586&r2=181587&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri May 10 05:08:40 2013
@@ -1448,7 +1448,7 @@ Sema::ActOnStringLiteral(const Token *St
 
   QualType StrTy = Context.CharTy;
   if (Literal.isWide())
-    StrTy = Context.getWCharType();
+    StrTy = Context.getWideCharType();
   else if (Literal.isUTF16())
     StrTy = Context.Char16Ty;
   else if (Literal.isUTF32())
@@ -2720,7 +2720,7 @@ ExprResult Sema::ActOnPredefinedExpr(Sou
 
     llvm::APInt LengthI(32, Length + 1);
     if (IT == PredefinedExpr::LFunction)
-      ResTy = Context.WCharTy.withConst();
+      ResTy = Context.WideCharTy.withConst();
     else
       ResTy = Context.CharTy.withConst();
     ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0);
@@ -2742,7 +2742,7 @@ ExprResult Sema::ActOnCharacterConstant(
 
   QualType Ty;
   if (Literal.isWide())
-    Ty = Context.WCharTy; // L'x' -> wchar_t in C and C++.
+    Ty = Context.WideCharTy; // L'x' -> wchar_t in C and C++.
   else if (Literal.isUTF16())
     Ty = Context.Char16Ty; // u'x' -> char16_t in C11 and C++11.
   else if (Literal.isUTF32())

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=181587&r1=181586&r2=181587&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Fri May 10 05:08:40 2013
@@ -266,7 +266,7 @@ ExprResult Sema::BuildObjCNumericLiteral
       break;
       
     case CharacterLiteral::Wide:
-      NumberType = Context.getWCharType();
+      NumberType = Context.getWideCharType();
       break;
       
     case CharacterLiteral::UTF16:
@@ -521,7 +521,7 @@ ExprResult Sema::BuildObjCBoxedExpr(Sour
         break;
         
       case CharacterLiteral::Wide:
-        ValueType = Context.getWCharType();
+        ValueType = Context.getWideCharType();
         break;
         
       case CharacterLiteral::UTF16:

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=181587&r1=181586&r2=181587&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Fri May 10 05:08:40 2013
@@ -65,7 +65,7 @@ static Expr *IsStringInit(Expr *Init, co
     // correction from DR343): "An array with element type compatible with a
     // qualified or unqualified version of wchar_t may be initialized by a wide
     // string literal, optionally enclosed in braces."
-    if (Context.typesAreCompatible(Context.getWCharType(),
+    if (Context.typesAreCompatible(Context.getWideCharType(),
                                    ElemTy.getUnqualifiedType()))
       return Init;
 

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=181587&r1=181586&r2=181587&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Fri May 10 05:08:40 2013
@@ -1105,7 +1105,7 @@ TemplateInstantiator::TransformPredefine
   llvm::APInt LengthI(32, Length + 1);
   QualType ResTy;
   if (IT == PredefinedExpr::LFunction)
-    ResTy = getSema().Context.WCharTy.withConst();
+    ResTy = getSema().Context.WideCharTy.withConst();
   else
     ResTy = getSema().Context.CharTy.withConst();
   ResTy = getSema().Context.getConstantArrayType(ResTy, LengthI, 

Added: cfe/trunk/test/Sema/ms-wchar.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/ms-wchar.c?rev=181587&view=auto
==============================================================================
--- cfe/trunk/test/Sema/ms-wchar.c (added)
+++ cfe/trunk/test/Sema/ms-wchar.c Fri May 10 05:08:40 2013
@@ -0,0 +1,15 @@
+// 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 = L'a'; // 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'}}
+
+// The type of a wide string literal is actually not __wchar_t.
+__wchar_t s[] = L"Hello world!"; // expected-error {{array initializer must be an initializer list}}

Added: cfe/trunk/test/SemaCXX/ms-wchar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/ms-wchar.cpp?rev=181587&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/ms-wchar.cpp (added)
+++ cfe/trunk/test/SemaCXX/ms-wchar.cpp Fri May 10 05:08:40 2013
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions -triple i386-pc-win32 %s
+
+wchar_t f();
+__wchar_t f(); // No error, wchar_t and __wchar_t are the same type.
+
+__wchar_t g = L'a';
+__wchar_t s[] = L"Hello world!";
+
+unsigned short t[] = L"Hello world!"; // expected-error{{array initializer must be an initializer list}}





More information about the cfe-commits mailing list