Implement support for the 'wchar_t' C++ type.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@54585 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 2c1e1e4..1d4c2a3 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -118,6 +118,7 @@
QualType VoidTy;
QualType BoolTy;
QualType CharTy;
+ QualType WCharTy; // [C++ 3.9.1p5]
QualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy;
QualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy;
QualType UnsignedLongLongTy;
@@ -236,6 +237,14 @@
/// getWcharType - Return the unique type for "wchar_t" (C99 7.17), defined
/// in <stddef.h>. Wide strings require this (C99 6.4.5p5).
QualType getWcharType() const;
+
+ /// getSignedWCharType - Return the type of "signed wchar_t".
+ /// Used when in C++, as a GCC extension.
+ QualType getSignedWCharType() const;
+
+ /// getUnsignedWCharType - Return the type of "unsigned wchar_t".
+ /// Used when in C++, as a GCC extension.
+ QualType getUnsignedWCharType() const;
/// getPointerDiffType - Return the unique type for "ptrdiff_t" (ref?)
/// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 2154179..502b387 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -476,7 +476,9 @@
Long,
LongLong,
- Float, Double, LongDouble
+ Float, Double, LongDouble,
+
+ WChar // This is 'wchar_t' for C++.
};
private:
Kind TypeKind;
diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def
index 7afe572..076ccce 100644
--- a/include/clang/Basic/DiagnosticKinds.def
+++ b/include/clang/Basic/DiagnosticKinds.def
@@ -571,6 +571,8 @@
"cannot combine with previous '%0' declaration specifier")
DIAG(err_invalid_sign_spec, ERROR,
"'%0' cannot be signed or unsigned")
+DIAG(ext_invalid_sign_spec, EXTENSION,
+ "'%0' cannot be signed or unsigned")
DIAG(err_invalid_short_spec, ERROR,
"'short %0' is invalid")
DIAG(err_invalid_long_spec, ERROR,
diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h
index acae7a3..df5109d 100644
--- a/include/clang/Parse/DeclSpec.h
+++ b/include/clang/Parse/DeclSpec.h
@@ -63,6 +63,7 @@
TST_unspecified,
TST_void,
TST_char,
+ TST_wchar, // C++ wchar_t
TST_int,
TST_float,
TST_double,
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index f47855a..fef85b5 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -161,7 +161,10 @@
InitBuiltinType(FloatTy, BuiltinType::Float);
InitBuiltinType(DoubleTy, BuiltinType::Double);
InitBuiltinType(LongDoubleTy, BuiltinType::LongDouble);
-
+
+ // C++ 3.9.1p5
+ InitBuiltinType(WCharTy, BuiltinType::WChar);
+
// C99 6.2.5p11.
FloatComplexTy = getComplexType(FloatTy);
DoubleComplexTy = getComplexType(DoubleTy);
@@ -246,6 +249,10 @@
Width = Target.getCharWidth();
Align = Target.getCharAlign();
break;
+ case BuiltinType::WChar:
+ Width = Target.getWCharWidth();
+ Align = Target.getWCharAlign();
+ break;
case BuiltinType::UShort:
case BuiltinType::Short:
Width = Target.getShortWidth();
@@ -996,11 +1003,28 @@
/// width of characters in wide strings, The value is target dependent and
/// needs to agree with the definition in <stddef.h>.
QualType ASTContext::getWcharType() const {
+ if (LangOpts.CPlusPlus)
+ return WCharTy;
+
// On Darwin, wchar_t is defined as a "int".
// FIXME: should derive from "Target".
return IntTy;
}
+/// getSignedWCharType - Return the type of "signed wchar_t".
+/// Used when in C++, as a GCC extension.
+QualType ASTContext::getSignedWCharType() const {
+ // FIXME: derive from "Target" ?
+ return WCharTy;
+}
+
+/// getUnsignedWCharType - Return the type of "unsigned wchar_t".
+/// Used when in C++, as a GCC extension.
+QualType ASTContext::getUnsignedWCharType() const {
+ // FIXME: derive from "Target" ?
+ return UnsignedIntTy;
+}
+
/// getPointerDiffType - Return the unique type for "ptrdiff_t" (ref?)
/// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
QualType ASTContext::getPointerDiffType() const {
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp
index 8e6dacb..d97dcfa 100644
--- a/lib/Parse/DeclSpec.cpp
+++ b/lib/Parse/DeclSpec.cpp
@@ -87,6 +87,7 @@
case DeclSpec::TST_unspecified: return "unspecified";
case DeclSpec::TST_void: return "void";
case DeclSpec::TST_char: return "char";
+ case DeclSpec::TST_wchar: return "wchar_t";
case DeclSpec::TST_int: return "int";
case DeclSpec::TST_float: return "float";
case DeclSpec::TST_double: return "double";
@@ -214,11 +215,12 @@
const LangOptions &Lang) {
// Check the type specifier components first.
- // signed/unsigned are only valid with int/char.
+ // signed/unsigned are only valid with int/char/wchar_t.
if (TypeSpecSign != TSS_unspecified) {
if (TypeSpecType == TST_unspecified)
TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int.
- else if (TypeSpecType != TST_int && TypeSpecType != TST_char) {
+ else if (TypeSpecType != TST_int &&
+ TypeSpecType != TST_char && TypeSpecType != TST_wchar) {
Diag(D, TSSLoc, SrcMgr, diag::err_invalid_sign_spec,
getSpecifierName( (TST)TypeSpecType));
// signed double -> double.
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 1cf3317..5b4473e 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -376,6 +376,7 @@
/// struct-or-union-specifier
/// enum-specifier
/// typedef-name
+/// [C++] 'wchar_t'
/// [C++] 'bool'
/// [C99] '_Bool'
/// [C99] '_Complex'
@@ -517,6 +518,9 @@
case tok::kw_double:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec);
break;
+ case tok::kw_wchar_t: // [C++ 2.11p1]
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec);
+ break;
case tok::kw_bool: // [C++ 2.11p1]
case tok::kw__Bool:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec);
@@ -941,6 +945,7 @@
case tok::kw__Imaginary:
case tok::kw_void:
case tok::kw_char:
+ case tok::kw_wchar_t:
case tok::kw_int:
case tok::kw_float:
case tok::kw_double:
@@ -992,6 +997,7 @@
case tok::kw__Imaginary:
case tok::kw_void:
case tok::kw_char:
+ case tok::kw_wchar_t:
case tok::kw_int:
case tok::kw_float:
case tok::kw_double:
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 7acb458..bda8932 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -42,6 +42,21 @@
Result = Context.UnsignedCharTy;
}
break;
+ case DeclSpec::TST_wchar:
+ if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified)
+ Result = Context.WCharTy;
+ else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed) {
+ Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec,
+ DS.getSpecifierName(DS.getTypeSpecType()));
+ Result = Context.getSignedWCharType();
+ } else {
+ assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned &&
+ "Unknown TSS value");
+ Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec,
+ DS.getSpecifierName(DS.getTypeSpecType()));
+ Result = Context.getUnsignedWCharType();
+ }
+ break;
case DeclSpec::TST_unspecified:
// "<proto1,proto2>" is an objc qualified ID with a missing id.
if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
diff --git a/test/Sema/cxx-wchar_t.cpp b/test/Sema/cxx-wchar_t.cpp
new file mode 100644
index 0000000..43dd6ee
--- /dev/null
+++ b/test/Sema/cxx-wchar_t.cpp
@@ -0,0 +1,8 @@
+// RUN: clang -fsyntax-only -pedantic -verify %s
+wchar_t x;
+
+void f(wchar_t p) {
+ wchar_t x;
+ unsigned wchar_t y; // expected-warning {{'wchar_t' cannot be signed or unsigned}}
+ signed wchar_t z; // expected-warning {{'wchar_t' cannot be signed or unsigned}}
+}