diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 34 | ||||
-rw-r--r-- | clang/lib/AST/ASTImporter.cpp | 11 | ||||
-rw-r--r-- | clang/lib/AST/ASTStructuralEquivalence.cpp | 4 | ||||
-rw-r--r-- | clang/lib/AST/ODRHash.cpp | 2 | ||||
-rw-r--r-- | clang/lib/AST/Type.cpp | 24 | ||||
-rw-r--r-- | clang/lib/AST/TypeLoc.cpp | 4 | ||||
-rw-r--r-- | clang/lib/AST/TypePrinter.cpp | 6 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGDebugInfo.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 39 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExpr.cpp | 18 | ||||
-rw-r--r-- | clang/lib/Sema/DeclSpec.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateDeduction.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateVariadic.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 27 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 31 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 2 |
19 files changed, 148 insertions, 71 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 99ab66d..f264223 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -5581,30 +5581,31 @@ QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl, /// multiple declarations that refer to "typeof(x)" all contain different /// DeclRefExpr's. This doesn't effect the type checker, since it operates /// on canonical type's (which are always unique). -QualType ASTContext::getTypeOfExprType(Expr *tofExpr) const { +QualType ASTContext::getTypeOfExprType(Expr *tofExpr, TypeOfKind Kind) const { TypeOfExprType *toe; if (tofExpr->isTypeDependent()) { llvm::FoldingSetNodeID ID; - DependentTypeOfExprType::Profile(ID, *this, tofExpr); + DependentTypeOfExprType::Profile(ID, *this, tofExpr, + Kind == TypeOfKind::Unqualified); void *InsertPos = nullptr; - DependentTypeOfExprType *Canon - = DependentTypeOfExprTypes.FindNodeOrInsertPos(ID, InsertPos); + DependentTypeOfExprType *Canon = + DependentTypeOfExprTypes.FindNodeOrInsertPos(ID, InsertPos); if (Canon) { // We already have a "canonical" version of an identical, dependent // typeof(expr) type. Use that as our canonical type. - toe = new (*this, TypeAlignment) TypeOfExprType(tofExpr, - QualType((TypeOfExprType*)Canon, 0)); + toe = new (*this, TypeAlignment) + TypeOfExprType(tofExpr, Kind, QualType((TypeOfExprType *)Canon, 0)); } else { // Build a new, canonical typeof(expr) type. - Canon - = new (*this, TypeAlignment) DependentTypeOfExprType(*this, tofExpr); + Canon = new (*this, TypeAlignment) + DependentTypeOfExprType(*this, tofExpr, Kind); DependentTypeOfExprTypes.InsertNode(Canon, InsertPos); toe = Canon; } } else { QualType Canonical = getCanonicalType(tofExpr->getType()); - toe = new (*this, TypeAlignment) TypeOfExprType(tofExpr, Canonical); + toe = new (*this, TypeAlignment) TypeOfExprType(tofExpr, Kind, Canonical); } Types.push_back(toe); return QualType(toe, 0); @@ -5615,9 +5616,10 @@ QualType ASTContext::getTypeOfExprType(Expr *tofExpr) const { /// memory savings. Since typeof(t) is fairly uncommon, space shouldn't be /// an issue. This doesn't affect the type checker, since it operates /// on canonical types (which are always unique). -QualType ASTContext::getTypeOfType(QualType tofType) const { +QualType ASTContext::getTypeOfType(QualType tofType, TypeOfKind Kind) const { QualType Canonical = getCanonicalType(tofType); - auto *tot = new (*this, TypeAlignment) TypeOfType(tofType, Canonical); + auto *tot = + new (*this, TypeAlignment) TypeOfType(tofType, Canonical, Kind); Types.push_back(tot); return QualType(tot, 0); } @@ -12936,7 +12938,15 @@ static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X, return Ctx.getTypedefType(CD, Ctx.getQualifiedType(Underlying)); } case Type::TypeOf: - return Ctx.getTypeOfType(Ctx.getQualifiedType(Underlying)); + // The common sugar between two typeof expressions, where one is + // potentially a typeof_unqual and the other is not, we unify to the + // qualified type as that retains the most information along with the type. + // We only return a typeof_unqual type when both types are unqual types. + return Ctx.getTypeOfType(Ctx.getQualifiedType(Underlying), + cast<TypeOfType>(X)->isUnqual() && + cast<TypeOfType>(Y)->isUnqual() + ? TypeOfKind::Unqualified + : TypeOfKind::Qualified); case Type::TypeOfExpr: return QualType(); diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 31a2efd..7ab425d 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -1370,16 +1370,17 @@ ExpectedType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) { ExpectedExpr ToExprOrErr = import(T->getUnderlyingExpr()); if (!ToExprOrErr) return ToExprOrErr.takeError(); - - return Importer.getToContext().getTypeOfExprType(*ToExprOrErr); + return Importer.getToContext().getTypeOfExprType( + *ToExprOrErr, + T->isUnqual() ? TypeOfKind::Unqualified : TypeOfKind::Qualified); } ExpectedType ASTNodeImporter::VisitTypeOfType(const TypeOfType *T) { - ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType()); + ExpectedType ToUnderlyingTypeOrErr = import(T->getUnmodifiedType()); if (!ToUnderlyingTypeOrErr) return ToUnderlyingTypeOrErr.takeError(); - - return Importer.getToContext().getTypeOfType(*ToUnderlyingTypeOrErr); + return Importer.getToContext().getTypeOfType(*ToUnderlyingTypeOrErr, + T->isUnqual() ? TypeOfKind::Unqualified : TypeOfKind::Qualified); } ExpectedType ASTNodeImporter::VisitUsingType(const UsingType *T) { diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index 7e6055d..8f2ecee 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -974,8 +974,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, case Type::TypeOf: if (!IsStructurallyEquivalent(Context, - cast<TypeOfType>(T1)->getUnderlyingType(), - cast<TypeOfType>(T2)->getUnderlyingType())) + cast<TypeOfType>(T1)->getUnmodifiedType(), + cast<TypeOfType>(T2)->getUnmodifiedType())) return false; break; diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index 51f8064..de46b40 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -1061,7 +1061,7 @@ public: VisitType(T); } void VisitTypeOfType(const TypeOfType *T) { - AddQualType(T->getUnderlyingType()); + AddQualType(T->getUnmodifiedType()); VisitType(T); } diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 96028f3..787d88b 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -3469,27 +3469,37 @@ QualType MacroQualifiedType::getModifiedType() const { return Inner; } -TypeOfExprType::TypeOfExprType(Expr *E, QualType can) - : Type(TypeOfExpr, can, +TypeOfExprType::TypeOfExprType(Expr *E, TypeOfKind Kind, QualType Can) + : Type(TypeOfExpr, + // We have to protect against 'Can' being invalid through its + // default argument. + Kind == TypeOfKind::Unqualified && !Can.isNull() + ? Can.getAtomicUnqualifiedType() + : Can, toTypeDependence(E->getDependence()) | (E->getType()->getDependence() & TypeDependence::VariablyModified)), - TOExpr(E) {} + TOExpr(E) { + TypeOfBits.IsUnqual = Kind == TypeOfKind::Unqualified; +} bool TypeOfExprType::isSugared() const { return !TOExpr->isTypeDependent(); } QualType TypeOfExprType::desugar() const { - if (isSugared()) - return getUnderlyingExpr()->getType(); - + if (isSugared()) { + QualType QT = getUnderlyingExpr()->getType(); + return isUnqual() ? QT.getAtomicUnqualifiedType() : QT; + } return QualType(this, 0); } void DependentTypeOfExprType::Profile(llvm::FoldingSetNodeID &ID, - const ASTContext &Context, Expr *E) { + const ASTContext &Context, Expr *E, + bool IsUnqual) { E->Profile(ID, Context, true); + ID.AddBoolean(IsUnqual); } DecltypeType::DecltypeType(Expr *E, QualType underlyingType, QualType can) diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp index 540634c..99566b4 100644 --- a/clang/lib/AST/TypeLoc.cpp +++ b/clang/lib/AST/TypeLoc.cpp @@ -521,8 +521,8 @@ void TypeOfTypeLoc::initializeLocal(ASTContext &Context, SourceLocation Loc) { TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo> ::initializeLocal(Context, Loc); - this->getLocalData()->UnderlyingTInfo = Context.getTrivialTypeSourceInfo( - getUnderlyingType(), Loc); + this->getLocalData()->UnmodifiedTInfo = + Context.getTrivialTypeSourceInfo(getUnmodifiedType(), Loc); } void UnaryTransformTypeLoc::initializeLocal(ASTContext &Context, diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index a7da9fd..c033b35 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -1110,7 +1110,7 @@ void TypePrinter::printTypedefAfter(const TypedefType *T, raw_ostream &OS) {} void TypePrinter::printTypeOfExprBefore(const TypeOfExprType *T, raw_ostream &OS) { - OS << "typeof "; + OS << (T->isUnqual() ? "typeof_unqual " : "typeof "); if (T->getUnderlyingExpr()) T->getUnderlyingExpr()->printPretty(OS, nullptr, Policy); spaceBeforePlaceHolder(OS); @@ -1120,8 +1120,8 @@ void TypePrinter::printTypeOfExprAfter(const TypeOfExprType *T, raw_ostream &OS) {} void TypePrinter::printTypeOfBefore(const TypeOfType *T, raw_ostream &OS) { - OS << "typeof("; - print(T->getUnderlyingType(), OS, StringRef()); + OS << (T->isUnqual() ? "typeof_unqual(" : "typeof("); + print(T->getUnmodifiedType(), OS, StringRef()); OS << ')'; spaceBeforePlaceHolder(OS); } diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 6302741..35432fa 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -3287,7 +3287,7 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) { T = cast<TypeOfExprType>(T)->getUnderlyingExpr()->getType(); break; case Type::TypeOf: - T = cast<TypeOfType>(T)->getUnderlyingType(); + T = cast<TypeOfType>(T)->getUnmodifiedType(); break; case Type::Decltype: T = cast<DecltypeType>(T)->getUnderlyingType(); diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 9363827..dfedbf5 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -4241,8 +4241,9 @@ void Parser::ParseDeclarationSpecifiers( continue; break; - // GNU typeof support. + // C2x/GNU typeof support. case tok::kw_typeof: + case tok::kw_typeof_unqual: ParseTypeofSpecifier(DS); continue; @@ -5252,8 +5253,9 @@ bool Parser::isTypeSpecifierQualifier() { // GNU attributes support. case tok::kw___attribute: - // GNU typeof support. + // C2x/GNU typeof support. case tok::kw_typeof: + case tok::kw_typeof_unqual: // type-specifiers case tok::kw_short: @@ -5495,8 +5497,9 @@ bool Parser::isDeclarationSpecifier( case tok::kw_static_assert: case tok::kw__Static_assert: - // GNU typeof support. + // C2x/GNU typeof support. case tok::kw_typeof: + case tok::kw_typeof_unqual: // GNU attributes. case tok::kw___attribute: @@ -7543,13 +7546,27 @@ void Parser::ParseMisplacedBracketDeclarator(Declarator &D) { /// typeof ( expressions ) /// typeof ( type-name ) /// [GNU/C++] typeof unary-expression +/// [C2x] typeof-specifier: +/// typeof '(' typeof-specifier-argument ')' +/// typeof_unqual '(' typeof-specifier-argument ')' +/// +/// typeof-specifier-argument: +/// expression +/// type-name /// void Parser::ParseTypeofSpecifier(DeclSpec &DS) { - assert(Tok.is(tok::kw_typeof) && "Not a typeof specifier"); + assert(Tok.isOneOf(tok::kw_typeof, tok::kw_typeof_unqual) && + "Not a typeof specifier"); + + bool IsUnqual = Tok.is(tok::kw_typeof_unqual); + const IdentifierInfo *II = Tok.getIdentifierInfo(); + if (getLangOpts().C2x && !II->getName().startswith("__")) + Diag(Tok.getLocation(), diag::warn_c2x_compat_typeof_type_specifier) + << IsUnqual; + Token OpTok = Tok; SourceLocation StartLoc = ConsumeToken(); - - const bool hasParens = Tok.is(tok::l_paren); + bool HasParens = Tok.is(tok::l_paren); EnterExpressionEvaluationContext Unevaluated( Actions, Sema::ExpressionEvaluationContext::Unevaluated, @@ -7560,7 +7577,7 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) { SourceRange CastRange; ExprResult Operand = Actions.CorrectDelayedTyposInExpr( ParseExprAfterUnaryExprOrTypeTrait(OpTok, isCastExpr, CastTy, CastRange)); - if (hasParens) + if (HasParens) DS.setTypeArgumentRange(CastRange); if (CastRange.getEnd().isInvalid()) @@ -7578,7 +7595,9 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) { const char *PrevSpec = nullptr; unsigned DiagID; // Check for duplicate type specifiers (e.g. "int typeof(int)"). - if (DS.SetTypeSpecType(DeclSpec::TST_typeofType, StartLoc, PrevSpec, + if (DS.SetTypeSpecType(IsUnqual ? DeclSpec::TST_typeof_unqualType + : DeclSpec::TST_typeofType, + StartLoc, PrevSpec, DiagID, CastTy, Actions.getASTContext().getPrintingPolicy())) Diag(StartLoc, DiagID) << PrevSpec; @@ -7601,7 +7620,9 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) { const char *PrevSpec = nullptr; unsigned DiagID; // Check for duplicate type specifiers (e.g. "int typeof(int)"). - if (DS.SetTypeSpecType(DeclSpec::TST_typeofExpr, StartLoc, PrevSpec, + if (DS.SetTypeSpecType(IsUnqual ? DeclSpec::TST_typeof_unqualExpr + : DeclSpec::TST_typeofExpr, + StartLoc, PrevSpec, DiagID, Operand.get(), Actions.getASTContext().getPrintingPolicy())) Diag(StartLoc, DiagID) << PrevSpec; diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 8209aff..89d3b3e 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -2288,6 +2288,13 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { /// typeof ( expressions ) /// typeof ( type-name ) /// [GNU/C++] typeof unary-expression +/// [C2x] typeof-specifier: +/// typeof '(' typeof-specifier-argument ')' +/// typeof_unqual '(' typeof-specifier-argument ')' +/// +/// typeof-specifier-argument: +/// expression +/// type-name /// /// [OpenCL 1.1 6.11.12] vec_step built-in function: /// vec_step ( expressions ) @@ -2299,8 +2306,9 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, ParsedType &CastTy, SourceRange &CastRange) { - assert(OpTok.isOneOf(tok::kw_typeof, tok::kw_sizeof, tok::kw___alignof, - tok::kw_alignof, tok::kw__Alignof, tok::kw_vec_step, + assert(OpTok.isOneOf(tok::kw_typeof, tok::kw_typeof_unqual, tok::kw_sizeof, + tok::kw___alignof, tok::kw_alignof, tok::kw__Alignof, + tok::kw_vec_step, tok::kw___builtin_omp_required_simd_align) && "Not a typeof/sizeof/alignof/vec_step expression!"); @@ -2336,7 +2344,8 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, } isCastExpr = false; - if (OpTok.is(tok::kw_typeof) && !getLangOpts().CPlusPlus) { + if (OpTok.isOneOf(tok::kw_typeof, tok::kw_typeof_unqual) && + !getLangOpts().CPlusPlus) { Diag(Tok, diag::err_expected_after) << OpTok.getIdentifierInfo() << tok::l_paren; return ExprError(); @@ -2362,7 +2371,8 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, return ExprEmpty(); } - if (getLangOpts().CPlusPlus || OpTok.isNot(tok::kw_typeof)) { + if (getLangOpts().CPlusPlus || + !OpTok.isOneOf(tok::kw_typeof, tok::kw_typeof_unqual)) { // GNU typeof in C requires the expression to be parenthesized. Not so for // sizeof/alignof or in C++. Therefore, the parenthesized expression is // the start of a unary-expression, but doesn't include any postfix diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index 0c4b79d..dc6a1ef 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -384,6 +384,7 @@ bool Declarator::isDeclarationOfFunction() const { return false; case TST_decltype: + case TST_typeof_unqualExpr: case TST_typeofExpr: if (Expr *E = DS.getRepAsExpr()) return E->getType()->isFunctionType(); @@ -392,6 +393,7 @@ bool Declarator::isDeclarationOfFunction() const { #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case TST_##Trait: #include "clang/Basic/TransformTypeTraits.def" case TST_typename: + case TST_typeof_unqualType: case TST_typeofType: { QualType QT = DS.getRepAsType().get(); if (QT.isNull()) @@ -573,6 +575,8 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T, case DeclSpec::TST_typename: return "type-name"; case DeclSpec::TST_typeofType: case DeclSpec::TST_typeofExpr: return "typeof"; + case DeclSpec::TST_typeof_unqualType: + case DeclSpec::TST_typeof_unqualExpr: return "typeof_unqual"; case DeclSpec::TST_auto: return "auto"; case DeclSpec::TST_auto_type: return "__auto_type"; case DeclSpec::TST_decltype: return "(decltype)"; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 77d9516..6c7df68 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -5939,6 +5939,7 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D, switch (DS.getTypeSpecType()) { case DeclSpec::TST_typename: case DeclSpec::TST_typeofType: + case DeclSpec::TST_typeof_unqualType: #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case DeclSpec::TST_##Trait: #include "clang/Basic/TransformTypeTraits.def" case DeclSpec::TST_atomic: { @@ -5964,6 +5965,7 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D, } case DeclSpec::TST_decltype: + case DeclSpec::TST_typeof_unqualExpr: case DeclSpec::TST_typeofExpr: { Expr *E = DS.getRepAsExpr(); ExprResult Result = S.RebuildExprInCurrentInstantiation(E); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index e2040f8..8223bb3d 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -6257,7 +6257,7 @@ bool UnnamedLocalNoLinkageFinder::VisitTypeOfExprType(const TypeOfExprType*) { } bool UnnamedLocalNoLinkageFinder::VisitTypeOfType(const TypeOfType* T) { - return Visit(T->getUnderlyingType()); + return Visit(T->getUnmodifiedType()); } bool UnnamedLocalNoLinkageFinder::VisitDecltypeType(const DecltypeType*) { diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 9f1942a..36f6333 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -5987,8 +5987,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, case Type::TypeOf: if (!OnlyDeduced) - MarkUsedTemplateParameters(Ctx, - cast<TypeOfType>(T)->getUnderlyingType(), + MarkUsedTemplateParameters(Ctx, cast<TypeOfType>(T)->getUnmodifiedType(), OnlyDeduced, Depth, Used); break; diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index 69e0c70..4915b48 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -863,6 +863,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { const DeclSpec &DS = D.getDeclSpec(); switch (DS.getTypeSpecType()) { case TST_typename: + case TST_typeof_unqualType: case TST_typeofType: #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case TST_##Trait: #include "clang/Basic/TransformTypeTraits.def" @@ -873,6 +874,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { break; } + case TST_typeof_unqualExpr: case TST_typeofExpr: case TST_decltype: case TST_bitint: diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index aa3160c..3e34408 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1610,6 +1610,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // TypeQuals handled by caller. break; } + case DeclSpec::TST_typeof_unqualType: case DeclSpec::TST_typeofType: // FIXME: Preserve type source info. Result = S.GetTypeFromParser(DS.getRepAsType()); @@ -1618,13 +1619,20 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { if (const TagType *TT = Result->getAs<TagType>()) S.DiagnoseUseOfDecl(TT->getDecl(), DS.getTypeSpecTypeLoc()); // TypeQuals handled by caller. - Result = Context.getTypeOfType(Result); + Result = Context.getTypeOfType( + Result, DS.getTypeSpecType() == DeclSpec::TST_typeof_unqualType + ? TypeOfKind::Unqualified + : TypeOfKind::Qualified); break; + case DeclSpec::TST_typeof_unqualExpr: case DeclSpec::TST_typeofExpr: { Expr *E = DS.getRepAsExpr(); assert(E && "Didn't get an expression for typeof?"); // TypeQuals handled by caller. - Result = S.BuildTypeofExprType(E); + Result = S.BuildTypeofExprType(E, DS.getTypeSpecType() == + DeclSpec::TST_typeof_unqualExpr + ? TypeOfKind::Unqualified + : TypeOfKind::Qualified); if (Result.isNull()) { Result = Context.IntTy; declarator.setInvalidType(true); @@ -6103,18 +6111,20 @@ namespace { } void VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) { - assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr); + assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr || + DS.getTypeSpecType() == DeclSpec::TST_typeof_unqualExpr); TL.setTypeofLoc(DS.getTypeSpecTypeLoc()); TL.setParensRange(DS.getTypeofParensRange()); } void VisitTypeOfTypeLoc(TypeOfTypeLoc TL) { - assert(DS.getTypeSpecType() == DeclSpec::TST_typeofType); + assert(DS.getTypeSpecType() == DeclSpec::TST_typeofType || + DS.getTypeSpecType() == DeclSpec::TST_typeof_unqualType); TL.setTypeofLoc(DS.getTypeSpecTypeLoc()); TL.setParensRange(DS.getTypeofParensRange()); assert(DS.getRepAsType()); TypeSourceInfo *TInfo = nullptr; Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); - TL.setUnderlyingTInfo(TInfo); + TL.setUnmodifiedTInfo(TInfo); } void VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { assert(DS.getTypeSpecType() == DeclSpec::TST_decltype); @@ -9163,18 +9173,19 @@ QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword, Keyword, SS.isValid() ? SS.getScopeRep() : nullptr, T, OwnedTagDecl); } -QualType Sema::BuildTypeofExprType(Expr *E) { +QualType Sema::BuildTypeofExprType(Expr *E, TypeOfKind Kind) { assert(!E->hasPlaceholderType() && "unexpected placeholder"); if (!getLangOpts().CPlusPlus && E->refersToBitField()) - Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield) << 2; + Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield) + << (Kind == TypeOfKind::Unqualified ? 3 : 2); if (!E->isTypeDependent()) { QualType T = E->getType(); if (const TagType *TT = T->getAs<TagType>()) DiagnoseUseOfDecl(TT->getDecl(), E->getExprLoc()); } - return Context.getTypeOfExprType(E); + return Context.getTypeOfExprType(E, Kind); } /// getDecltypeForExpr - Given an expr, will return the decltype for diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index feb31a8..e6109d6 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -963,12 +963,13 @@ public: /// /// By default, performs semantic analysis when building the typeof type. /// Subclasses may override this routine to provide different behavior. - QualType RebuildTypeOfExprType(Expr *Underlying, SourceLocation Loc); + QualType RebuildTypeOfExprType(Expr *Underlying, SourceLocation Loc, + TypeOfKind Kind); /// Build a new typeof(type) type. /// /// By default, builds a new TypeOfType with the given underlying type. - QualType RebuildTypeOfType(QualType Underlying); + QualType RebuildTypeOfType(QualType Underlying, TypeOfKind Kind); /// Build a new unary transform type. QualType RebuildUnaryTransformType(QualType BaseType, @@ -6199,13 +6200,15 @@ QualType TreeTransform<Derived>::TransformTypeOfExprType(TypeLocBuilder &TLB, return QualType(); QualType Result = TL.getType(); + bool IsUnqual = Result->getAs<TypeOfExprType>()->isUnqual(); if (getDerived().AlwaysRebuild() || E.get() != TL.getUnderlyingExpr()) { - Result = getDerived().RebuildTypeOfExprType(E.get(), TL.getTypeofLoc()); + Result = getDerived().RebuildTypeOfExprType( + E.get(), TL.getTypeofLoc(), + IsUnqual ? TypeOfKind::Unqualified : TypeOfKind::Qualified); if (Result.isNull()) return QualType(); } - else E.get(); TypeOfExprTypeLoc NewTL = TLB.push<TypeOfExprTypeLoc>(Result); NewTL.setTypeofLoc(TL.getTypeofLoc()); @@ -6218,14 +6221,17 @@ QualType TreeTransform<Derived>::TransformTypeOfExprType(TypeLocBuilder &TLB, template<typename Derived> QualType TreeTransform<Derived>::TransformTypeOfType(TypeLocBuilder &TLB, TypeOfTypeLoc TL) { - TypeSourceInfo* Old_Under_TI = TL.getUnderlyingTInfo(); + TypeSourceInfo* Old_Under_TI = TL.getUnmodifiedTInfo(); TypeSourceInfo* New_Under_TI = getDerived().TransformType(Old_Under_TI); if (!New_Under_TI) return QualType(); QualType Result = TL.getType(); + bool IsUnqual = Result->getAs<TypeOfType>()->isUnqual(); if (getDerived().AlwaysRebuild() || New_Under_TI != Old_Under_TI) { - Result = getDerived().RebuildTypeOfType(New_Under_TI->getType()); + Result = getDerived().RebuildTypeOfType(New_Under_TI->getType(), + IsUnqual ? TypeOfKind::Unqualified + : TypeOfKind::Qualified); if (Result.isNull()) return QualType(); } @@ -6234,7 +6240,7 @@ QualType TreeTransform<Derived>::TransformTypeOfType(TypeLocBuilder &TLB, NewTL.setTypeofLoc(TL.getTypeofLoc()); NewTL.setLParenLoc(TL.getLParenLoc()); NewTL.setRParenLoc(TL.getRParenLoc()); - NewTL.setUnderlyingTInfo(New_Under_TI); + NewTL.setUnmodifiedTInfo(New_Under_TI); return Result; } @@ -14719,14 +14725,15 @@ QualType TreeTransform<Derived>::RebuildUnresolvedUsingType(SourceLocation Loc, } template <typename Derived> -QualType TreeTransform<Derived>::RebuildTypeOfExprType(Expr *E, - SourceLocation) { - return SemaRef.BuildTypeofExprType(E); +QualType TreeTransform<Derived>::RebuildTypeOfExprType(Expr *E, SourceLocation, + TypeOfKind Kind) { + return SemaRef.BuildTypeofExprType(E, Kind); } template<typename Derived> -QualType TreeTransform<Derived>::RebuildTypeOfType(QualType Underlying) { - return SemaRef.Context.getTypeOfType(Underlying); +QualType TreeTransform<Derived>::RebuildTypeOfType(QualType Underlying, + TypeOfKind Kind) { + return SemaRef.Context.getTypeOfType(Underlying, Kind); } template <typename Derived> diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 5521a9b..7f2bee1 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -6662,7 +6662,7 @@ void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) { TL.setTypeofLoc(readSourceLocation()); TL.setLParenLoc(readSourceLocation()); TL.setRParenLoc(readSourceLocation()); - TL.setUnderlyingTInfo(GetTypeSourceInfo()); + TL.setUnmodifiedTInfo(GetTypeSourceInfo()); } void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 16d0bc7..c9c94d4 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -436,7 +436,7 @@ void TypeLocWriter::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) { addSourceLocation(TL.getTypeofLoc()); addSourceLocation(TL.getLParenLoc()); addSourceLocation(TL.getRParenLoc()); - Record.AddTypeSourceInfo(TL.getUnderlyingTInfo()); + Record.AddTypeSourceInfo(TL.getUnmodifiedTInfo()); } void TypeLocWriter::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { |