diff options
author | Nico Weber <thakis@chromium.org> | 2022-08-14 15:57:38 -0400 |
---|---|---|
committer | Nico Weber <thakis@chromium.org> | 2022-08-14 15:58:21 -0400 |
commit | aacf1a9742f714dd432117d82d19a007289c3dee (patch) | |
tree | b41c0f61e159b81a13659a8759223fcdddb04d5d /clang/lib | |
parent | a8c294d6aae340afba9347ef3d41fbb7a9ab51be (diff) | |
download | llvm-aacf1a9742f714dd432117d82d19a007289c3dee.zip llvm-aacf1a9742f714dd432117d82d19a007289c3dee.tar.gz llvm-aacf1a9742f714dd432117d82d19a007289c3dee.tar.bz2 |
Revert "[clang] adds unary type transformations as compiler built-ins"
This reverts commit bc60cf2368de90918719dc7e3d7c63a72cc007ad.
Doesn't build on Windows and breaks gcc 9 build, see
https://reviews.llvm.org/D116203#3722094 and
https://reviews.llvm.org/D116203#3722128
Also revert two follow-ups. One fixed a warning added in
bc60cf2368de90918719dc7e3d7c63a72cc007ad, the other
makes use of the feature added in bc60cf2368de90918719dc7e3d7c63a72cc007ad
in libc++:
Revert "[libcxx][NFC] utilises compiler builtins for unary transform type-traits"
This reverts commit 06a1d917ef1f507aaa2f6891bb654696c866ea3a.
Revert "[Sema] Fix a warning"
This reverts commit c85abbe879ef3257de4db862ce249b060cc3d2a4.
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 27 | ||||
-rw-r--r-- | clang/lib/AST/ItaniumMangle.cpp | 14 | ||||
-rw-r--r-- | clang/lib/AST/JSONNodeDumper.cpp | 7 | ||||
-rw-r--r-- | clang/lib/AST/TextNodeDumper.cpp | 6 | ||||
-rw-r--r-- | clang/lib/AST/TypePrinter.cpp | 32 | ||||
-rw-r--r-- | clang/lib/Format/FormatToken.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Format/FormatToken.h | 3 | ||||
-rw-r--r-- | clang/lib/Format/TokenAnnotator.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Lex/PPMacroExpansion.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 18 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 116 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExpr.cpp | 22 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 20 | ||||
-rw-r--r-- | clang/lib/Parse/ParseStmt.cpp | 18 | ||||
-rw-r--r-- | clang/lib/Parse/ParseTentative.cpp | 11 | ||||
-rw-r--r-- | clang/lib/Sema/DeclSpec.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateVariadic.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 303 |
19 files changed, 134 insertions, 493 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 45ec85f..2c2f466 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -10782,8 +10782,7 @@ unsigned ASTContext::getIntWidth(QualType T) const { } QualType ASTContext::getCorrespondingUnsignedType(QualType T) const { - assert((T->hasIntegerRepresentation() || T->isEnumeralType() || - T->isFixedPointType()) && + assert((T->hasSignedIntegerRepresentation() || T->isSignedFixedPointType()) && "Unexpected type"); // Turn <4 x signed int> -> <4 x unsigned int> @@ -10801,11 +10800,8 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) const { T = ETy->getDecl()->getIntegerType(); switch (T->castAs<BuiltinType>()->getKind()) { - case BuiltinType::Char_U: - // Plain `char` is mapped to `unsigned char` even if it's already unsigned case BuiltinType::Char_S: case BuiltinType::SChar: - case BuiltinType::Char8: return UnsignedCharTy; case BuiltinType::Short: return UnsignedShortTy; @@ -10819,7 +10815,7 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) const { return UnsignedInt128Ty; // wchar_t is special. It is either signed or not, but when it's signed, // there's no matching "unsigned wchar_t". Therefore we return the unsigned - // version of its underlying type instead. + // version of it's underlying type instead. case BuiltinType::WChar_S: return getUnsignedWCharType(); @@ -10848,16 +10844,13 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) const { case BuiltinType::SatLongFract: return SatUnsignedLongFractTy; default: - assert((T->hasUnsignedIntegerRepresentation() || - T->isUnsignedFixedPointType()) && - "Unexpected signed integer or fixed point type"); - return T; + llvm_unreachable("Unexpected signed integer or fixed point type"); } } QualType ASTContext::getCorrespondingSignedType(QualType T) const { - assert((T->hasIntegerRepresentation() || T->isEnumeralType() || - T->isFixedPointType()) && + assert((T->hasUnsignedIntegerRepresentation() || + T->isUnsignedFixedPointType()) && "Unexpected type"); // Turn <4 x unsigned int> -> <4 x signed int> @@ -10875,11 +10868,8 @@ QualType ASTContext::getCorrespondingSignedType(QualType T) const { T = ETy->getDecl()->getIntegerType(); switch (T->castAs<BuiltinType>()->getKind()) { - case BuiltinType::Char_S: - // Plain `char` is mapped to `signed char` even if it's already signed case BuiltinType::Char_U: case BuiltinType::UChar: - case BuiltinType::Char8: return SignedCharTy; case BuiltinType::UShort: return ShortTy; @@ -10893,7 +10883,7 @@ QualType ASTContext::getCorrespondingSignedType(QualType T) const { return Int128Ty; // wchar_t is special. It is either unsigned or not, but when it's unsigned, // there's no matching "signed wchar_t". Therefore we return the signed - // version of its underlying type instead. + // version of it's underlying type instead. case BuiltinType::WChar_U: return getSignedWCharType(); @@ -10922,10 +10912,7 @@ QualType ASTContext::getCorrespondingSignedType(QualType T) const { case BuiltinType::SatULongFract: return SatLongFractTy; default: - assert( - (T->hasSignedIntegerRepresentation() || T->isSignedFixedPointType()) && - "Unexpected signed integer or fixed point type"); - return T; + llvm_unreachable("Unexpected unsigned integer or fixed point type"); } } diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 46229a0..fc5a590 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -3980,22 +3980,16 @@ void CXXNameMangler::mangleType(const UnaryTransformType *T) { // If this is dependent, we need to record that. If not, we simply // mangle it as the underlying type since they are equivalent. if (T->isDependentType()) { - Out << "u"; + Out << 'U'; - StringRef BuiltinName; switch (T->getUTTKind()) { -#define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait) \ - case UnaryTransformType::Enum: \ - BuiltinName = "__" #Trait; \ - break; -#include "clang/Basic/TransformTypeTraits.def" + case UnaryTransformType::EnumUnderlyingType: + Out << "3eut"; + break; } - Out << BuiltinName.size() << BuiltinName; } - Out << "I"; mangleType(T->getBaseType()); - Out << "E"; } void CXXNameMangler::mangleType(const AutoType *T) { diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp index ae9c85e..74ef4c3 100644 --- a/clang/lib/AST/JSONNodeDumper.cpp +++ b/clang/lib/AST/JSONNodeDumper.cpp @@ -1,5 +1,4 @@ #include "clang/AST/JSONNodeDumper.h" -#include "clang/AST/Type.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/Specifiers.h" #include "clang/Lex/Lexer.h" @@ -663,11 +662,9 @@ void JSONNodeDumper::VisitUnresolvedUsingType(const UnresolvedUsingType *UUT) { void JSONNodeDumper::VisitUnaryTransformType(const UnaryTransformType *UTT) { switch (UTT->getUTTKind()) { -#define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait) \ - case UnaryTransformType::Enum: \ - JOS.attribute("transformKind", #Trait); \ + case UnaryTransformType::EnumUnderlyingType: + JOS.attribute("transformKind", "underlying_type"); break; -#include "clang/Basic/TransformTypeTraits.def" } } diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index f9f149b..c3da5a4 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -1551,11 +1551,9 @@ void TextNodeDumper::VisitTypedefType(const TypedefType *T) { void TextNodeDumper::VisitUnaryTransformType(const UnaryTransformType *T) { switch (T->getUTTKind()) { -#define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait) \ - case UnaryTransformType::Enum: \ - OS << " " #Trait; \ + case UnaryTransformType::EnumUnderlyingType: + OS << " underlying_type"; break; -#include "clang/Basic/TransformTypeTraits.def" } } diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index a7da9fd..3cb2001 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -22,7 +22,6 @@ #include "clang/AST/PrettyPrinter.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/TemplateName.h" -#include "clang/AST/TextNodeDumper.h" #include "clang/AST/Type.h" #include "clang/Basic/AddressSpaces.h" #include "clang/Basic/ExceptionSpecificationType.h" @@ -33,7 +32,6 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/Specifiers.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" @@ -1142,19 +1140,29 @@ void TypePrinter::printUnaryTransformBefore(const UnaryTransformType *T, raw_ostream &OS) { IncludeStrongLifetimeRAII Strong(Policy); - static llvm::DenseMap<int, const char *> Transformation = {{ -#define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait) \ - {UnaryTransformType::Enum, "__" #Trait}, -#include "clang/Basic/TransformTypeTraits.def" - }}; - OS << Transformation[T->getUTTKind()] << '('; - print(T->getBaseType(), OS, StringRef()); - OS << ')'; - spaceBeforePlaceHolder(OS); + switch (T->getUTTKind()) { + case UnaryTransformType::EnumUnderlyingType: + OS << "__underlying_type("; + print(T->getBaseType(), OS, StringRef()); + OS << ')'; + spaceBeforePlaceHolder(OS); + return; + } + + printBefore(T->getBaseType(), OS); } void TypePrinter::printUnaryTransformAfter(const UnaryTransformType *T, - raw_ostream &OS) {} + raw_ostream &OS) { + IncludeStrongLifetimeRAII Strong(Policy); + + switch (T->getUTTKind()) { + case UnaryTransformType::EnumUnderlyingType: + return; + } + + printAfter(T->getBaseType(), OS); +} void TypePrinter::printAutoBefore(const AutoType *T, raw_ostream &OS) { // If the type has been deduced, do not print 'auto'. diff --git a/clang/lib/Format/FormatToken.cpp b/clang/lib/Format/FormatToken.cpp index f9f0d71..832af46 100644 --- a/clang/lib/Format/FormatToken.cpp +++ b/clang/lib/Format/FormatToken.cpp @@ -56,8 +56,7 @@ bool FormatToken::isSimpleTypeSpecifier() const { case tok::kw___ibm128: case tok::kw_wchar_t: case tok::kw_bool: -#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait: -#include "clang/Basic/TransformTypeTraits.def" + case tok::kw___underlying_type: case tok::annot_typename: case tok::kw_char8_t: case tok::kw_char16_t: diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index 1ce64f7..7d963cf 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -677,8 +677,7 @@ public: case tok::kw_static_assert: case tok::kw__Atomic: case tok::kw___attribute: -#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait: -#include "clang/Basic/TransformTypeTraits.def" + case tok::kw___underlying_type: case tok::kw_requires: return true; default: diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index eb0ee91..b0a1c69 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -317,10 +317,8 @@ private: if (PrevNonComment->is(tok::kw___attribute)) { OpeningParen.setType(TT_AttributeParen); } else if (PrevNonComment->isOneOf(TT_TypenameMacro, tok::kw_decltype, - tok::kw_typeof, -#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) tok::kw___##Trait, -#include "clang/Basic/TransformTypeTraits.def" - tok::kw__Atomic)) { + tok::kw_typeof, tok::kw__Atomic, + tok::kw___underlying_type)) { OpeningParen.setType(TT_TypeDeclarationParen); // decltype() and typeof() usually contain expressions. if (PrevNonComment->isOneOf(tok::kw_decltype, tok::kw_typeof)) diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index 78ab8ba..f3be210 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -1663,8 +1663,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { .Case("__array_rank", true) .Case("__array_extent", true) .Case("__reference_binds_to_temporary", true) -#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) .Case("__" #Trait, true) -#include "clang/Basic/TransformTypeTraits.def" + .Case("__underlying_type", true) .Default(false); } else { return llvm::StringSwitch<bool>(II->getName()) diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 70dd5e2..39ba93e 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -3471,8 +3471,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // typedef-name case tok::kw___super: case tok::kw_decltype: - case tok::identifier: - ParseIdentifier: { + case tok::identifier: { // This identifier can only be a typedef name if we haven't already seen // a type-specifier. Without this check we misparse: // typedef int X; struct Y { short X; }; as 'short int'. @@ -3665,7 +3664,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, } } ConsumedEnd = Tok.getLocation(); - DS.setTypeArgumentRange(Tracker.getRange()); + DS.setTypeofParensRange(Tracker.getRange()); // Even if something went wrong above, continue as if we've seen // `decltype(auto)`. isInvalid = DS.SetTypeSpecType(TST_decltype_auto, Loc, PrevSpec, @@ -4207,13 +4206,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, HandlePragmaMSPointersToMembers(); continue; -#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait: -#include "clang/Basic/TransformTypeTraits.def" - // HACK: libstdc++ already uses '__remove_cv' as an alias template so we - // work around this by expecting all transform type traits to be suffixed - // with '('. They're an identifier otherwise. - if (!MaybeParseTypeTransformTypeSpecifier(DS)) - goto ParseIdentifier; + case tok::kw___underlying_type: + ParseUnderlyingTypeSpecifier(DS); continue; case tok::kw__Atomic: @@ -7451,7 +7445,7 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) { ExprResult Operand = Actions.CorrectDelayedTyposInExpr( ParseExprAfterUnaryExprOrTypeTrait(OpTok, isCastExpr, CastTy, CastRange)); if (hasParens) - DS.setTypeArgumentRange(CastRange); + DS.setTypeofParensRange(CastRange); if (CastRange.getEnd().isInvalid()) // FIXME: Not accurate, the range gets one token more than it should. @@ -7521,7 +7515,7 @@ void Parser::ParseAtomicSpecifier(DeclSpec &DS) { if (T.getCloseLocation().isInvalid()) return; - DS.setTypeArgumentRange(T.getRange()); + DS.setTypeofParensRange(T.getRange()); DS.SetRangeEnd(T.getCloseLocation()); const char *PrevSpec = nullptr; diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 4510ff8..8dfa91e 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -18,7 +18,6 @@ #include "clang/Basic/CharInfo.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/TargetInfo.h" -#include "clang/Basic/TokenKinds.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" @@ -1022,7 +1021,7 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { EndLoc = Tok.getAnnotationEndLoc(); // Unfortunately, we don't know the LParen source location as the annotated // token doesn't have it. - DS.setTypeArgumentRange(SourceRange(SourceLocation(), EndLoc)); + DS.setTypeofParensRange(SourceRange(SourceLocation(), EndLoc)); ConsumeAnnotationToken(); if (Result.isInvalid()) { DS.SetTypeSpecError(); @@ -1086,7 +1085,7 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { // Match the ')' T.consumeClose(); - DS.setTypeArgumentRange(T.getRange()); + DS.setTypeofParensRange(T.getRange()); if (T.getCloseLocation().isInvalid()) { DS.SetTypeSpecError(); // FIXME: this should return the location of the last token @@ -1143,48 +1142,35 @@ void Parser::AnnotateExistingDecltypeSpecifier(const DeclSpec &DS, PP.AnnotateCachedTokens(Tok); } -DeclSpec::TST Parser::TypeTransformTokToDeclSpec() { - switch (Tok.getKind()) { -#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \ - case tok::kw___##Trait: \ - return DeclSpec::TST_##Trait; -#include "clang/Basic/TransformTypeTraits.def" - default: - llvm_unreachable("passed in an unhandled type transformation built-in"); - } -} +void Parser::ParseUnderlyingTypeSpecifier(DeclSpec &DS) { + assert(Tok.is(tok::kw___underlying_type) && + "Not an underlying type specifier"); -bool Parser::MaybeParseTypeTransformTypeSpecifier(DeclSpec &DS) { - if (!NextToken().is(tok::l_paren)) { - Tok.setKind(tok::identifier); - return false; - } - DeclSpec::TST TypeTransformTST = TypeTransformTokToDeclSpec(); SourceLocation StartLoc = ConsumeToken(); - BalancedDelimiterTracker T(*this, tok::l_paren); - if (T.expectAndConsume(diag::err_expected_lparen_after, Tok.getName(), - tok::r_paren)) - return true; + if (T.expectAndConsume(diag::err_expected_lparen_after, "__underlying_type", + tok::r_paren)) { + return; + } TypeResult Result = ParseTypeName(); if (Result.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); - return true; + return; } + // Match the ')' T.consumeClose(); if (T.getCloseLocation().isInvalid()) - return true; + return; const char *PrevSpec = nullptr; unsigned DiagID; - if (DS.SetTypeSpecType(TypeTransformTST, StartLoc, PrevSpec, DiagID, - Result.get(), + if (DS.SetTypeSpecType(DeclSpec::TST_underlyingType, StartLoc, PrevSpec, + DiagID, Result.get(), Actions.getASTContext().getPrintingPolicy())) Diag(StartLoc, DiagID) << PrevSpec; - DS.setTypeArgumentRange(T.getRange()); - return true; + DS.setTypeofParensRange(T.getRange()); } /// ParseBaseTypeSpecifier - Parse a C++ base-type-specifier which is either a @@ -1539,58 +1525,28 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (TagType == DeclSpec::TST_struct && Tok.isNot(tok::identifier) && !Tok.isAnnotation() && Tok.getIdentifierInfo() && Tok.isOneOf( -#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) tok::kw___##Trait, -#include "clang/Basic/TransformTypeTraits.def" - tok::kw___is_abstract, - tok::kw___is_aggregate, - tok::kw___is_arithmetic, - tok::kw___is_array, - tok::kw___is_assignable, - tok::kw___is_base_of, - tok::kw___is_class, - tok::kw___is_complete_type, - tok::kw___is_compound, - tok::kw___is_const, - tok::kw___is_constructible, - tok::kw___is_convertible, - tok::kw___is_convertible_to, - tok::kw___is_destructible, - tok::kw___is_empty, - tok::kw___is_enum, - tok::kw___is_floating_point, - tok::kw___is_final, - tok::kw___is_function, - tok::kw___is_fundamental, - tok::kw___is_integral, - tok::kw___is_interface_class, - tok::kw___is_literal, - tok::kw___is_lvalue_expr, - tok::kw___is_lvalue_reference, - tok::kw___is_member_function_pointer, - tok::kw___is_member_object_pointer, - tok::kw___is_member_pointer, - tok::kw___is_nothrow_assignable, - tok::kw___is_nothrow_constructible, - tok::kw___is_nothrow_destructible, - tok::kw___is_object, - tok::kw___is_pod, - tok::kw___is_pointer, - tok::kw___is_polymorphic, - tok::kw___is_reference, - tok::kw___is_rvalue_expr, - tok::kw___is_rvalue_reference, - tok::kw___is_same, - tok::kw___is_scalar, - tok::kw___is_sealed, - tok::kw___is_signed, - tok::kw___is_standard_layout, - tok::kw___is_trivial, + tok::kw___is_abstract, tok::kw___is_aggregate, + tok::kw___is_arithmetic, tok::kw___is_array, tok::kw___is_assignable, + tok::kw___is_base_of, tok::kw___is_class, tok::kw___is_complete_type, + tok::kw___is_compound, tok::kw___is_const, tok::kw___is_constructible, + tok::kw___is_convertible, tok::kw___is_convertible_to, + tok::kw___is_destructible, tok::kw___is_empty, tok::kw___is_enum, + tok::kw___is_floating_point, tok::kw___is_final, + tok::kw___is_function, tok::kw___is_fundamental, + tok::kw___is_integral, tok::kw___is_interface_class, + tok::kw___is_literal, tok::kw___is_lvalue_expr, + tok::kw___is_lvalue_reference, tok::kw___is_member_function_pointer, + tok::kw___is_member_object_pointer, tok::kw___is_member_pointer, + tok::kw___is_nothrow_assignable, tok::kw___is_nothrow_constructible, + tok::kw___is_nothrow_destructible, tok::kw___is_object, + tok::kw___is_pod, tok::kw___is_pointer, tok::kw___is_polymorphic, + tok::kw___is_reference, tok::kw___is_rvalue_expr, + tok::kw___is_rvalue_reference, tok::kw___is_same, tok::kw___is_scalar, + tok::kw___is_sealed, tok::kw___is_signed, + tok::kw___is_standard_layout, tok::kw___is_trivial, tok::kw___is_trivially_assignable, - tok::kw___is_trivially_constructible, - tok::kw___is_trivially_copyable, - tok::kw___is_union, - tok::kw___is_unsigned, - tok::kw___is_void, + tok::kw___is_trivially_constructible, tok::kw___is_trivially_copyable, + tok::kw___is_union, tok::kw___is_unsigned, tok::kw___is_void, tok::kw___is_volatile)) // GNU libstdc++ 4.2 and libc++ use certain intrinsic names as the // name of struct templates, but some are keywords in GCC >= 4.3 diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 588f4cf..354908a 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1038,10 +1038,9 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, return ParseCastExpression(ParseKind, isAddressOfOperand, isTypeCast, isVectorLiteral, NotPrimaryExpression); - case tok::identifier: - ParseIdentifier: { // primary-expression: identifier - // unqualified-id: identifier - // constant: enumeration-constant + case tok::identifier: { // primary-expression: identifier + // unqualified-id: identifier + // constant: enumeration-constant // Turn a potentially qualified name into a annot_typename or // annot_cxxscope if it would be valid. This handles things like x::y, etc. if (getLangOpts().CPlusPlus) { @@ -1114,9 +1113,6 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, REVERTIBLE_TYPE_TRAIT(__is_unsigned); REVERTIBLE_TYPE_TRAIT(__is_void); REVERTIBLE_TYPE_TRAIT(__is_volatile); -#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \ - REVERTIBLE_TYPE_TRAIT(RTT_JOIN(__, Trait)); -#include "clang/Basic/TransformTypeTraits.def" #undef REVERTIBLE_TYPE_TRAIT #undef RTT_JOIN } @@ -1743,17 +1739,6 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, PreferredType.get(Tok.getLocation())); return ExprError(); } -#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait: -#include "clang/Basic/TransformTypeTraits.def" - // HACK: libstdc++ uses some of the transform-type-traits as alias - // templates, so we need to work around this. - if (!NextToken().is(tok::l_paren)) { - Tok.setKind(tok::identifier); - Diag(Tok, diag::ext_keyword_as_ident) - << Tok.getIdentifierInfo()->getName() << 0; - goto ParseIdentifier; - } - goto ExpectedExpression; case tok::l_square: if (getLangOpts().CPlusPlus11) { if (getLangOpts().ObjC) { @@ -1781,7 +1766,6 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, } [[fallthrough]]; default: - ExpectedExpression: NotCastExpr = true; return ExprError(); } diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index b2e9aa1..2f30075 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -14,7 +14,6 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" #include "clang/Basic/PrettyStackTrace.h" -#include "clang/Basic/TokenKinds.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" @@ -22,7 +21,6 @@ #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include <numeric> @@ -2821,7 +2819,6 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, // identifier // template-id (when it hasn't already been annotated) if (Tok.is(tok::identifier)) { - ParseIdentifier: // Consume the identifier. IdentifierInfo *Id = Tok.getIdentifierInfo(); SourceLocation IdLoc = ConsumeToken(); @@ -3056,20 +3053,9 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, return false; } - switch (Tok.getKind()) { -#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait: -#include "clang/Basic/TransformTypeTraits.def" - if (!NextToken().is(tok::l_paren)) { - Tok.setKind(tok::identifier); - Diag(Tok, diag::ext_keyword_as_ident) - << Tok.getIdentifierInfo()->getName() << 0; - goto ParseIdentifier; - } - LLVM_FALLTHROUGH; - default: - Diag(Tok, diag::err_expected_unqualified_id) << getLangOpts().CPlusPlus; - return true; - } + Diag(Tok, diag::err_expected_unqualified_id) + << getLangOpts().CPlusPlus; + return true; } /// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index fc515f1..530e0de 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -14,7 +14,6 @@ #include "clang/AST/PrettyDeclStackTrace.h" #include "clang/Basic/Attributes.h" #include "clang/Basic/PrettyStackTrace.h" -#include "clang/Basic/TokenKinds.h" #include "clang/Parse/LoopHint.h" #include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" @@ -189,8 +188,7 @@ Retry: Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Statement); return StmtError(); - case tok::identifier: - ParseIdentifier: { + case tok::identifier: { Token Next = NextToken(); if (Next.is(tok::colon)) { // C99 6.8.1: labeled-statement // Both C++11 and GNU attributes preceding the label appertain to the @@ -263,19 +261,7 @@ Retry: return StmtError(); } - switch (Tok.getKind()) { -#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait: -#include "clang/Basic/TransformTypeTraits.def" - if (NextToken().is(tok::less)) { - Tok.setKind(tok::identifier); - Diag(Tok, diag::ext_keyword_as_ident) - << Tok.getIdentifierInfo()->getName() << 0; - goto ParseIdentifier; - } - LLVM_FALLTHROUGH; - default: - return ParseExprStatement(StmtCtx); - } + return ParseExprStatement(StmtCtx); } case tok::kw___attribute: { diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index 9cd405a..8f45584 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -161,9 +161,7 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() { [[fallthrough]]; case tok::kw_typeof: case tok::kw___attribute: -#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait: -#include "clang/Basic/TransformTypeTraits.def" - { + case tok::kw___underlying_type: { ConsumeToken(); if (Tok.isNot(tok::l_paren)) return TPResult::Error; @@ -1684,8 +1682,8 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, return TPResult::True; } -#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait: -#include "clang/Basic/TransformTypeTraits.def" + // C++0x type traits support + case tok::kw___underlying_type: return TPResult::True; // C11 _Atomic @@ -1723,8 +1721,7 @@ bool Parser::isCXXDeclarationSpecifierAType() { case tok::annot_template_id: case tok::annot_typename: case tok::kw_typeof: -#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait: -#include "clang/Basic/TransformTypeTraits.def" + case tok::kw___underlying_type: return true; // elaborated-type-specifier diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index af31105..d4dc790 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -18,7 +18,6 @@ #include "clang/AST/TypeLoc.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceManager.h" -#include "clang/Basic/Specifiers.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Sema.h" @@ -390,8 +389,7 @@ bool Declarator::isDeclarationOfFunction() const { return E->getType()->isFunctionType(); return false; -#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case TST_##Trait: -#include "clang/Basic/TransformTypeTraits.def" + case TST_underlyingType: case TST_typename: case TST_typeofType: { QualType QT = DS.getRepAsType().get(); @@ -578,10 +576,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T, case DeclSpec::TST_auto_type: return "__auto_type"; case DeclSpec::TST_decltype: return "(decltype)"; case DeclSpec::TST_decltype_auto: return "decltype(auto)"; -#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \ - case DeclSpec::TST_##Trait: \ - return "__" #Trait; -#include "clang/Basic/TransformTypeTraits.def" + case DeclSpec::TST_underlyingType: return "__underlying_type"; case DeclSpec::TST_unknown_anytype: return "__unknown_anytype"; case DeclSpec::TST_atomic: return "_Atomic"; case DeclSpec::TST_BFloat16: return "__bf16"; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index e689a05..94009d3 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -145,8 +145,7 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const { case tok::kw___ibm128: case tok::kw_wchar_t: case tok::kw_bool: -#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait: -#include "clang/Basic/TransformTypeTraits.def" + case tok::kw___underlying_type: case tok::kw___auto_type: return true; @@ -5924,8 +5923,7 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D, switch (DS.getTypeSpecType()) { case DeclSpec::TST_typename: case DeclSpec::TST_typeofType: -#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case DeclSpec::TST_##Trait: -#include "clang/Basic/TransformTypeTraits.def" + case DeclSpec::TST_underlyingType: case DeclSpec::TST_atomic: { // Grab the type from the parser. TypeSourceInfo *TSI = nullptr; diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index 285bf67..790792f 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -858,8 +858,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { switch (DS.getTypeSpecType()) { case TST_typename: case TST_typeofType: -#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case TST_##Trait: -#include "clang/Basic/TransformTypeTraits.def" + case TST_underlyingType: case TST_atomic: { QualType T = DS.getRepAsType().get(); if (!T.isNull() && T->containsUnexpandedParameterPack()) diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index fb339fa..14b2d2e 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -19,11 +19,9 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" -#include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeLocVisitor.h" #include "clang/Basic/PartialDiagnostic.h" -#include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" @@ -35,7 +33,6 @@ #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "clang/Sema/TemplateInstCallback.h" -#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" @@ -1250,18 +1247,6 @@ getImageAccess(const ParsedAttributesView &Attrs) { return OpenCLAccessAttr::Keyword_read_only; } -static UnaryTransformType::UTTKind -TSTToUnaryTransformType(DeclSpec::TST SwitchTST) { - switch (SwitchTST) { -#define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait) \ - case TST_##Trait: \ - return UnaryTransformType::Enum; -#include "clang/Basic/TransformTypeTraits.def" - default: - llvm_unreachable("attempted to parse a non-unary transform builtin"); - } -} - /// Convert the specified declspec to the appropriate type /// object. /// \param state Specifies the declarator containing the declaration specifier @@ -1643,13 +1628,12 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { } break; } -#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case DeclSpec::TST_##Trait: -#include "clang/Basic/TransformTypeTraits.def" + case DeclSpec::TST_underlyingType: Result = S.GetTypeFromParser(DS.getRepAsType()); - assert(!Result.isNull() && "Didn't get a type for the transformation?"); - Result = S.BuildUnaryTransformType( - Result, TSTToUnaryTransformType(DS.getTypeSpecType()), - DS.getTypeSpecTypeLoc()); + assert(!Result.isNull() && "Didn't get a type for __underlying_type?"); + Result = S.BuildUnaryTransformType(Result, + UnaryTransformType::EnumUnderlyingType, + DS.getTypeSpecTypeLoc()); if (Result.isNull()) { Result = Context.IntTy; declarator.setInvalidType(true); @@ -6083,7 +6067,8 @@ namespace { TL.setRParenLoc(DS.getTypeofParensRange().getEnd()); } void VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) { - assert(DS.isTransformTypeTrait(DS.getTypeSpecType())); + // FIXME: This holds only because we only have one unary transform. + assert(DS.getTypeSpecType() == DeclSpec::TST_underlyingType); TL.setKWLoc(DS.getTypeSpecTypeLoc()); TL.setParensRange(DS.getTypeofParensRange()); assert(DS.getRepAsType()); @@ -9220,257 +9205,39 @@ QualType Sema::BuildDecltypeType(Expr *E, bool AsUnevaluated) { return Context.getDecltypeType(E, getDecltypeForExpr(E)); } -static QualType GetEnumUnderlyingType(Sema &S, QualType BaseType, - SourceLocation Loc) { - assert(BaseType->isEnumeralType()); - EnumDecl *ED = BaseType->castAs<EnumType>()->getDecl(); - assert(ED && "EnumType has no EnumDecl"); - - S.DiagnoseUseOfDecl(ED, Loc); - - QualType Underlying = ED->getIntegerType(); - assert(!Underlying.isNull()); - - return Underlying; -} - -QualType Sema::BuiltinEnumUnderlyingType(QualType BaseType, - SourceLocation Loc) { - if (!BaseType->isEnumeralType()) { - Diag(Loc, diag::err_only_enums_have_underlying_types); - return QualType(); - } - - // The enum could be incomplete if we're parsing its definition or - // recovering from an error. - NamedDecl *FwdDecl = nullptr; - if (BaseType->isIncompleteType(&FwdDecl)) { - Diag(Loc, diag::err_underlying_type_of_incomplete_enum) << BaseType; - Diag(FwdDecl->getLocation(), diag::note_forward_declaration) << FwdDecl; - return QualType(); - } - - return GetEnumUnderlyingType(*this, BaseType, Loc); -} - -QualType Sema::BuiltinAddPointer(QualType BaseType, SourceLocation Loc) { - QualType Pointer = BaseType.isReferenceable() || BaseType->isVoidType() - ? BuildPointerType(BaseType.getNonReferenceType(), Loc, - DeclarationName()) - : BaseType; - - return Pointer.isNull() ? QualType() : Pointer; -} - -QualType Sema::BuiltinRemovePointer(QualType BaseType, SourceLocation Loc) { - // We don't want block pointers or ObjectiveC's id type. - if (!BaseType->isAnyPointerType() || BaseType->isObjCIdType()) - return BaseType; - - return BaseType->getPointeeType(); -} - -QualType Sema::BuiltinDecay(QualType BaseType, SourceLocation Loc) { - QualType Underlying = BaseType.getNonReferenceType(); - if (Underlying->isArrayType()) - return Context.getDecayedType(Underlying); - - if (Underlying->isFunctionType()) - return BuiltinAddPointer(BaseType, Loc); - - SplitQualType Split = Underlying.getSplitUnqualifiedType(); - // std::decay is supposed to produce 'std::remove_cv', but since 'restrict' is - // in the same group of qualifiers as 'const' and 'volatile', we're extending - // '__decay(T)' so that it removes all qualifiers. - Split.Quals.removeCVRQualifiers(); - return Context.getQualifiedType(Split); -} - -QualType Sema::BuiltinAddReference(QualType BaseType, UTTKind UKind, - SourceLocation Loc) { - assert(LangOpts.CPlusPlus); - QualType Reference = - BaseType.isReferenceable() - ? BuildReferenceType(BaseType, - UKind == UnaryTransformType::AddLvalueReference, - Loc, DeclarationName()) - : BaseType; - return Reference.isNull() ? QualType() : Reference; -} - -QualType Sema::BuiltinRemoveExtent(QualType BaseType, UTTKind UKind, - SourceLocation Loc) { - if (UKind == UnaryTransformType::RemoveAllExtents) - return Context.getBaseElementType(BaseType); - - if (const auto *AT = Context.getAsArrayType(BaseType)) - return AT->getElementType(); - - return BaseType; -} - -QualType Sema::BuiltinRemoveReference(QualType BaseType, UTTKind UKind, - SourceLocation Loc) { - assert(LangOpts.CPlusPlus); - QualType T = BaseType.getNonReferenceType(); - if (UKind == UTTKind::RemoveCVRef && - (T.isConstQualified() || T.isVolatileQualified())) { - Qualifiers Quals; - QualType Unqual = Context.getUnqualifiedArrayType(T, Quals); - Quals.removeConst(); - Quals.removeVolatile(); - T = Context.getQualifiedType(Unqual, Quals); - } - return T; -} - -QualType Sema::BuiltinChangeCVRQualifiers(QualType BaseType, UTTKind UKind, - SourceLocation Loc) { - if ((BaseType->isReferenceType() && UKind != UTTKind::RemoveRestrict) || - BaseType->isFunctionType()) - return BaseType; - - Qualifiers Quals; - QualType Unqual = Context.getUnqualifiedArrayType(BaseType, Quals); - - if (UKind == UTTKind::RemoveConst || UKind == UTTKind::RemoveCV) - Quals.removeConst(); - if (UKind == UTTKind::RemoveVolatile || UKind == UTTKind::RemoveCV) - Quals.removeVolatile(); - if (UKind == UTTKind::RemoveRestrict) - Quals.removeRestrict(); - - return Context.getQualifiedType(Unqual, Quals); -} - -static QualType ChangeIntegralSignedness(Sema &S, QualType BaseType, - bool IsMakeSigned, - SourceLocation Loc) { - if (BaseType->isEnumeralType()) { - QualType Underlying = GetEnumUnderlyingType(S, BaseType, Loc); - if (auto *BitInt = dyn_cast<BitIntType>(Underlying)) { - unsigned int Bits = BitInt->getNumBits(); - if (Bits > 1) - return S.Context.getBitIntType(!IsMakeSigned, Bits); - - S.Diag(Loc, diag::err_make_signed_integral_only) - << IsMakeSigned << /*_BitInt(1)*/ true << BaseType << 1 << Underlying; - return QualType(); - } - if (Underlying->isBooleanType()) { - S.Diag(Loc, diag::err_make_signed_integral_only) - << IsMakeSigned << /*_BitInt(1)*/ false << BaseType << 1 - << Underlying; - return QualType(); - } - } - - bool Int128Unsupported = !S.Context.getTargetInfo().hasInt128Type(); - std::array<CanQualType *, 6> AllSignedIntegers = { - &S.Context.SignedCharTy, &S.Context.ShortTy, &S.Context.IntTy, - &S.Context.LongTy, &S.Context.LongLongTy, &S.Context.Int128Ty}; - ArrayRef<CanQualType *> AvailableSignedIntegers( - AllSignedIntegers.begin(), AllSignedIntegers.end() - Int128Unsupported); - std::array<CanQualType *, 6> AllUnsignedIntegers = { - &S.Context.UnsignedCharTy, &S.Context.UnsignedShortTy, - &S.Context.UnsignedIntTy, &S.Context.UnsignedLongTy, - &S.Context.UnsignedLongLongTy, &S.Context.UnsignedInt128Ty}; - ArrayRef<CanQualType *> AvailableUnsignedIntegers(AllUnsignedIntegers.begin(), - AllUnsignedIntegers.end() - - Int128Unsupported); - ArrayRef<CanQualType *> *Consider = - IsMakeSigned ? &AvailableSignedIntegers : &AvailableUnsignedIntegers; - - uint64_t BaseSize = S.Context.getTypeSize(BaseType); - auto *Result = - llvm::find_if(*Consider, [&S, BaseSize](const CanQual<Type> *T) { - return BaseSize == S.Context.getTypeSize(T->getTypePtr()); - }); - - assert(Result != Consider->end()); - return QualType((*Result)->getTypePtr(), 0); -} - -QualType Sema::BuiltinChangeSignedness(QualType BaseType, UTTKind UKind, +QualType Sema::BuildUnaryTransformType(QualType BaseType, + UnaryTransformType::UTTKind UKind, SourceLocation Loc) { - bool IsMakeSigned = UKind == UnaryTransformType::MakeSigned; - if ((!BaseType->isIntegerType() && !BaseType->isEnumeralType()) || - BaseType->isBooleanType() || - (BaseType->isBitIntType() && - BaseType->getAs<BitIntType>()->getNumBits() < 2)) { - Diag(Loc, diag::err_make_signed_integral_only) - << IsMakeSigned << BaseType->isBitIntType() << BaseType << 0; - return QualType(); - } + switch (UKind) { + case UnaryTransformType::EnumUnderlyingType: + if (!BaseType->isDependentType() && !BaseType->isEnumeralType()) { + Diag(Loc, diag::err_only_enums_have_underlying_types); + return QualType(); + } else { + QualType Underlying = BaseType; + if (!BaseType->isDependentType()) { + // The enum could be incomplete if we're parsing its definition or + // recovering from an error. + NamedDecl *FwdDecl = nullptr; + if (BaseType->isIncompleteType(&FwdDecl)) { + Diag(Loc, diag::err_underlying_type_of_incomplete_enum) << BaseType; + Diag(FwdDecl->getLocation(), diag::note_forward_declaration) << FwdDecl; + return QualType(); + } - bool IsNonIntIntegral = - BaseType->isChar16Type() || BaseType->isChar32Type() || - BaseType->isWideCharType() || BaseType->isEnumeralType(); + EnumDecl *ED = BaseType->castAs<EnumType>()->getDecl(); + assert(ED && "EnumType has no EnumDecl"); - QualType Underlying = - IsNonIntIntegral - ? ChangeIntegralSignedness(*this, BaseType, IsMakeSigned, Loc) - : IsMakeSigned ? Context.getCorrespondingSignedType(BaseType) - : Context.getCorrespondingUnsignedType(BaseType); - if (Underlying.isNull()) - return Underlying; - return Context.getQualifiedType(Underlying, BaseType.getQualifiers()); -} + DiagnoseUseOfDecl(ED, Loc); -QualType Sema::BuildUnaryTransformType(QualType BaseType, UTTKind UKind, - SourceLocation Loc) { - if (BaseType->isDependentType()) - return Context.getUnaryTransformType(BaseType, BaseType, UKind); - QualType Result; - switch (UKind) { - case UnaryTransformType::EnumUnderlyingType: { - Result = BuiltinEnumUnderlyingType(BaseType, Loc); - break; - } - case UnaryTransformType::AddPointer: { - Result = BuiltinAddPointer(BaseType, Loc); - break; - } - case UnaryTransformType::RemovePointer: { - Result = BuiltinRemovePointer(BaseType, Loc); - break; - } - case UnaryTransformType::Decay: { - Result = BuiltinDecay(BaseType, Loc); - break; - } - case UnaryTransformType::AddLvalueReference: - case UnaryTransformType::AddRvalueReference: { - Result = BuiltinAddReference(BaseType, UKind, Loc); - break; - } - case UnaryTransformType::RemoveAllExtents: - case UnaryTransformType::RemoveExtent: { - Result = BuiltinRemoveExtent(BaseType, UKind, Loc); - break; - } - case UnaryTransformType::RemoveCVRef: - case UnaryTransformType::RemoveReference: { - Result = BuiltinRemoveReference(BaseType, UKind, Loc); - break; - } - case UnaryTransformType::RemoveConst: - case UnaryTransformType::RemoveCV: - case UnaryTransformType::RemoveRestrict: - case UnaryTransformType::RemoveVolatile: { - Result = BuiltinChangeCVRQualifiers(BaseType, UKind, Loc); - break; - } - case UnaryTransformType::MakeSigned: - case UnaryTransformType::MakeUnsigned: { - Result = BuiltinChangeSignedness(BaseType, UKind, Loc); - break; - } + Underlying = ED->getIntegerType(); + assert(!Underlying.isNull()); + } + return Context.getUnaryTransformType(BaseType, Underlying, + UnaryTransformType::EnumUnderlyingType); + } } - - return !Result.isNull() - ? Context.getUnaryTransformType(BaseType, Result, UKind) - : Result; + llvm_unreachable("unknown unary transform type"); } QualType Sema::BuildAtomicType(QualType T, SourceLocation Loc) { |