]> granicus.if.org Git - clang/commitdiff
Implement __underlying_type for libc++.
authorSean Hunt <scshunt@csclub.uwaterloo.ca>
Thu, 19 May 2011 05:37:45 +0000 (05:37 +0000)
committerSean Hunt <scshunt@csclub.uwaterloo.ca>
Thu, 19 May 2011 05:37:45 +0000 (05:37 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131633 91177308-0d34-0410-b5e6-96231b3b80d8

13 files changed:
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Basic/Specifiers.h
include/clang/Basic/TokenKinds.def
include/clang/Parse/Parser.h
include/clang/Sema/DeclSpec.h
lib/Parse/ParseDecl.cpp
lib/Parse/ParseDeclCXX.cpp
lib/Parse/ParseExprCXX.cpp
lib/Parse/ParseTentative.cpp
lib/Sema/DeclSpec.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaTemplateVariadic.cpp
lib/Sema/SemaType.cpp

index 513ad0ea73c058c73a93fff2340d4d1e07085f43..7e3cf03d53092f6ab184a88a1ba7425ac92f35e3 100644 (file)
@@ -1015,6 +1015,10 @@ def err_enum_redeclare_fixed_mismatch : Error<
   "enumeration previously declared with %select{non|}0fixed underlying type">;
 def err_enum_redeclare_scoped_mismatch : Error<
   "enumeration previously declared as %select{un|}0scoped">;
+def err_only_enums_have_underlying_types : Error<
+  "only enumeration types have underlying types">;
+def err_incomplete_type_no_underlying_type : Error<
+  "an incomplete enumeration type has no underlying type yet">;
 
 // C++0x delegating constructors
 def err_delegation_0x_only : Error<
index 2f0ad9ffb688cbecc198eb2ce22f849b1ebb042e..042fd02fbed88af259f45f542088c386fda56854 100644 (file)
@@ -54,6 +54,7 @@ namespace clang {
     TST_typeofType,
     TST_typeofExpr,
     TST_decltype,     // C++0x decltype
+    TST_underlying_type, // __underlying_type for C++0x
     TST_auto,         // C++0x auto
     TST_unknown_anytype, // __unknown_anytype extension
     TST_error         // erroneous type
index 239c5b83e101dd516ea4480d173a1dbd5146af0d..11865247af5f1cdad379a7e4667fe95a916c059d 100644 (file)
@@ -348,6 +348,7 @@ KEYWORD(__is_union                  , KEYCXX)
 
 // Clang-only C++ Type Traits
 KEYWORD(__is_trivially_copyable     , KEYCXX)
+KEYWORD(__underlying_type           , KEYCXX)
 
 // Embarcadero Expression Traits
 KEYWORD(__is_lvalue_expr            , KEYCXX)
index e54b00c821d2457a1ed10c5df33105b1e1e3e4f0..0d65f43e907f341cc962f1471ce8db33e6362e48 100644 (file)
@@ -1648,6 +1648,7 @@ bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names,
 
   void ParseTypeofSpecifier(DeclSpec &DS);
   void ParseDecltypeSpecifier(DeclSpec &DS);
+  void ParseUnderlyingTypeSpecifier(DeclSpec &DS);
   
   ExprResult ParseCXX0XAlignArgument(SourceLocation Start);
 
index da40f14f0ed772f10799a6809a9cb1267d5c56da..d3e943ede058733d82e4365e4959c707c86e80d0 100644 (file)
@@ -249,6 +249,7 @@ public:
   static const TST TST_typeofType = clang::TST_typeofType;
   static const TST TST_typeofExpr = clang::TST_typeofExpr;
   static const TST TST_decltype = clang::TST_decltype;
+  static const TST TST_underlying_type = clang::TST_underlying_type;
   static const TST TST_auto = clang::TST_auto;
   static const TST TST_unknown_anytype = clang::TST_unknown_anytype;
   static const TST TST_error = clang::TST_error;
@@ -344,7 +345,8 @@ private:
   void SaveStorageSpecifierAsWritten();
 
   static bool isTypeRep(TST T) {
-    return (T == TST_typename || T == TST_typeofType);
+    return (T == TST_typename || T == TST_typeofType ||
+            T == TST_underlying_type);
   }
   static bool isExprRep(TST T) {
     return (T == TST_typeofExpr || T == TST_decltype);
index d7b90f129c4494310c45f1aec007d5ee54b1b2cc..eadd5464f2972cd9915c7fb9d1407a2f7d7d5604 100644 (file)
@@ -1859,6 +1859,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
       ParseDecltypeSpecifier(DS);
       continue;
 
+    case tok::kw___underlying_type:
+      ParseUnderlyingTypeSpecifier(DS);
+
     // OpenCL qualifiers:
     case tok::kw_private: 
       if (!getLang().OpenCL)
@@ -2129,6 +2132,11 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
     ParseDecltypeSpecifier(DS);
     return true;
 
+  // C++0x type traits support.
+  case tok::kw___underlying_type:
+    ParseUnderlyingTypeSpecifier(DS);
+    return true;
+
   // OpenCL qualifiers:
   case tok::kw_private: 
     if (!getLang().OpenCL)
index 91b55d5b58729a8310251c5b9146ce6c061d2360..f623c8e5b6375e08b079c90572b342455c1f8ad2 100644 (file)
@@ -572,6 +572,42 @@ void Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
     Diag(StartLoc, DiagID) << PrevSpec;
 }
 
+void Parser::ParseUnderlyingTypeSpecifier(DeclSpec &DS) {
+  assert(Tok.is(tok::kw___underlying_type) &&
+         "Not an underlying type specifier");
+
+  SourceLocation StartLoc = ConsumeToken();
+  SourceLocation LParenLoc = Tok.getLocation();
+
+  if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
+                       "__underlying_type")) {
+    SkipUntil(tok::r_paren);
+    return;
+  }
+
+  TypeResult Result = ParseTypeName();
+  if (Result.isInvalid()) {
+    SkipUntil(tok::r_paren);
+    return;
+  }
+
+  // Match the ')'
+  SourceLocation RParenLoc;
+  if (Tok.is(tok::r_paren))
+    RParenLoc = ConsumeParen();
+  else
+    MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+  if (RParenLoc.isInvalid())
+    return;
+
+  const char *PrevSpec = 0;
+  unsigned DiagID;
+  if (DS.SetTypeSpecType(DeclSpec::TST_underlying_type, StartLoc, PrevSpec,
+                         DiagID, Result.release()))
+    Diag(StartLoc, DiagID) << PrevSpec;
+}
+
 /// ParseClassName - Parse a C++ class-name, which names a class. Note
 /// that we only check that the result names a type; semantic analysis
 /// will need to verify that the type names a class. The result is
