From 69da4a8f0787fe3ee2200dabcb17dbfbf2d1c545 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Tue, 22 Jun 2010 09:55:07 +0000 Subject: [PATCH] Support emitting/reading function templates to/from PCH. llvm-svn: 106534 --- clang/lib/Frontend/PCHReaderDecl.cpp | 92 ++++++++++++++++++++++++++-- clang/lib/Frontend/PCHWriterDecl.cpp | 77 +++++++++++++++++++++-- clang/test/PCH/cxx-templates.cpp | 4 ++ clang/test/PCH/cxx-templates.h | 5 ++ 4 files changed, 169 insertions(+), 9 deletions(-) diff --git a/clang/lib/Frontend/PCHReaderDecl.cpp b/clang/lib/Frontend/PCHReaderDecl.cpp index d84eb085cf5b..b8046578aee8 100644 --- a/clang/lib/Frontend/PCHReaderDecl.cpp +++ b/clang/lib/Frontend/PCHReaderDecl.cpp @@ -74,7 +74,7 @@ namespace { void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); void VisitTemplateDecl(TemplateDecl *D); void VisitClassTemplateDecl(ClassTemplateDecl *D); - void visitFunctionTemplateDecl(FunctionTemplateDecl *D); + void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); void VisitUsingDecl(UsingDecl *D); void VisitUsingShadowDecl(UsingShadowDecl *D); @@ -214,8 +214,71 @@ void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) { FD->setCopyAssignment(Record[Idx++]); FD->setHasImplicitReturnZero(Record[Idx++]); FD->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++])); - // FIXME: C++ TemplateOrInstantiation + switch ((FunctionDecl::TemplatedKind)Record[Idx++]) { + case FunctionDecl::TK_NonTemplate: + break; + case FunctionDecl::TK_FunctionTemplate: + FD->setDescribedFunctionTemplate( + cast(Reader.GetDecl(Record[Idx++]))); + break; + case FunctionDecl::TK_MemberSpecialization: { + FunctionDecl *InstFD = cast(Reader.GetDecl(Record[Idx++])); + TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; + SourceLocation POI = Reader.ReadSourceLocation(Record, Idx); + FD->setInstantiationOfMemberFunction(InstFD, TSK); + FD->getMemberSpecializationInfo()->setPointOfInstantiation(POI); + break; + } + case FunctionDecl::TK_FunctionTemplateSpecialization: { + FunctionTemplateDecl *Template + = cast(Reader.GetDecl(Record[Idx++])); + TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; + + // Template arguments. + unsigned NumTemplateArgs = Record[Idx++]; + llvm::SmallVector TemplArgs; + TemplArgs.reserve(NumTemplateArgs); + for (unsigned i=0; i != NumTemplateArgs; ++i) + TemplArgs.push_back(Reader.ReadTemplateArgument(Record, Idx)); + + // Template args as written. + unsigned NumTemplateArgLocs = Record[Idx++]; + llvm::SmallVector TemplArgLocs; + TemplArgLocs.reserve(NumTemplateArgLocs); + for (unsigned i=0; i != NumTemplateArgLocs; ++i) + TemplArgLocs.push_back(Reader.ReadTemplateArgumentLoc(Record, Idx)); + + SourceLocation LAngleLoc, RAngleLoc; + if (NumTemplateArgLocs) { + LAngleLoc = Reader.ReadSourceLocation(Record, Idx); + RAngleLoc = Reader.ReadSourceLocation(Record, Idx); + } + + FD->setFunctionTemplateSpecialization(Template, NumTemplateArgs, + TemplArgs.data(), TSK, + NumTemplateArgLocs, + NumTemplateArgLocs ? TemplArgLocs.data() : 0, + LAngleLoc, RAngleLoc); + } + case FunctionDecl::TK_DependentFunctionTemplateSpecialization: { + // Templates. + UnresolvedSet<8> TemplDecls; + unsigned NumTemplates = Record[Idx++]; + while (NumTemplates--) + TemplDecls.addDecl(cast(Reader.GetDecl(Record[Idx++]))); + + // Templates args. + TemplateArgumentListInfo TemplArgs; + unsigned NumArgs = Record[Idx++]; + while (NumArgs--) + TemplArgs.addArgument(Reader.ReadTemplateArgumentLoc(Record, Idx)); + + FD->setDependentTemplateSpecialization(*Reader.getContext(), + TemplDecls, TemplArgs); + } + } + // Read in the parameters. unsigned NumParams = Record[Idx++]; llvm::SmallVector Params; @@ -725,8 +788,26 @@ void PCHDeclReader::VisitClassTemplatePartialSpecializationDecl( assert(false && "cannot read ClassTemplatePartialSpecializationDecl"); } -void PCHDeclReader::visitFunctionTemplateDecl(FunctionTemplateDecl *D) { - assert(false && "cannot read FunctionTemplateDecl"); +void PCHDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { + VisitTemplateDecl(D); + + FunctionTemplateDecl *PrevDecl = + cast_or_null(Reader.GetDecl(Record[Idx++])); + D->setPreviousDeclaration(PrevDecl); + if (PrevDecl == 0) { + // This FunctionTemplateDecl owns a CommonPtr; read it. + + // FunctionTemplateSpecializationInfos are filled through the + // templated FunctionDecl's setFunctionTemplateSpecialization, no need to + // read them here. + + if (FunctionTemplateDecl *CTD + = cast_or_null(Reader.GetDecl(Record[Idx++]))) { + D->setInstantiatedFromMemberTemplate(CTD); + if (Record[Idx++]) + D->setMemberSpecialization(); + } + } } void PCHDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { @@ -1095,7 +1176,8 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) { assert(false && "cannot read ClassTemplatePartialSpecializationDecl"); break; case pch::DECL_FUNCTION_TEMPLATE: - assert(false && "cannot read FunctionTemplateDecl"); + D = FunctionTemplateDecl::Create(*Context, 0, SourceLocation(), + DeclarationName(), 0, 0); break; case pch::DECL_TEMPLATE_TYPE_PARM: D = TemplateTypeParmDecl::Create(*Context, 0, SourceLocation(), 0,0,0,0,0); diff --git a/clang/lib/Frontend/PCHWriterDecl.cpp b/clang/lib/Frontend/PCHWriterDecl.cpp index 4ea764d91920..05414d5fc71c 100644 --- a/clang/lib/Frontend/PCHWriterDecl.cpp +++ b/clang/lib/Frontend/PCHWriterDecl.cpp @@ -75,7 +75,7 @@ namespace { void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); void VisitTemplateDecl(TemplateDecl *D); void VisitClassTemplateDecl(ClassTemplateDecl *D); - void visitFunctionTemplateDecl(FunctionTemplateDecl *D); + void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); void VisitUsingDecl(UsingDecl *D); void VisitUsingShadowDecl(UsingShadowDecl *D); @@ -221,8 +221,63 @@ void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) { Record.push_back(D->isTrivial()); Record.push_back(D->isCopyAssignment()); Record.push_back(D->hasImplicitReturnZero()); - // FIXME: C++ TemplateOrInstantiation??? Writer.AddSourceLocation(D->getLocEnd(), Record); + + Record.push_back(D->getTemplatedKind()); + switch (D->getTemplatedKind()) { + case FunctionDecl::TK_NonTemplate: + break; + case FunctionDecl::TK_FunctionTemplate: + Writer.AddDeclRef(D->getDescribedFunctionTemplate(), Record); + break; + case FunctionDecl::TK_MemberSpecialization: { + MemberSpecializationInfo *MemberInfo = D->getMemberSpecializationInfo(); + Writer.AddDeclRef(MemberInfo->getInstantiatedFrom(), Record); + Record.push_back(MemberInfo->getTemplateSpecializationKind()); + Writer.AddSourceLocation(MemberInfo->getPointOfInstantiation(), Record); + break; + } + case FunctionDecl::TK_FunctionTemplateSpecialization: { + FunctionTemplateSpecializationInfo * + FTSInfo = D->getTemplateSpecializationInfo(); + Writer.AddDeclRef(FTSInfo->getTemplate(), Record); + Record.push_back(FTSInfo->getTemplateSpecializationKind()); + + // Template arguments. + assert(FTSInfo->TemplateArguments && "No template args!"); + Record.push_back(FTSInfo->TemplateArguments->flat_size()); + for (int i=0, e = FTSInfo->TemplateArguments->flat_size(); i != e; ++i) + Writer.AddTemplateArgument(FTSInfo->TemplateArguments->get(i), Record); + + // Template args as written. + if (FTSInfo->TemplateArgumentsAsWritten) { + Record.push_back(FTSInfo->TemplateArgumentsAsWritten->size()); + for (int i=0, e = FTSInfo->TemplateArgumentsAsWritten->size(); i!=e; ++i) + Writer.AddTemplateArgumentLoc((*FTSInfo->TemplateArgumentsAsWritten)[i], + Record); + Writer.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->getLAngleLoc(), + Record); + Writer.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->getRAngleLoc(), + Record); + } else { + Record.push_back(0); + } + } + case FunctionDecl::TK_DependentFunctionTemplateSpecialization: { + DependentFunctionTemplateSpecializationInfo * + DFTSInfo = D->getDependentSpecializationInfo(); + + // Templates. + Record.push_back(DFTSInfo->getNumTemplates()); + for (int i=0, e = DFTSInfo->getNumTemplates(); i != e; ++i) + Writer.AddDeclRef(DFTSInfo->getTemplate(i), Record); + + // Templates args. + Record.push_back(DFTSInfo->getNumTemplateArgs()); + for (int i=0, e = DFTSInfo->getNumTemplateArgs(); i != e; ++i) + Writer.AddTemplateArgumentLoc(DFTSInfo->getTemplateArg(i), Record); + } + } Record.push_back(D->param_size()); for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end(); @@ -701,8 +756,22 @@ void PCHDeclWriter::VisitClassTemplatePartialSpecializationDecl( assert(false && "cannot write ClassTemplatePartialSpecializationDecl"); } -void PCHDeclWriter::visitFunctionTemplateDecl(FunctionTemplateDecl *D) { - assert(false && "cannot write FunctionTemplateDecl"); +void PCHDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { + VisitTemplateDecl(D); + + Writer.AddDeclRef(D->getPreviousDeclaration(), Record); + if (D->getPreviousDeclaration() == 0) { + // This FunctionTemplateDecl owns the CommonPtr; write it. + + // FunctionTemplateSpecializationInfos are filled through the + // templated FunctionDecl's setFunctionTemplateSpecialization, no need to + // write them here. + + Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record); + if (D->getInstantiatedFromMemberTemplate()) + Record.push_back(D->isMemberSpecialization()); + } + Code = pch::DECL_FUNCTION_TEMPLATE; } void PCHDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { diff --git a/clang/test/PCH/cxx-templates.cpp b/clang/test/PCH/cxx-templates.cpp index 948763a5905a..4f66da03461e 100644 --- a/clang/test/PCH/cxx-templates.cpp +++ b/clang/test/PCH/cxx-templates.cpp @@ -2,3 +2,7 @@ // RUN: %clang_cc1 -include-pch %t -fsyntax-only %s S v; + +void test() { + int x = templ_f(3); +} diff --git a/clang/test/PCH/cxx-templates.h b/clang/test/PCH/cxx-templates.h index 74885f059097..bfd499ba0287 100644 --- a/clang/test/PCH/cxx-templates.h +++ b/clang/test/PCH/cxx-templates.h @@ -4,3 +4,8 @@ template struct S { T x; }; + +template +T templ_f(T x) { + return x; +}