[cfe-commits] r131633 - in /cfe/trunk: 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

Douglas Gregor dgregor at apple.com
Thu May 19 14:00:48 PDT 2011


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





More information about the cfe-commits mailing list