index 7410dbecf1f3ecafa60456c728fd6e8fa639558b..0862af323e001d838ca6925e7e83f9f79b4bc926 100644 (file)
@@ -962,6 +962,7 @@ bool Parser::isCXXSimpleTypeSpecifier() const {
   case tok::kw_bool:
   case tok::kw_decltype:
   case tok::kw_typeof:
+  case tok::kw___underlying_type:
     return true;
 
   default:
index 12152c36cc3a61d35cba7a2ff1a3dac706c3b2ca..78d2c9091b1bad4a61307d2dd7fae61056ab5b1b 100644 (file)
@@ -694,6 +694,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
   case tok::kw_char16_t:
   case tok::kw_char32_t:
   case tok::kw_decltype:
+  case tok::kw___underlying_type:
   case tok::kw_thread_local:
   case tok::kw__Decimal32:
   case tok::kw__Decimal64:
@@ -1012,6 +1013,10 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() {
   case tok::kw_decltype:
     return TPResult::True();
 
+  // C++0x type traits support
+  case tok::kw___underlying_type:
+    return TPResult::True();
+
   default:
     return TPResult::False();
   }
index 0f20d10b076a2053a3a65c439da8d110cf7c5be1..d6f8f91bbf111eb210a180ed22cac20c1daa12e4 100644 (file)
@@ -309,6 +309,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T) {
   case DeclSpec::TST_typeofExpr:  return "typeof";
   case DeclSpec::TST_auto:        return "auto";
   case DeclSpec::TST_decltype:    return "(decltype)";
+  case DeclSpec::TST_underlying_type: return "__underlying_type";
   case DeclSpec::TST_unknown_anytype: return "__unknown_anytype";
   case DeclSpec::TST_error:       return "(error)";
   }
index 7c6cde2296bbbdbbd70897a7e874bdc2fe94b96c..fd28f2b6ee9d59b9f348faf05e7c92fb58914d9b 100644 (file)
@@ -2864,7 +2864,8 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D,
   switch (DS.getTypeSpecType()) {
   case DeclSpec::TST_typename:
   case DeclSpec::TST_typeofType:
-  case DeclSpec::TST_decltype: {
+  case DeclSpec::TST_decltype:
+  case DeclSpec::TST_underlying_type: {
     // Grab the type from the parser.
     TypeSourceInfo *TSI = 0;
     QualType T = S.GetTypeFromParser(DS.getRepAsType(), &TSI);
index 096d353bccc320cd9bb987cd1cf3e8db1a2b03a2..100c6a77a06348f0c34f47cdff977c3c2fd69adf 100644 (file)
@@ -617,7 +617,8 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
   const DeclSpec &DS = D.getDeclSpec();
   switch (DS.getTypeSpecType()) {
   case TST_typename:
-  case TST_typeofType: {
+  case TST_typeofType:
+  case TST_underlying_type: {
     QualType T = DS.getRepAsType().get();
     if (!T.isNull() && T->containsUnexpandedParameterPack())
       return true;
index 06548a44ddbc49d93d019ec560517eb73e4c812f..dbacb47812a2eecb20f44ad3c9cb67f71caad9f1 100644 (file)
@@ -836,6 +836,29 @@ static QualType ConvertDeclSpecToType(Sema &S, TypeProcessingState &state) {
     }
     break;
   }
+  case DeclSpec::TST_underlying_type:
+    // FIXME: Preserve type source info?
+    Result = S.GetTypeFromParser(DS.getRepAsType());
+    assert(!Result.isNull() && "Didn't get a type for __underlying_type?");
+    if (!Result->isDependentType()) {
+      if (Result->isEnumeralType()) {
+        EnumDecl *ED = Result->getAs<EnumType>()->getDecl();
+        S.DiagnoseUseOfDecl(ED, DS.getTypeSpecTypeLoc());
+        QualType UnderlyingType = ED->getIntegerType();
+        if (UnderlyingType.isNull()) {
+          declarator.setInvalidType(true);
+          Result = Context.IntTy;
+        } else {
+          Result = UnderlyingType;
+        }
+      } else {
+        S.Diag(DS.getTypeSpecTypeLoc(),
+               diag::err_only_enums_have_underlying_types);
+        Result = Context.IntTy;
+      }
+    }
+    break; 
+
   case DeclSpec::TST_auto: {
     // TypeQuals handled by caller.
     Result = Context.getAutoType(QualType());