From: John McCall Date: Wed, 21 Oct 2009 00:40:46 +0000 (+0000) Subject: Rewrite TreeTransform to transform types as DeclaratorInfos rather than as bare X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a2becad14a0eb19cde2f441ced588b975433d2ed;p=clang Rewrite TreeTransform to transform types as DeclaratorInfos rather than as bare QualTypes. Don't actually exploit this yet. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84716 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 13014936a3..da7545c02d 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -4265,12 +4265,27 @@ namespace { /// \brief Transforms a typename type by determining whether the type now /// refers to a member of the current instantiation, and then /// type-checking and building a QualifiedNameType (when possible). - QualType TransformTypenameType(const TypenameType *T); + QualType TransformTypenameType(TypeLocBuilder &TLB, TypenameTypeLoc TL); + QualType TransformTypenameType(TypenameType *T); }; } QualType -CurrentInstantiationRebuilder::TransformTypenameType(const TypenameType *T) { +CurrentInstantiationRebuilder::TransformTypenameType(TypeLocBuilder &TLB, + TypenameTypeLoc TL) { + QualType Result = TransformTypenameType(TL.getTypePtr()); + if (Result.isNull()) + return QualType(); + + TypenameTypeLoc NewTL = TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); + + return Result; +} + +QualType +CurrentInstantiationRebuilder::TransformTypenameType(TypenameType *T) { + NestedNameSpecifier *NNS = TransformNestedNameSpecifier(T->getQualifier(), /*FIXME:*/SourceRange(getBaseLocation())); diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 75719b0de9..9b9fc00848 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -420,7 +420,8 @@ namespace { /// \brief Transforms a template type parameter type by performing /// substitution of the corresponding template type argument. - QualType TransformTemplateTypeParmType(const TemplateTypeParmType *T); + QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB, + TemplateTypeParmTypeLoc TL); }; } @@ -625,8 +626,9 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) { } QualType -TemplateInstantiator::TransformTemplateTypeParmType( - const TemplateTypeParmType *T) { +TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB, + TemplateTypeParmTypeLoc TL) { + TemplateTypeParmType *T = TL.getTypePtr(); if (T->getDepth() < TemplateArgs.getNumLevels()) { // Replace the template type parameter with its corresponding // template argument. @@ -635,8 +637,12 @@ TemplateInstantiator::TransformTemplateTypeParmType( // because we are performing instantiation from explicitly-specified // template arguments in a function template class, but there were some // arguments left unspecified. - if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex())) - return QualType(T, 0); + if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex())) { + TemplateTypeParmTypeLoc NewTL + = TLB.push(TL.getType()); + NewTL.setNameLoc(TL.getNameLoc()); + return TL.getType(); + } assert(TemplateArgs(T->getDepth(), T->getIndex()).getKind() == TemplateArgument::Type && @@ -646,18 +652,27 @@ TemplateInstantiator::TransformTemplateTypeParmType( = TemplateArgs(T->getDepth(), T->getIndex()).getAsType(); // TODO: only do this uniquing once, at the start of instantiation. - return getSema().Context.getSubstTemplateTypeParmType(T, Replacement); + QualType Result + = getSema().Context.getSubstTemplateTypeParmType(T, Replacement); + SubstTemplateTypeParmTypeLoc NewTL + = TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); + return Result; } // The template type parameter comes from an inner template (e.g., // the template parameter list of a member template inside the // template we are instantiating). Create a new template type // parameter with the template "level" reduced by one. - return getSema().Context.getTemplateTypeParmType( - T->getDepth() - TemplateArgs.getNumLevels(), - T->getIndex(), - T->isParameterPack(), - T->getName()); + QualType Result + = getSema().Context.getTemplateTypeParmType(T->getDepth() + - TemplateArgs.getNumLevels(), + T->getIndex(), + T->isParameterPack(), + T->getName()); + TemplateTypeParmTypeLoc NewTL = TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); + return Result; } /// \brief Perform substitution on the type T with a given set of template diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index fb0e2b1ae9..ee028b4127 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -1,4 +1,4 @@ -//===------- TreeTransform.h - Semantic Tree Transformation ---------------===/ +//===------- TreeTransform.h - Semantic Tree Transformation -----*- C++ -*-===/ // // The LLVM Compiler Infrastructure // @@ -22,9 +22,11 @@ #include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" +#include "clang/AST/TypeLocBuilder.h" #include "clang/Parse/Ownership.h" #include "clang/Parse/Designator.h" #include "clang/Lex/Preprocessor.h" +#include "llvm/Support/ErrorHandling.h" #include namespace clang { @@ -170,25 +172,30 @@ public: /// \brief Transforms the given type into another type. /// - /// By default, this routine transforms a type by delegating to the - /// appropriate TransformXXXType to build a new type, then applying - /// the qualifiers on \p T to the resulting type with AddTypeQualifiers. - /// Subclasses may override this function (to take over all type - /// transformations), some set of the TransformXXXType functions, or - /// the AddTypeQualifiers function to alter the transformation. + /// By default, this routine transforms a type by creating a + /// DeclaratorInfo for it and delegating to the appropriate + /// function. This is expensive, but we don't mind, because + /// this method is deprecated anyway; all users should be + /// switched to storing DeclaratorInfos. /// /// \returns the transformed type. QualType TransformType(QualType T); - /// \brief Transform the given type by adding the given set of qualifiers - /// and returning the result. + /// \brief Transforms the given type-with-location into a new + /// type-with-location. + /// + /// By default, this routine transforms a type by delegating to the + /// appropriate TransformXXXType to build a new type. Subclasses + /// may override this function (to take over all type + /// transformations) or some set of the TransformXXXType functions + /// to alter the transformation. + DeclaratorInfo *TransformType(DeclaratorInfo *DI); + + /// \brief Transform the given type-with-location into a new + /// type, collecting location information in the given builder + /// as necessary. /// - /// FIXME: By default, this routine adds type qualifiers only to types that - /// can have qualifiers, and silently suppresses those qualifiers that are - /// not permitted (e.g., qualifiers on reference or function types). This - /// is the right thing for template instantiation, but probably not for - /// other clients. - QualType AddTypeQualifiers(QualType T, Qualifiers Qs); + QualType TransformType(TypeLocBuilder &TLB, TypeLoc TL); /// \brief Transform the given statement. /// @@ -285,10 +292,10 @@ public: /// override this function to provide alternate behavior. TemplateArgument TransformTemplateArgument(const TemplateArgument &Arg); -#define ABSTRACT_TYPE(CLASS, PARENT) -#define TYPE(CLASS, PARENT) \ - QualType Transform##CLASS##Type(const CLASS##Type *T); -#include "clang/AST/TypeNodes.def" +#define ABSTRACT_TYPELOC(CLASS, PARENT) +#define TYPELOC(CLASS, PARENT) \ + QualType Transform##CLASS##Type(TypeLocBuilder &TLB, CLASS##TypeLoc T); +#include "clang/AST/TypeLocNodes.def" QualType TransformTemplateSpecializationType(const TemplateSpecializationType *T, @@ -334,6 +341,9 @@ public: /// type. Subclasses may override this routine to provide different behavior. QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType); + /// \brief Build a new Objective C object pointer type. + QualType RebuildObjCObjectPointerType(QualType PointeeType); + /// \brief Build a new array type given the element type, size /// modifier, size of the array (if known), size expression, and index type /// qualifiers. @@ -422,6 +432,9 @@ public: unsigned NumParamTypes, bool Variadic, unsigned Quals); + /// \brief Build a new unprototyped function type. + QualType RebuildFunctionNoProtoType(QualType ResultType); + /// \brief Build a new typedef type. QualType RebuildTypedefType(TypedefDecl *Typedef) { return SemaRef.Context.getTypeDeclType(Typedef); @@ -501,6 +514,14 @@ public: SourceRange(getDerived().getBaseLocation())); } + /// \brief Rebuild an objective C protocol list type. + QualType RebuildObjCProtocolListType(QualType BaseType, + ObjCProtocolDecl **Protocols, + unsigned NumProtocols) { + return SemaRef.Context.getObjCProtocolListType(BaseType, Protocols, + NumProtocols); + } + /// \brief Build a new nested-name-specifier given the prefix and an /// identifier that names the next step in the nested-name-specifier. /// @@ -1939,222 +1960,369 @@ QualType TreeTransform::TransformType(QualType T) { if (getDerived().AlreadyTransformed(T)) return T; - QualifierCollector Qs; - const Type *Ty = Qs.strip(T); - - QualType Result; - switch (Ty->getTypeClass()) { -#define ABSTRACT_TYPE(CLASS, PARENT) -#define TYPE(CLASS, PARENT) \ - case Type::CLASS: \ - Result = getDerived().Transform##CLASS##Type( \ - static_cast(Ty)); \ - break; -#include "clang/AST/TypeNodes.def" - } + // Temporary workaround. All of these transformations should + // eventually turn into transformations on TypeLocs. + DeclaratorInfo *DI = getSema().Context.CreateDeclaratorInfo(T); + DI->getTypeLoc().initialize(getBaseLocation()); + + DeclaratorInfo *NewDI = getDerived().TransformType(DI); - if (Result.isNull() || T == Result) - return Result; + if (!NewDI) + return QualType(); - return getDerived().AddTypeQualifiers(Result, Qs); + return NewDI->getType(); } template -QualType -TreeTransform::AddTypeQualifiers(QualType T, Qualifiers Quals) { - if (!Quals.empty() && !T->isFunctionType() && !T->isReferenceType()) - return SemaRef.Context.getQualifiedType(T, Quals); +DeclaratorInfo *TreeTransform::TransformType(DeclaratorInfo *DI) { + if (getDerived().AlreadyTransformed(DI->getType())) + return DI; - return T; -} + TypeLocBuilder TLB; -template -QualType TreeTransform::TransformBuiltinType(const BuiltinType *T) { - // Nothing to do - return QualType(T, 0); -} + TypeLoc TL = DI->getTypeLoc(); + TLB.reserve(TL.getFullDataSize()); -template -QualType TreeTransform::TransformFixedWidthIntType( - const FixedWidthIntType *T) { - // FIXME: Implement - return QualType(T, 0); -} + QualType Result = getDerived().TransformType(TLB, TL); + if (Result.isNull()) + return 0; -template -QualType TreeTransform::TransformComplexType(const ComplexType *T) { - // FIXME: Implement - return QualType(T, 0); + return TLB.getDeclaratorInfo(SemaRef.Context, Result); } template -QualType TreeTransform::TransformPointerType(const PointerType *T) { - QualType PointeeType = getDerived().TransformType(T->getPointeeType()); - if (PointeeType.isNull()) - return QualType(); - - if (!getDerived().AlwaysRebuild() && - PointeeType == T->getPointeeType()) - return QualType(T, 0); +QualType +TreeTransform::TransformType(TypeLocBuilder &TLB, TypeLoc T) { + switch (T.getTypeLocClass()) { +#define ABSTRACT_TYPELOC(CLASS, PARENT) +#define TYPELOC(CLASS, PARENT) \ + case TypeLoc::CLASS: \ + return getDerived().Transform##CLASS##Type(TLB, cast(T)); +#include "clang/AST/TypeLocNodes.def" + } - return getDerived().RebuildPointerType(PointeeType); + llvm::llvm_unreachable("unhandled type loc!"); + return QualType(); } +/// FIXME: By default, this routine adds type qualifiers only to types +/// that can have qualifiers, and silently suppresses those qualifiers +/// that are not permitted (e.g., qualifiers on reference or function +/// types). This is the right thing for template instantiation, but +/// probably not for other clients. template QualType -TreeTransform::TransformBlockPointerType(const BlockPointerType *T) { - QualType PointeeType = getDerived().TransformType(T->getPointeeType()); - if (PointeeType.isNull()) +TreeTransform::TransformQualifiedType(TypeLocBuilder &TLB, + QualifiedTypeLoc T) { + Qualifiers Quals = T.getType().getQualifiers(); + + QualType Result = getDerived().TransformType(TLB, T.getUnqualifiedLoc()); + if (Result.isNull()) return QualType(); - if (!getDerived().AlwaysRebuild() && - PointeeType == T->getPointeeType()) - return QualType(T, 0); + // Silently suppress qualifiers if the result type can't be qualified. + // FIXME: this is the right thing for template instantiation, but + // probably not for other clients. + if (Result->isFunctionType() || Result->isReferenceType()) + return Result; - return getDerived().RebuildBlockPointerType(PointeeType); + Result = SemaRef.Context.getQualifiedType(Result, Quals); + + TLB.push(Result); + + // No location information to preserve. + + return Result; +} + +template static inline +QualType TransformTypeSpecType(TypeLocBuilder &TLB, TyLoc T) { + TyLoc NewT = TLB.push(T.getType()); + NewT.setNameLoc(T.getNameLoc()); + return T.getType(); +} + +// Ugly metaprogramming macros because I couldn't be bothered to make +// the equivalent template version work. +#define TransformPointerLikeType(TypeClass) do { \ + QualType PointeeType \ + = getDerived().TransformType(TLB, TL.getPointeeLoc()); \ + if (PointeeType.isNull()) \ + return QualType(); \ + \ + QualType Result = TL.getType(); \ + if (getDerived().AlwaysRebuild() || \ + PointeeType != TL.getPointeeLoc().getType()) { \ + Result = getDerived().Rebuild##TypeClass(PointeeType); \ + if (Result.isNull()) \ + return QualType(); \ + } \ + \ + TypeClass##Loc NewT = TLB.push(Result); \ + NewT.setSigilLoc(TL.getSigilLoc()); \ + \ + return Result; \ +} while(0) + +// Reference collapsing forces us to transform reference types +// differently from the other pointer-like types. +#define TransformReferenceType(TypeClass) do { \ + QualType PointeeType \ + = getDerived().TransformType(TLB, TL.getPointeeLoc()); \ + if (PointeeType.isNull()) \ + return QualType(); \ + \ + QualType Result = TL.getType(); \ + if (getDerived().AlwaysRebuild() || \ + PointeeType != TL.getPointeeLoc().getType()) { \ + Result = getDerived().Rebuild##TypeClass(PointeeType); \ + if (Result.isNull()) \ + return QualType(); \ + } \ + \ + /* Workaround: rebuild doesn't always change the type */ \ + /* FIXME: avoid losing this location information. */ \ + if (Result == PointeeType) \ + return Result; \ + ReferenceTypeLoc NewTL; \ + if (isa(Result)) \ + NewTL = TLB.push(Result); \ + else \ + NewTL = TLB.push(Result); \ + NewTL.setSigilLoc(TL.getSigilLoc()); \ + return Result; \ +} while (0) + +template +QualType TreeTransform::TransformBuiltinType(TypeLocBuilder &TLB, + BuiltinTypeLoc T) { + return TransformTypeSpecType(TLB, T); } template QualType -TreeTransform::TransformLValueReferenceType( - const LValueReferenceType *T) { - QualType PointeeType = getDerived().TransformType(T->getPointeeType()); - if (PointeeType.isNull()) - return QualType(); +TreeTransform::TransformFixedWidthIntType(TypeLocBuilder &TLB, + FixedWidthIntTypeLoc T) { + return TransformTypeSpecType(TLB, T); +} - if (!getDerived().AlwaysRebuild() && - PointeeType == T->getPointeeType()) - return QualType(T, 0); +template +QualType TreeTransform::TransformComplexType(TypeLocBuilder &TLB, + ComplexTypeLoc T) { + // FIXME: recurse? + return TransformTypeSpecType(TLB, T); +} - return getDerived().RebuildLValueReferenceType(PointeeType); +template +QualType TreeTransform::TransformPointerType(TypeLocBuilder &TLB, + PointerTypeLoc TL) { + TransformPointerLikeType(PointerType); } template QualType -TreeTransform::TransformRValueReferenceType( - const RValueReferenceType *T) { - QualType PointeeType = getDerived().TransformType(T->getPointeeType()); - if (PointeeType.isNull()) - return QualType(); +TreeTransform::TransformBlockPointerType(TypeLocBuilder &TLB, + BlockPointerTypeLoc TL) { + TransformPointerLikeType(BlockPointerType); +} - if (!getDerived().AlwaysRebuild() && - PointeeType == T->getPointeeType()) - return QualType(T, 0); +template +QualType +TreeTransform::TransformLValueReferenceType(TypeLocBuilder &TLB, + LValueReferenceTypeLoc TL) { + TransformReferenceType(LValueReferenceType); +} - return getDerived().RebuildRValueReferenceType(PointeeType); +template +QualType +TreeTransform::TransformRValueReferenceType(TypeLocBuilder &TLB, + RValueReferenceTypeLoc TL) { + TransformReferenceType(RValueReferenceType); } template QualType -TreeTransform::TransformMemberPointerType(const MemberPointerType *T) { - QualType PointeeType = getDerived().TransformType(T->getPointeeType()); +TreeTransform::TransformMemberPointerType(TypeLocBuilder &TLB, + MemberPointerTypeLoc TL) { + MemberPointerType *T = TL.getTypePtr(); + + QualType PointeeType = getDerived().TransformType(TLB, TL.getPointeeLoc()); if (PointeeType.isNull()) return QualType(); - QualType ClassType = getDerived().TransformType(QualType(T->getClass(), 0)); + // TODO: preserve source information for this. + QualType ClassType + = getDerived().TransformType(QualType(T->getClass(), 0)); if (ClassType.isNull()) return QualType(); - if (!getDerived().AlwaysRebuild() && - PointeeType == T->getPointeeType() && - ClassType == QualType(T->getClass(), 0)) - return QualType(T, 0); + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + PointeeType != T->getPointeeType() || + ClassType != QualType(T->getClass(), 0)) { + Result = getDerived().RebuildMemberPointerType(PointeeType, ClassType); + if (Result.isNull()) + return QualType(); + } + + MemberPointerTypeLoc NewTL = TLB.push(Result); + NewTL.setSigilLoc(TL.getSigilLoc()); - return getDerived().RebuildMemberPointerType(PointeeType, ClassType); + return Result; } template QualType -TreeTransform::TransformConstantArrayType(const ConstantArrayType *T) { - QualType ElementType = getDerived().TransformType(T->getElementType()); +TreeTransform::TransformConstantArrayType(TypeLocBuilder &TLB, + ConstantArrayTypeLoc TL) { + ConstantArrayType *T = TL.getTypePtr(); + QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc()); if (ElementType.isNull()) return QualType(); - if (!getDerived().AlwaysRebuild() && - ElementType == T->getElementType()) - return QualType(T, 0); + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + ElementType != T->getElementType()) { + Result = getDerived().RebuildConstantArrayType(ElementType, + T->getSizeModifier(), + T->getSize(), + T->getIndexTypeCVRQualifiers()); + if (Result.isNull()) + return QualType(); + } + + ConstantArrayTypeLoc NewTL = TLB.push(Result); + NewTL.setLBracketLoc(TL.getLBracketLoc()); + NewTL.setRBracketLoc(TL.getRBracketLoc()); + + Expr *Size = TL.getSizeExpr(); + if (Size) { + EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); + Size = getDerived().TransformExpr(Size).template takeAs(); + } + NewTL.setSizeExpr(Size); - return getDerived().RebuildConstantArrayType(ElementType, - T->getSizeModifier(), - T->getSize(), - T->getIndexTypeCVRQualifiers()); + return Result; } template QualType TreeTransform::TransformIncompleteArrayType( - const IncompleteArrayType *T) { - QualType ElementType = getDerived().TransformType(T->getElementType()); + TypeLocBuilder &TLB, + IncompleteArrayTypeLoc TL) { + IncompleteArrayType *T = TL.getTypePtr(); + QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc()); if (ElementType.isNull()) return QualType(); - if (!getDerived().AlwaysRebuild() && - ElementType == T->getElementType()) - return QualType(T, 0); + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + ElementType != T->getElementType()) { + Result = getDerived().RebuildIncompleteArrayType(ElementType, + T->getSizeModifier(), + T->getIndexTypeCVRQualifiers()); + if (Result.isNull()) + return QualType(); + } + + IncompleteArrayTypeLoc NewTL = TLB.push(Result); + NewTL.setLBracketLoc(TL.getLBracketLoc()); + NewTL.setRBracketLoc(TL.getRBracketLoc()); + NewTL.setSizeExpr(0); - return getDerived().RebuildIncompleteArrayType(ElementType, - T->getSizeModifier(), - T->getIndexTypeCVRQualifiers()); + return Result; } template -QualType TreeTransform::TransformVariableArrayType( - const VariableArrayType *T) { - QualType ElementType = getDerived().TransformType(T->getElementType()); +QualType +TreeTransform::TransformVariableArrayType(TypeLocBuilder &TLB, + VariableArrayTypeLoc TL) { + VariableArrayType *T = TL.getTypePtr(); + QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc()); if (ElementType.isNull()) return QualType(); // Array bounds are not potentially evaluated contexts EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); - Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr()); - if (Size.isInvalid()) + Sema::OwningExprResult SizeResult + = getDerived().TransformExpr(T->getSizeExpr()); + if (SizeResult.isInvalid()) return QualType(); - if (!getDerived().AlwaysRebuild() && - ElementType == T->getElementType() && - Size.get() == T->getSizeExpr()) { - Size.take(); - return QualType(T, 0); + Expr *Size = static_cast(SizeResult.get()); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + ElementType != T->getElementType() || + Size != T->getSizeExpr()) { + Result = getDerived().RebuildVariableArrayType(ElementType, + T->getSizeModifier(), + move(SizeResult), + T->getIndexTypeCVRQualifiers(), + T->getBracketsRange()); + if (Result.isNull()) + return QualType(); } + else SizeResult.take(); + + VariableArrayTypeLoc NewTL = TLB.push(Result); + NewTL.setLBracketLoc(TL.getLBracketLoc()); + NewTL.setRBracketLoc(TL.getRBracketLoc()); + NewTL.setSizeExpr(Size); - return getDerived().RebuildVariableArrayType(ElementType, - T->getSizeModifier(), - move(Size), - T->getIndexTypeCVRQualifiers(), - T->getBracketsRange()); + return Result; } template -QualType TreeTransform::TransformDependentSizedArrayType( - const DependentSizedArrayType *T) { - QualType ElementType = getDerived().TransformType(T->getElementType()); +QualType +TreeTransform::TransformDependentSizedArrayType(TypeLocBuilder &TLB, + DependentSizedArrayTypeLoc TL) { + DependentSizedArrayType *T = TL.getTypePtr(); + QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc()); if (ElementType.isNull()) return QualType(); // Array bounds are not potentially evaluated contexts EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); - Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr()); - if (Size.isInvalid()) + Sema::OwningExprResult SizeResult + = getDerived().TransformExpr(T->getSizeExpr()); + if (SizeResult.isInvalid()) return QualType(); - if (!getDerived().AlwaysRebuild() && - ElementType == T->getElementType() && - Size.get() == T->getSizeExpr()) { - Size.take(); - return QualType(T, 0); + Expr *Size = static_cast(SizeResult.get()); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + ElementType != T->getElementType() || + Size != T->getSizeExpr()) { + Result = getDerived().RebuildDependentSizedArrayType(ElementType, + T->getSizeModifier(), + move(SizeResult), + T->getIndexTypeCVRQualifiers(), + T->getBracketsRange()); + if (Result.isNull()) + return QualType(); } + else SizeResult.take(); - return getDerived().RebuildDependentSizedArrayType(ElementType, - T->getSizeModifier(), - move(Size), - T->getIndexTypeCVRQualifiers(), - T->getBracketsRange()); + // We might have any sort of array type now, but fortunately they + // all have the same location layout. + ArrayTypeLoc NewTL = TLB.push(Result); + NewTL.setLBracketLoc(TL.getLBracketLoc()); + NewTL.setRBracketLoc(TL.getRBracketLoc()); + NewTL.setSizeExpr(Size); + + return Result; } template QualType TreeTransform::TransformDependentSizedExtVectorType( - const DependentSizedExtVectorType *T) { + TypeLocBuilder &TLB, + DependentSizedExtVectorTypeLoc TL) { + DependentSizedExtVectorType *T = TL.getTypePtr(); + + // FIXME: ext vector locs should be nested QualType ElementType = getDerived().TransformType(T->getElementType()); if (ElementType.isNull()) return QualType(); @@ -2166,98 +2334,202 @@ QualType TreeTransform::TransformDependentSizedExtVectorType( if (Size.isInvalid()) return QualType(); - if (!getDerived().AlwaysRebuild() && - ElementType == T->getElementType() && - Size.get() == T->getSizeExpr()) { - Size.take(); - return QualType(T, 0); - } - - return getDerived().RebuildDependentSizedExtVectorType(ElementType, + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + ElementType != T->getElementType() && + Size.get() != T->getSizeExpr()) { + Result = getDerived().RebuildDependentSizedExtVectorType(ElementType, move(Size), T->getAttributeLoc()); + if (Result.isNull()) + return QualType(); + } + else Size.take(); + + // Result might be dependent or not. + if (isa(Result)) { + DependentSizedExtVectorTypeLoc NewTL + = TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); + } else { + ExtVectorTypeLoc NewTL = TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); + } + + return Result; } template -QualType TreeTransform::TransformVectorType(const VectorType *T) { +QualType TreeTransform::TransformVectorType(TypeLocBuilder &TLB, + VectorTypeLoc TL) { + VectorType *T = TL.getTypePtr(); QualType ElementType = getDerived().TransformType(T->getElementType()); if (ElementType.isNull()) return QualType(); - if (!getDerived().AlwaysRebuild() && - ElementType == T->getElementType()) - return QualType(T, 0); + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + ElementType != T->getElementType()) { + Result = getDerived().RebuildVectorType(ElementType, T->getNumElements()); + if (Result.isNull()) + return QualType(); + } + + VectorTypeLoc NewTL = TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); - return getDerived().RebuildVectorType(ElementType, T->getNumElements()); + return Result; } template -QualType -TreeTransform::TransformExtVectorType(const ExtVectorType *T) { +QualType TreeTransform::TransformExtVectorType(TypeLocBuilder &TLB, + ExtVectorTypeLoc TL) { + VectorType *T = TL.getTypePtr(); QualType ElementType = getDerived().TransformType(T->getElementType()); if (ElementType.isNull()) return QualType(); - if (!getDerived().AlwaysRebuild() && - ElementType == T->getElementType()) - return QualType(T, 0); + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + ElementType != T->getElementType()) { + Result = getDerived().RebuildExtVectorType(ElementType, + T->getNumElements(), + /*FIXME*/ SourceLocation()); + if (Result.isNull()) + return QualType(); + } + + ExtVectorTypeLoc NewTL = TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); - return getDerived().RebuildExtVectorType(ElementType, T->getNumElements(), - /*FIXME*/SourceLocation()); + return Result; } template -QualType TreeTransform::TransformFunctionProtoType( - const FunctionProtoType *T) { - QualType ResultType = getDerived().TransformType(T->getResultType()); +QualType +TreeTransform::TransformFunctionProtoType(TypeLocBuilder &TLB, + FunctionProtoTypeLoc TL) { + FunctionProtoType *T = TL.getTypePtr(); + QualType ResultType = getDerived().TransformType(TLB, TL.getResultLoc()); if (ResultType.isNull()) return QualType(); + // Transform the parameters. llvm::SmallVector ParamTypes; - for (FunctionProtoType::arg_type_iterator Param = T->arg_type_begin(), - ParamEnd = T->arg_type_end(); - Param != ParamEnd; ++Param) { - QualType P = getDerived().TransformType(*Param); - if (P.isNull()) - return QualType(); + llvm::SmallVector ParamDecls; + for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) { + ParmVarDecl *OldParm = TL.getArg(i); + + QualType NewType; + ParmVarDecl *NewParm; + + if (OldParm) { + DeclaratorInfo *OldDI = OldParm->getDeclaratorInfo(); + assert(OldDI->getType() == T->getArgType(i)); + + DeclaratorInfo *NewDI = getDerived().TransformType(OldDI); + if (!NewDI) + return QualType(); + + if (NewDI == OldDI) + NewParm = OldParm; + else + NewParm = ParmVarDecl::Create(SemaRef.Context, + OldParm->getDeclContext(), + OldParm->getLocation(), + OldParm->getIdentifier(), + NewDI->getType(), + NewDI, + OldParm->getStorageClass(), + /* DefArg */ NULL); + NewType = NewParm->getType(); + + // Deal with the possibility that we don't have a parameter + // declaration for this parameter. + } else { + NewParm = 0; + + QualType OldType = T->getArgType(i); + NewType = getDerived().TransformType(OldType); + if (NewType.isNull()) + return QualType(); + } - ParamTypes.push_back(P); + ParamTypes.push_back(NewType); + ParamDecls.push_back(NewParm); } - if (!getDerived().AlwaysRebuild() && - ResultType == T->getResultType() && - std::equal(T->arg_type_begin(), T->arg_type_end(), ParamTypes.begin())) - return QualType(T, 0); + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + ResultType != T->getResultType() || + !std::equal(T->arg_type_begin(), T->arg_type_end(), ParamTypes.begin())) { + Result = getDerived().RebuildFunctionProtoType(ResultType, + ParamTypes.data(), + ParamTypes.size(), + T->isVariadic(), + T->getTypeQuals()); + if (Result.isNull()) + return QualType(); + } - return getDerived().RebuildFunctionProtoType(ResultType, ParamTypes.data(), - ParamTypes.size(), T->isVariadic(), - T->getTypeQuals()); + FunctionProtoTypeLoc NewTL = TLB.push(Result); + NewTL.setLParenLoc(TL.getLParenLoc()); + NewTL.setRParenLoc(TL.getRParenLoc()); + for (unsigned i = 0, e = NewTL.getNumArgs(); i != e; ++i) + NewTL.setArg(i, ParamDecls[i]); + + return Result; } template QualType TreeTransform::TransformFunctionNoProtoType( - const FunctionNoProtoType *T) { - // FIXME: Implement - return QualType(T, 0); + TypeLocBuilder &TLB, + FunctionNoProtoTypeLoc TL) { + FunctionNoProtoType *T = TL.getTypePtr(); + QualType ResultType = getDerived().TransformType(TLB, TL.getResultLoc()); + if (ResultType.isNull()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + ResultType != T->getResultType()) + Result = getDerived().RebuildFunctionNoProtoType(ResultType); + + FunctionNoProtoTypeLoc NewTL = TLB.push(Result); + NewTL.setLParenLoc(TL.getLParenLoc()); + NewTL.setRParenLoc(TL.getRParenLoc()); + + return Result; } template -QualType TreeTransform::TransformTypedefType(const TypedefType *T) { +QualType TreeTransform::TransformTypedefType(TypeLocBuilder &TLB, + TypedefTypeLoc TL) { + TypedefType *T = TL.getTypePtr(); TypedefDecl *Typedef = cast_or_null(getDerived().TransformDecl(T->getDecl())); if (!Typedef) return QualType(); - if (!getDerived().AlwaysRebuild() && - Typedef == T->getDecl()) - return QualType(T, 0); + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + Typedef != T->getDecl()) { + Result = getDerived().RebuildTypedefType(Typedef); + if (Result.isNull()) + return QualType(); + } + + TypedefTypeLoc NewTL = TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); - return getDerived().RebuildTypedefType(Typedef); + return Result; } template -QualType TreeTransform::TransformTypeOfExprType( - const TypeOfExprType *T) { +QualType TreeTransform::TransformTypeOfExprType(TypeLocBuilder &TLB, + TypeOfExprTypeLoc TL) { + TypeOfExprType *T = TL.getTypePtr(); + // typeof expressions are not potentially evaluated contexts EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); @@ -2265,30 +2537,50 @@ QualType TreeTransform::TransformTypeOfExprType( if (E.isInvalid()) return QualType(); - if (!getDerived().AlwaysRebuild() && - E.get() == T->getUnderlyingExpr()) { - E.take(); - return QualType(T, 0); + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + E.get() != T->getUnderlyingExpr()) { + Result = getDerived().RebuildTypeOfExprType(move(E)); + if (Result.isNull()) + return QualType(); } + else E.take(); - return getDerived().RebuildTypeOfExprType(move(E)); + TypeOfExprTypeLoc NewTL = TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); + + return Result; } template -QualType TreeTransform::TransformTypeOfType(const TypeOfType *T) { +QualType TreeTransform::TransformTypeOfType(TypeLocBuilder &TLB, + TypeOfTypeLoc TL) { + TypeOfType *T = TL.getTypePtr(); + + // FIXME: should be an inner type, or at least have a DeclaratorInfo. QualType Underlying = getDerived().TransformType(T->getUnderlyingType()); if (Underlying.isNull()) return QualType(); - if (!getDerived().AlwaysRebuild() && - Underlying == T->getUnderlyingType()) - return QualType(T, 0); + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + Underlying != T->getUnderlyingType()) { + Result = getDerived().RebuildTypeOfType(Underlying); + if (Result.isNull()) + return QualType(); + } + + TypeOfTypeLoc NewTL = TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); - return getDerived().RebuildTypeOfType(Underlying); + return Result; } template -QualType TreeTransform::TransformDecltypeType(const DecltypeType *T) { +QualType TreeTransform::TransformDecltypeType(TypeLocBuilder &TLB, + DecltypeTypeLoc TL) { + DecltypeType *T = TL.getTypePtr(); + // decltype expressions are not potentially evaluated contexts EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); @@ -2296,77 +2588,122 @@ QualType TreeTransform::TransformDecltypeType(const DecltypeType *T) { if (E.isInvalid()) return QualType(); - if (!getDerived().AlwaysRebuild() && - E.get() == T->getUnderlyingExpr()) { - E.take(); - return QualType(T, 0); + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + E.get() != T->getUnderlyingExpr()) { + Result = getDerived().RebuildDecltypeType(move(E)); + if (Result.isNull()) + return QualType(); } + else E.take(); - return getDerived().RebuildDecltypeType(move(E)); + DecltypeTypeLoc NewTL = TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); + + return Result; } template -QualType TreeTransform::TransformRecordType(const RecordType *T) { +QualType TreeTransform::TransformRecordType(TypeLocBuilder &TLB, + RecordTypeLoc TL) { + RecordType *T = TL.getTypePtr(); RecordDecl *Record - = cast_or_null(getDerived().TransformDecl(T->getDecl())); + = cast_or_null(getDerived().TransformDecl(T->getDecl())); if (!Record) return QualType(); - if (!getDerived().AlwaysRebuild() && - Record == T->getDecl()) - return QualType(T, 0); + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + Record != T->getDecl()) { + Result = getDerived().RebuildRecordType(Record); + if (Result.isNull()) + return QualType(); + } + + RecordTypeLoc NewTL = TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); - return getDerived().RebuildRecordType(Record); + return Result; } template -QualType TreeTransform::TransformEnumType(const EnumType *T) { +QualType TreeTransform::TransformEnumType(TypeLocBuilder &TLB, + EnumTypeLoc TL) { + EnumType *T = TL.getTypePtr(); EnumDecl *Enum - = cast_or_null(getDerived().TransformDecl(T->getDecl())); + = cast_or_null(getDerived().TransformDecl(T->getDecl())); if (!Enum) return QualType(); - if (!getDerived().AlwaysRebuild() && - Enum == T->getDecl()) - return QualType(T, 0); + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + Enum != T->getDecl()) { + Result = getDerived().RebuildEnumType(Enum); + if (Result.isNull()) + return QualType(); + } - return getDerived().RebuildEnumType(Enum); + EnumTypeLoc NewTL = TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); + + return Result; } template -QualType TreeTransform::TransformElaboratedType( - const ElaboratedType *T) { +QualType TreeTransform::TransformElaboratedType(TypeLocBuilder &TLB, + ElaboratedTypeLoc TL) { + ElaboratedType *T = TL.getTypePtr(); + + // FIXME: this should be a nested type. QualType Underlying = getDerived().TransformType(T->getUnderlyingType()); if (Underlying.isNull()) return QualType(); - if (!getDerived().AlwaysRebuild() && - Underlying == T->getUnderlyingType()) - return QualType(T, 0); + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + Underlying != T->getUnderlyingType()) { + Result = getDerived().RebuildElaboratedType(Underlying, T->getTagKind()); + if (Result.isNull()) + return QualType(); + } - return getDerived().RebuildElaboratedType(Underlying, T->getTagKind()); + ElaboratedTypeLoc NewTL = TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); + + return Result; } template QualType TreeTransform::TransformTemplateTypeParmType( - const TemplateTypeParmType *T) { - // Nothing to do - return QualType(T, 0); + TypeLocBuilder &TLB, + TemplateTypeParmTypeLoc TL) { + return TransformTypeSpecType(TLB, TL); } template QualType TreeTransform::TransformSubstTemplateTypeParmType( - const SubstTemplateTypeParmType *T) { - // Nothing to do - return QualType(T, 0); + TypeLocBuilder &TLB, + SubstTemplateTypeParmTypeLoc TL) { + return TransformTypeSpecType(TLB, TL); } template inline QualType TreeTransform::TransformTemplateSpecializationType( - const TemplateSpecializationType *T) { - return TransformTemplateSpecializationType(T, QualType()); + TypeLocBuilder &TLB, + TemplateSpecializationTypeLoc TL) { + // TODO: figure out how make this work with an ObjectType. + QualType Result + = TransformTemplateSpecializationType(TL.getTypePtr(), QualType()); + if (Result.isNull()) + return QualType(); + + TemplateSpecializationTypeLoc NewTL + = TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); + + return Result; } template @@ -2399,8 +2736,10 @@ QualType TreeTransform::TransformTemplateSpecializationType( } template -QualType TreeTransform::TransformQualifiedNameType( - const QualifiedNameType *T) { +QualType +TreeTransform::TransformQualifiedNameType(TypeLocBuilder &TLB, + QualifiedNameTypeLoc TL) { + QualifiedNameType *T = TL.getTypePtr(); NestedNameSpecifier *NNS = getDerived().TransformNestedNameSpecifier(T->getQualifier(), SourceRange()); @@ -2411,22 +2750,33 @@ QualType TreeTransform::TransformQualifiedNameType( if (Named.isNull()) return QualType(); - if (!getDerived().AlwaysRebuild() && - NNS == T->getQualifier() && - Named == T->getNamedType()) - return QualType(T, 0); + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + NNS != T->getQualifier() || + Named != T->getNamedType()) { + Result = getDerived().RebuildQualifiedNameType(NNS, Named); + if (Result.isNull()) + return QualType(); + } + + QualifiedNameTypeLoc NewTL = TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); - return getDerived().RebuildQualifiedNameType(NNS, Named); + return Result; } template -QualType TreeTransform::TransformTypenameType(const TypenameType *T) { +QualType TreeTransform::TransformTypenameType(TypeLocBuilder &TLB, + TypenameTypeLoc TL) { + TypenameType *T = TL.getTypePtr(); NestedNameSpecifier *NNS = getDerived().TransformNestedNameSpecifier(T->getQualifier(), SourceRange(/*FIXME:*/getDerived().getBaseLocation())); if (!NNS) return QualType(); + QualType Result; + if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) { QualType NewTemplateId = getDerived().TransformType(QualType(TemplateId, 0)); @@ -2438,31 +2788,67 @@ QualType TreeTransform::TransformTypenameType(const TypenameType *T) { NewTemplateId == QualType(TemplateId, 0)) return QualType(T, 0); - return getDerived().RebuildTypenameType(NNS, NewTemplateId); + Result = getDerived().RebuildTypenameType(NNS, NewTemplateId); + } else { + Result = getDerived().RebuildTypenameType(NNS, T->getIdentifier()); } + if (Result.isNull()) + return QualType(); + + TypenameTypeLoc NewTL = TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); - return getDerived().RebuildTypenameType(NNS, T->getIdentifier()); + return Result; } template -QualType TreeTransform::TransformObjCInterfaceType( - const ObjCInterfaceType *T) { - // FIXME: Implement - return QualType(T, 0); +QualType +TreeTransform::TransformObjCInterfaceType(TypeLocBuilder &TLB, + ObjCInterfaceTypeLoc TL) { + return TransformTypeSpecType(TLB, TL); } template -QualType TreeTransform::TransformObjCObjectPointerType( - const ObjCObjectPointerType *T) { - // FIXME: Implement - return QualType(T, 0); +QualType +TreeTransform::TransformObjCObjectPointerType(TypeLocBuilder &TLB, + ObjCObjectPointerTypeLoc TL) { + TransformPointerLikeType(ObjCObjectPointerType); } template QualType TreeTransform::TransformObjCProtocolListType( - const ObjCProtocolListType *T) { - assert(false && "Should not see ObjCProtocolList types"); - return QualType(T, 0); + TypeLocBuilder &TLB, + ObjCProtocolListTypeLoc TL) { + ObjCProtocolListType *T = TL.getTypePtr(); + QualType BaseType = T->getBaseType(); + if (!BaseType.isNull()) { + BaseType = getDerived().TransformType(TLB, TL.getBaseTypeLoc()); + if (BaseType.isNull()) + return QualType(); + } + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + BaseType != T->getBaseType()) { + // TODO: transform these? + llvm::SmallVector Protocols(T->getNumProtocols()); + std::copy(T->qual_begin(), T->qual_end(), Protocols.begin()); + Result = getDerived().RebuildObjCProtocolListType(BaseType, + &Protocols[0], + T->getNumProtocols()); + if (Result.isNull()) + return QualType(); + } + + ObjCProtocolListTypeLoc NewTL = TLB.push(Result); + NewTL.setLAngleLoc(TL.getLAngleLoc()); + NewTL.setRAngleLoc(TL.getRAngleLoc()); + + assert(NewTL.getNumProtocols() == TL.getNumProtocols()); + for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) + NewTL.setProtocolLoc(i, TL.getProtocolLoc(i)); + + return Result; } //===----------------------------------------------------------------------===// @@ -4477,6 +4863,14 @@ QualType TreeTransform::RebuildMemberPointerType(QualType PointeeType, getDerived().getBaseEntity()); } +template +QualType +TreeTransform::RebuildObjCObjectPointerType(QualType PointeeType) { + return SemaRef.BuildPointerType(PointeeType, Qualifiers(), + getDerived().getBaseLocation(), + getDerived().getBaseEntity()); +} + template QualType TreeTransform::RebuildArrayType(QualType ElementType, @@ -4595,6 +4989,11 @@ QualType TreeTransform::RebuildFunctionProtoType(QualType T, getDerived().getBaseEntity()); } +template +QualType TreeTransform::RebuildFunctionNoProtoType(QualType T) { + return SemaRef.Context.getFunctionNoProtoType(T); +} + template QualType TreeTransform::RebuildTypeOfExprType(ExprArg E) { return SemaRef.BuildTypeofExprType(E.takeAs());