diff options
author | Abramo Bagnara <abramo.bagnara@gmail.com> | 2010-12-10 16:29:40 +0000 |
---|---|---|
committer | Abramo Bagnara <abramo.bagnara@gmail.com> | 2010-12-10 16:29:40 +0000 |
commit | 075f8f1b6bed4d1b224c74f87508534cc6392ce6 (patch) | |
tree | c928464ba32f736d3a38292dd23a6ef919ce4d1c /lib | |
parent | c3c0af36bac3d71f61dd758585ab307892545de4 (diff) |
Added ParenType type node.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@121488 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ASTContext.cpp | 34 | ||||
-rw-r--r-- | lib/AST/ASTDiagnostic.cpp | 6 | ||||
-rw-r--r-- | lib/AST/ASTImporter.cpp | 7 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 6 | ||||
-rw-r--r-- | lib/AST/TypePrinter.cpp | 6 | ||||
-rw-r--r-- | lib/CodeGen/CGDebugInfo.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.cpp | 5 | ||||
-rw-r--r-- | lib/Parse/ParseCXXInlineMethods.cpp | 3 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 4 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 2 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 14 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 20 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaExceptionSpec.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 15 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 30 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 13 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 9 |
20 files changed, 164 insertions, 29 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index dfdc505b1a..ecba4a136f 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -811,6 +811,9 @@ ASTContext::getTypeInfo(const Type *T) { return getTypeInfo(cast<SubstTemplateTypeParmType>(T)-> getReplacementType().getTypePtr()); + case Type::Paren: + return getTypeInfo(cast<ParenType>(T)->getInnerType().getTypePtr()); + case Type::Typedef: { const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl(); std::pair<uint64_t, unsigned> Info @@ -1147,6 +1150,13 @@ static QualType getExtFunctionType(ASTContext& Context, QualType T, return T; ResultType = Context.getPointerType(ResultType); + } else if (const ParenType *Paren = T->getAs<ParenType>()) { + QualType Inner = Paren->getInnerType(); + ResultType = getExtFunctionType(Context, Inner, Info); + if (ResultType == Inner) + return T; + + ResultType = Context.getParenType(ResultType); } else if (const BlockPointerType *BlockPointer = T->getAs<BlockPointerType>()) { QualType Pointee = BlockPointer->getPointeeType(); @@ -2095,6 +2105,30 @@ ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword, return QualType(T, 0); } +QualType +ASTContext::getParenType(QualType InnerType) { + llvm::FoldingSetNodeID ID; + ParenType::Profile(ID, InnerType); + + void *InsertPos = 0; + ParenType *T = ParenTypes.FindNodeOrInsertPos(ID, InsertPos); + if (T) + return QualType(T, 0); + + QualType Canon = InnerType; + if (!Canon.isCanonical()) { + Canon = getCanonicalType(InnerType); + ParenType *CheckT = ParenTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(!CheckT && "Paren canonical type broken"); + (void)CheckT; + } + + T = new (*this) ParenType(InnerType, Canon); + Types.push_back(T); + ParenTypes.InsertNode(T, InsertPos); + return QualType(T, 0); +} + QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp index 8d5e408465..bd128f0514 100644 --- a/lib/AST/ASTDiagnostic.cpp +++ b/lib/AST/ASTDiagnostic.cpp @@ -32,7 +32,11 @@ static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) { QT = cast<ElaboratedType>(Ty)->desugar(); continue; } - + // ... or a paren type ... + if (isa<ParenType>(Ty)) { + QT = cast<ParenType>(Ty)->desugar(); + continue; + } // ...or a substituted template type parameter. if (isa<SubstTemplateTypeParmType>(Ty)) { QT = cast<SubstTemplateTypeParmType>(Ty)->desugar(); diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 4094c88e13..8415977349 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -553,6 +553,13 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, break; + case Type::Paren: + if (!IsStructurallyEquivalent(Context, + cast<ParenType>(T1)->getInnerType(), + cast<ParenType>(T2)->getInnerType())) + return false; + break; + case Type::Typedef: if (!IsStructurallyEquivalent(Context, cast<TypedefType>(T1)->getDecl(), diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 705b097212..ed05a39305 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -171,6 +171,12 @@ SplitQualType QualType::getSplitDesugaredType(QualType T) { } } +QualType QualType::IgnoreParens(QualType T) { + while (const ParenType *PT = T->getAs<ParenType>()) + T = PT->getInnerType(); + return T; +} + /// getUnqualifiedDesugaredType - Pull any qualifiers and syntactic /// sugar off the given type. This should produce an object of the /// same dynamic type as the canonical type. diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index 0e37acb40f..15c3fb2fbf 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -618,6 +618,12 @@ void TypePrinter::printElaborated(const ElaboratedType *T, std::string &S) { S = MyString + ' ' + S; } +void TypePrinter::printParen(const ParenType *T, std::string &S) { + if (!S.empty() && !isa<FunctionType>(T->getInnerType())) + S = '(' + S + ')'; + print(T->getInnerType(), S); +} + void TypePrinter::printDependentName(const DependentNameType *T, std::string &S) { std::string MyString; diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 3e77769466..615972afbc 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -1327,6 +1327,9 @@ static QualType UnwrapTypeForDebugInfo(QualType T) { case Type::Elaborated: T = cast<ElaboratedType>(T)->getNamedType(); break; + case Type::Paren: + T = cast<ParenType>(T)->getInnerType(); + break; case Type::SubstTemplateTypeParm: T = cast<SubstTemplateTypeParmType>(T)->getReplacementType(); break; @@ -1422,6 +1425,7 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, case Type::TemplateSpecialization: case Type::Elaborated: + case Type::Paren: case Type::SubstTemplateTypeParm: case Type::TypeOfExpr: case Type::TypeOf: diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index efeca2d538..7bd0c3da9e 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -656,6 +656,11 @@ llvm::Value *CodeGenFunction::EmitVLASize(QualType Ty) { return 0; } + if (const ParenType *PT = dyn_cast<ParenType>(Ty)) { + EmitVLASize(PT->getInnerType()); + return 0; + } + const PointerType *PT = Ty->getAs<PointerType>(); assert(PT && "unknown VM type!"); EmitVLASize(PT->getPointeeType()); diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp index 718c71be02..2341ad39f0 100644 --- a/lib/Parse/ParseCXXInlineMethods.cpp +++ b/lib/Parse/ParseCXXInlineMethods.cpp @@ -22,8 +22,7 @@ using namespace clang; /// and store its tokens for parsing after the C++ class is complete. Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D, const ParsedTemplateInfo &TemplateInfo) { - assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function && - "This isn't a function declarator!"); + assert(D.isFunctionDeclarator() && "This isn't a function declarator!"); assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) && "Current token not a '{', ':' or 'try'!"); diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 9a682b064d..53cccc0819 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -3037,10 +3037,10 @@ void Parser::ParseParenDeclarator(Declarator &D) { ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator); // Match the ')'. - SourceLocation Loc = MatchRHSPunctuation(tok::r_paren, StartLoc); + SourceLocation EndLoc = MatchRHSPunctuation(tok::r_paren, StartLoc); + D.AddTypeInfo(DeclaratorChunk::getParen(StartLoc, EndLoc), EndLoc); D.setGroupingParens(hadGroupingParens); - D.SetRangeEnd(Loc); return; } diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 68797a7542..a2c87f85c3 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -1239,7 +1239,7 @@ void Parser::HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo, // has any default arguments, we'll need to parse them later. LateParsedMethodDeclaration *LateMethod = 0; DeclaratorChunk::FunctionTypeInfo &FTI - = DeclaratorInfo.getTypeObject(0).Fun; + = DeclaratorInfo.getFunctionTypeInfo(); for (unsigned ParamIdx = 0; ParamIdx < FTI.NumArgs; ++ParamIdx) { if (LateMethod || FTI.ArgInfo[ParamIdx].DefaultArgTokens) { if (!LateMethod) { diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index f5e4bfb649..f79a2f68c7 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -601,14 +601,13 @@ bool Parser::isDeclarationAfterDeclarator() const { /// \brief Determine whether the current token, if it occurs after a /// declarator, indicates the start of a function definition. bool Parser::isStartOfFunctionDefinition(const ParsingDeclarator &Declarator) { - assert(Declarator.getTypeObject(0).Kind == DeclaratorChunk::Function && - "Isn't a function declarator"); + assert(Declarator.isFunctionDeclarator() && "Isn't a function declarator"); if (Tok.is(tok::l_brace)) // int X() {} return true; // Handle K&R C argument lists: int X(f) int f; {} if (!getLang().CPlusPlus && - Declarator.getTypeObject(0).Fun.isKNRPrototype()) + Declarator.getFunctionTypeInfo().isKNRPrototype()) return isDeclarationSpecifier(); return Tok.is(tok::colon) || // X() : Base() {} (used for ctors) @@ -712,11 +711,8 @@ Parser::ParseDeclarationOrFunctionDefinition(AttributeList *Attr, /// decl-specifier-seq[opt] declarator function-try-block /// Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, - const ParsedTemplateInfo &TemplateInfo) { - const DeclaratorChunk &FnTypeInfo = D.getTypeObject(0); - assert(FnTypeInfo.Kind == DeclaratorChunk::Function && - "This isn't a function declarator!"); - const DeclaratorChunk::FunctionTypeInfo &FTI = FnTypeInfo.Fun; + const ParsedTemplateInfo &TemplateInfo) { + const DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); // If this is C90 and the declspecs were completely missing, fudge in an // implicit int. We do this here because this is the only place where @@ -793,7 +789,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, /// types for a function with a K&R-style identifier list for arguments. void Parser::ParseKNRParamDeclarations(Declarator &D) { // We know that the top-level of this declarator is a function. - DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); // Enter function-declaration scope, limiting any declarators to the // function prototype scope, including parameter declarators. diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 0e30a2b0ba..2394629be5 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -1919,6 +1919,9 @@ static std::string FormatFunctionParameter(ASTContext &Context, if (BlockPointerTypeLoc *BlockPtr = dyn_cast<BlockPointerTypeLoc>(&TL)) { TL = BlockPtr->getPointeeLoc(); + // Skip any paren typeloc. + while (ParenTypeLoc *ParenPtr = dyn_cast<ParenTypeLoc>(&TL)) + TL = ParenPtr->getInnerLoc(); Block = dyn_cast<FunctionProtoTypeLoc>(&TL); } break; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 1112d85b8b..522ba36760 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2571,6 +2571,15 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T, FixedType = Context.getPointerType(FixedType); return Qs.apply(Context, FixedType); } + if (const ParenType* PTy = dyn_cast<ParenType>(Ty)) { + QualType Inner = PTy->getInnerType(); + QualType FixedType = + TryToFixInvalidVariablyModifiedType(Inner, Context, SizeIsNegative, + Oversized); + if (FixedType.isNull()) return FixedType; + FixedType = Context.getParenType(FixedType); + return Qs.apply(Context, FixedType); + } const VariableArrayType* VLATy = dyn_cast<VariableArrayType>(T); if (!VLATy) @@ -3456,7 +3465,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // - the type R of the function is some kind of typedef or other reference // to a type name (which eventually refers to a function type). bool HasPrototype = - (D.getNumTypeObjects() && D.getTypeObject(0).Fun.hasPrototype) || + (D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) || (!isa<FunctionType>(R.getTypePtr()) && R->isFunctionProtoType()); NewFD = FunctionDecl::Create(Context, DC, @@ -3754,7 +3763,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // declaration NewFD, if they are available. First scavenge them into Params. llvm::SmallVector<ParmVarDecl*, 16> Params; if (D.getNumTypeObjects() > 0) { - DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); // Check for C99 6.7.5.3p10 - foo(void) is a non-varargs // function that takes no arguments, not a function that takes a @@ -5088,9 +5097,7 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, SourceLocation LocAfterDecls) { - assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function && - "Not a function declarator!"); - DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); // Verify 6.9.1p6: 'every identifier in the identifier list shall be declared' // for a K&R function. @@ -5124,8 +5131,7 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) { assert(getCurFunctionDecl() == 0 && "Function parsing confused"); - assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function && - "Not a function declarator!"); + assert(D.isFunctionDeclarator() && "Not a function declarator!"); Scope *ParentScope = FnBodyScope->getParent(); Decl *DP = HandleDeclarator(ParentScope, D, diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index b5e6321276..be1979e26e 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2835,7 +2835,7 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R, SC = SC_None; } - DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); if (FTI.TypeQuals != 0) { if (FTI.TypeQuals & Qualifiers::Const) Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor) @@ -2984,7 +2984,7 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, << SourceRange(D.getIdentifierLoc()); } - DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); if (FTI.TypeQuals != 0 && !D.isInvalidType()) { if (FTI.TypeQuals & Qualifiers::Const) Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor) @@ -3074,7 +3074,7 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, Diag(D.getIdentifierLoc(), diag::err_conv_function_with_params); // Delete the parameters. - D.getTypeObject(0).Fun.freeArgs(); + D.getFunctionTypeInfo().freeArgs(); D.setInvalidType(); } else if (Proto->isVariadic()) { Diag(D.getIdentifierLoc(), diag::err_conv_function_variadic); diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp index c902e77870..885e52dd76 100644 --- a/lib/Sema/SemaExceptionSpec.cpp +++ b/lib/Sema/SemaExceptionSpec.cpp @@ -81,6 +81,7 @@ bool Sema::CheckSpecifiedExceptionType(QualType T, const SourceRange &Range) { /// to member to a function with an exception specification. This means that /// it is invalid to add another level of indirection. bool Sema::CheckDistantExceptionSpec(QualType T) { + T = T.IgnoreParens(); if (const PointerType *PT = T->getAs<PointerType>()) T = PT->getPointeeType(); else if (const MemberPointerType *PT = T->getAs<MemberPointerType>()) @@ -88,6 +89,7 @@ bool Sema::CheckDistantExceptionSpec(QualType T) { else return false; + T = T.IgnoreParens(); const FunctionProtoType *FnT = T->getAs<FunctionProtoType>(); if (!FnT) return false; diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index ad0d42a11a..7539a56965 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -4336,9 +4336,7 @@ Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope, MultiTemplateParamsArg TemplateParameterLists, Declarator &D) { assert(getCurFunctionDecl() == 0 && "Function parsing confused"); - assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function && - "Not a function declarator!"); - DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); if (FTI.hasPrototype) { // FIXME: Diagnose arguments without names in C. diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 5f86010602..23c159fbc5 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -521,6 +521,11 @@ QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc, return Context.getQualifiedType(T, Qs); } +/// \brief Build a paren type including \p T. +QualType Sema::BuildParenType(QualType T) { + return Context.getParenType(T); +} + /// \brief Build a pointer type. /// /// \param T The type to which we'll be building a pointer. @@ -1002,7 +1007,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // Check for auto functions and trailing return type and adjust the // return type accordingly. if (getLangOptions().CPlusPlus0x && D.isFunctionDeclarator()) { - const DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; + const DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); if (T == Context.UndeducedAutoTy) { if (FTI.TrailingReturnType) { T = GetTypeFromParser(ParsedType::getFromOpaquePtr(FTI.TrailingReturnType), @@ -1082,6 +1087,9 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, DeclaratorChunk &DeclType = D.getTypeObject(e-i-1); switch (DeclType.Kind) { default: assert(0 && "Unknown decltype!"); + case DeclaratorChunk::Paren: + T = BuildParenType(T); + break; case DeclaratorChunk::BlockPointer: // If blocks are disabled, emit an error. if (!LangOpts.Blocks) @@ -1678,6 +1686,11 @@ namespace { } // FIXME: exception specs } + void VisitParenTypeLoc(ParenTypeLoc TL) { + assert(Chunk.Kind == DeclaratorChunk::Paren); + TL.setLParenLoc(Chunk.Loc); + TL.setRParenLoc(Chunk.EndLoc); + } void VisitTypeLoc(TypeLoc TL) { llvm_unreachable("unsupported TypeLoc kind in declarator!"); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index c0bafc7cb0..9f6f84bec8 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -519,6 +519,14 @@ public: SourceLocation TemplateLoc, const TemplateArgumentListInfo &Args); + /// \brief Build a new parenthesized type. + /// + /// By default, builds a new ParenType type from the inner type. + /// Subclasses may override this routine to provide different behavior. + QualType RebuildParenType(QualType InnerType) { + return SemaRef.Context.getParenType(InnerType); + } + /// \brief Build a new qualified name type. /// /// By default, builds a new ElaboratedType type from the keyword, @@ -3372,6 +3380,28 @@ TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB, } template<typename Derived> +QualType +TreeTransform<Derived>::TransformParenType(TypeLocBuilder &TLB, + ParenTypeLoc TL) { + QualType Inner = getDerived().TransformType(TLB, TL.getInnerLoc()); + if (Inner.isNull()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + Inner != TL.getInnerLoc().getType()) { + Result = getDerived().RebuildParenType(Inner); + if (Result.isNull()) + return QualType(); + } + + ParenTypeLoc NewTL = TLB.push<ParenTypeLoc>(Result); + NewTL.setLParenLoc(TL.getLParenLoc()); + NewTL.setRParenLoc(TL.getRParenLoc()); + return Result; +} + +template<typename Derived> QualType TreeTransform<Derived>::TransformDependentNameType(TypeLocBuilder &TLB, DependentNameTypeLoc TL) { DependentNameType *T = TL.getTypePtr(); diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index c3c0aeae67..4e0a7b783b 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -2916,6 +2916,15 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { return T; } + case TYPE_PAREN: { + if (Record.size() != 1) { + Error("incorrect encoding of paren type"); + return QualType(); + } + QualType InnerType = GetType(Record[0]); + return Context->getParenType(InnerType); + } + case TYPE_ELABORATED: { unsigned Idx = 0; ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++]; @@ -3186,6 +3195,10 @@ void TypeLocReader::VisitTemplateSpecializationTypeLoc( TL.getTypePtr()->getArg(i).getKind(), Record, Idx)); } +void TypeLocReader::VisitParenTypeLoc(ParenTypeLoc TL) { + TL.setLParenLoc(ReadSourceLocation(Record, Idx)); + TL.setRParenLoc(ReadSourceLocation(Record, Idx)); +} void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { TL.setKeywordLoc(ReadSourceLocation(Record, Idx)); TL.setQualifierRange(Reader.ReadSourceRange(F, Record, Idx)); diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index e95e422fbd..7b405e9c8b 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -298,6 +298,11 @@ ASTTypeWriter::VisitDependentTemplateSpecializationType( Code = TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION; } +void ASTTypeWriter::VisitParenType(const ParenType *T) { + Writer.AddTypeRef(T->getInnerType(), Record); + Code = TYPE_PAREN; +} + void ASTTypeWriter::VisitElaboratedType(const ElaboratedType *T) { Record.push_back(T->getKeyword()); Writer.AddNestedNameSpecifier(T->getQualifier(), Record); @@ -467,6 +472,10 @@ void TypeLocWriter::VisitTemplateSpecializationTypeLoc( Writer.AddTemplateArgumentLocInfo(TL.getArgLoc(i).getArgument().getKind(), TL.getArgLoc(i).getLocInfo(), Record); } +void TypeLocWriter::VisitParenTypeLoc(ParenTypeLoc TL) { + Writer.AddSourceLocation(TL.getLParenLoc(), Record); + Writer.AddSourceLocation(TL.getRParenLoc(), Record); +} void TypeLocWriter::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { Writer.AddSourceLocation(TL.getKeywordLoc(), Record); Writer.AddSourceRange(TL.getQualifierRange(), Record); |