On May 18, 2011, at 10:37 PM, Sean Hunt wrote:

> Author: coppro
> Date: Thu May 19 00:37:45 2011
> New Revision: 131633
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=131633&view=rev
> Log:
> Implement __underlying_type for libc++.
> 
> Modified:
>    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>    cfe/trunk/include/clang/Basic/Specifiers.h
>    cfe/trunk/include/clang/Basic/TokenKinds.def
>    cfe/trunk/include/clang/Parse/Parser.h
>    cfe/trunk/include/clang/Sema/DeclSpec.h
>    cfe/trunk/lib/Parse/ParseDecl.cpp
>    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
>    cfe/trunk/lib/Parse/ParseExprCXX.cpp
>    cfe/trunk/lib/Parse/ParseTentative.cpp
>    cfe/trunk/lib/Sema/DeclSpec.cpp
>    cfe/trunk/lib/Sema/SemaDecl.cpp
>    cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
>    cfe/trunk/lib/Sema/SemaType.cpp
> 
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=131633&r1=131632&r2=131633&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu May 19 00:37:45 
> 2011
> @@ -1015,6 +1015,10 @@
>   "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<
> 
> Modified: cfe/trunk/include/clang/Basic/Specifiers.h
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Specifiers.h?rev=131633&r1=131632&r2=131633&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/Specifiers.h (original)
> +++ cfe/trunk/include/clang/Basic/Specifiers.h Thu May 19 00:37:45 2011
> @@ -54,6 +54,7 @@
>     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
> 
> Modified: cfe/trunk/include/clang/Basic/TokenKinds.def
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=131633&r1=131632&r2=131633&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/TokenKinds.def (original)
> +++ cfe/trunk/include/clang/Basic/TokenKinds.def Thu May 19 00:37:45 2011
> @@ -348,6 +348,7 @@
> 
> // Clang-only C++ Type Traits
> KEYWORD(__is_trivially_copyable     , KEYCXX)
> +KEYWORD(__underlying_type           , KEYCXX)
> 
> // Embarcadero Expression Traits
> KEYWORD(__is_lvalue_expr            , KEYCXX)
> 
> Modified: cfe/trunk/include/clang/Parse/Parser.h
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=131633&r1=131632&r2=131633&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Parse/Parser.h (original)
> +++ cfe/trunk/include/clang/Parse/Parser.h Thu May 19 00:37:45 2011
> @@ -1648,6 +1648,7 @@
> 
>   void ParseTypeofSpecifier(DeclSpec &DS);
>   void ParseDecltypeSpecifier(DeclSpec &DS);
> +  void ParseUnderlyingTypeSpecifier(DeclSpec &DS);
> 
>   ExprResult ParseCXX0XAlignArgument(SourceLocation Start);
> 
> 
> Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=131633&r1=131632&r2=131633&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
> +++ cfe/trunk/include/clang/Sema/DeclSpec.h Thu May 19 00:37:45 2011
> @@ -249,6 +249,7 @@
>   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 @@
>   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);
> 
> Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=131633&r1=131632&r2=131633&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu May 19 00:37:45 2011
> @@ -1859,6 +1859,9 @@
>       ParseDecltypeSpecifier(DS);
>       continue;
> 
> +    case tok::kw___underlying_type:
> +      ParseUnderlyingTypeSpecifier(DS);
> +

Aren't you missing a 'continue' or 'return' here?

>     // OpenCL qualifiers:
>     case tok::kw_private: 
>       if (!getLang().OpenCL)
> @@ -2129,6 +2132,11 @@
>     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)
> 
> Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=131633&r1=131632&r2=131633&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Thu May 19 00:37:45 2011
> @@ -572,6 +572,42 @@
>     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)

Doesn't MatchRHSPunctuation 'just work' here? Rather than the separate check?

> +  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
> 
> Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=131633&r1=131632&r2=131633&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Thu May 19 00:37:45 2011
> @@ -962,6 +962,7 @@
>   case tok::kw_bool:
>   case tok::kw_decltype:
>   case tok::kw_typeof:
> +  case tok::kw___underlying_type:
>     return true;
> 
>   default:
> 
> Modified: cfe/trunk/lib/Parse/ParseTentative.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=131633&r1=131632&r2=131633&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseTentative.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseTentative.cpp Thu May 19 00:37:45 2011
> @@ -694,6 +694,7 @@
>   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 @@
>   case tok::kw_decltype:
>     return TPResult::True();
> 
> +  // C++0x type traits support
> +  case tok::kw___underlying_type:
> +    return TPResult::True();
> +
>   default:
>     return TPResult::False();
>   }
> 
> Modified: cfe/trunk/lib/Sema/DeclSpec.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/DeclSpec.cpp?rev=131633&r1=131632&r2=131633&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/DeclSpec.cpp (original)
> +++ cfe/trunk/lib/Sema/DeclSpec.cpp Thu May 19 00:37:45 2011
> @@ -309,6 +309,7 @@
>   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)";
>   }
> 
> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=131633&r1=131632&r2=131633&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu May 19 00:37:45 2011
> @@ -2864,7 +2864,8 @@
>   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);
> 
> Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=131633&r1=131632&r2=131633&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Thu May 19 00:37:45 2011
> @@ -617,7 +617,8 @@
>   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;
> 
> Modified: cfe/trunk/lib/Sema/SemaType.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=131633&r1=131632&r2=131633&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaType.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaType.cpp Thu May 19 00:37:45 2011
> @@ -836,6 +836,29 @@
>     }
>     break;
>   }
> +  case DeclSpec::TST_underlying_type:
> +    // FIXME: Preserve type source info?

Yes, we absolutely must preserve type source information. Type source location 
information is absolutely critical for the correct functioning of the front 
end, especially in templates, so we can't skip this part any more.

> +    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; 

This isn't the right place to perform this computation. GetTypeFromParser 
should just be building an UnderlyingType node through some abstracted function 
that handles the creation and type-checking of this type, also used by template 
instantiation.

So… where's the UnderlyingType node in the type hierarchy? Or the associated 
UnderlyingTypeLoc?This is only going to work for non-dependent types, which are 
the least interesting types.

        - Doug


_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to