Initial support for writing templates to PCH.

llvm-svn: 106391
This commit is contained in:
Argyrios Kyrtzidis 2010-06-19 19:28:53 +00:00
parent bf5c3d42ba
commit 106caf92cd
10 changed files with 224 additions and 24 deletions

View File

@ -101,6 +101,14 @@ class TemplateName {
}
public:
// \brief Kind of name that is actually stored.
enum NameKind {
Template,
OverloadedTemplate,
QualifiedTemplate,
DependentTemplate
};
TemplateName() : Storage() { }
explicit TemplateName(TemplateDecl *Template) : Storage(Template) { }
explicit TemplateName(OverloadedTemplateStorage *Storage)
@ -110,6 +118,9 @@ public:
/// \brief Determine whether this template name is NULL.
bool isNull() const { return Storage.isNull(); }
// \brief Get the kind of name that is actually stored.
NameKind getKind() const;
/// \brief Retrieve the the underlying template declaration that
/// this template name refers to, if known.

View File

@ -417,7 +417,11 @@ namespace clang {
/// \brief An InjectedClassNameType record.
TYPE_INJECTED_CLASS_NAME = 27,
/// \brief An ObjCObjectType record.
TYPE_OBJC_OBJECT = 28
TYPE_OBJC_OBJECT = 28,
/// \brief An TemplateTypeParmType record.
TYPE_TEMPLATE_TYPE_PARM = 29,
/// \brief An TemplateSpecializationType record.
TYPE_TEMPLATE_SPECIALIZATION = 30
};
/// \brief The type IDs for special types constructed by semantic
@ -569,7 +573,6 @@ namespace clang {
// allocates the order in which
DECL_FRIEND,
DECL_FRIEND_TEMPLATE,
DECL_TEMPLATE,
DECL_CLASS_TEMPLATE,
DECL_CLASS_TEMPLATE_SPECIALIZATION,
DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION,

View File

@ -315,6 +315,12 @@ public:
/// \brief Emit a nested name specifier.
void AddNestedNameSpecifier(NestedNameSpecifier *NNS, RecordData &Record);
/// \brief Emit a template name.
void AddTemplateName(TemplateName Name, RecordData &Record);
/// \brief Emit a template argument.
void AddTemplateArgument(const TemplateArgument &Arg, RecordData &Record);
/// \brief Add a string to the given record.
void AddString(const std::string &Str, RecordData &Record);

View File

@ -21,6 +21,17 @@
using namespace clang;
using namespace llvm;
TemplateName::NameKind TemplateName::getKind() const {
if (Storage.is<TemplateDecl *>())
return Template;
if (Storage.is<OverloadedTemplateStorage *>())
return OverloadedTemplate;
if (Storage.is<QualifiedTemplateName *>())
return QualifiedTemplate;
assert(Storage.is<DependentTemplateName *>() && "There's a case unhandled!");
return DependentTemplate;
}
TemplateDecl *TemplateName::getAsTemplateDecl() const {
if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
return Template;

View File

@ -2207,6 +2207,14 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
QualType TST = GetType(Record[1]); // probably derivable
return Context->getInjectedClassNameType(D, TST);
}
case pch::TYPE_TEMPLATE_TYPE_PARM:
assert(false && "can't read template type parm types yet");
break;
case pch::TYPE_TEMPLATE_SPECIALIZATION:
assert(false && "can't read template specialization types yet");
break;
}
// Suppress a GCC warning
return QualType();

View File

@ -987,10 +987,6 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
case pch::DECL_FRIEND_TEMPLATE:
assert(false && "cannot read FriendTemplateDecl");
break;
case pch::DECL_TEMPLATE:
// FIXME: Should TemplateDecl be ABSTRACT_DECL???
assert(false && "TemplateDecl should be abstract!");
break;
case pch::DECL_CLASS_TEMPLATE:
assert(false && "cannot read ClassTemplateDecl");
break;

View File

@ -61,9 +61,7 @@ namespace {
#define TYPE(Class, Base) void Visit##Class##Type(const Class##Type *T);
#define ABSTRACT_TYPE(Class, Base)
#define DEPENDENT_TYPE(Class, Base)
#include "clang/AST/TypeNodes.def"
void VisitInjectedClassNameType(const InjectedClassNameType *T);
};
}
@ -169,13 +167,10 @@ void PCHTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {
Code = pch::TYPE_FUNCTION_PROTO;
}
#if 0
// For when we want it....
void PCHTypeWriter::VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
Writer.AddDeclRef(T->getDecl(), Record);
Code = pch::TYPE_UNRESOLVED_USING;
}
#endif
void PCHTypeWriter::VisitTypedefType(const TypedefType *T) {
Writer.AddDeclRef(T->getDecl(), Record);
@ -224,8 +219,47 @@ PCHTypeWriter::VisitSubstTemplateTypeParmType(
void
PCHTypeWriter::VisitTemplateSpecializationType(
const TemplateSpecializationType *T) {
Writer.AddTemplateName(T->getTemplateName(), Record);
Record.push_back(T->getNumArgs());
for (TemplateSpecializationType::iterator ArgI = T->begin(), ArgE = T->end();
ArgI != ArgE; ++ArgI)
Writer.AddTemplateArgument(*ArgI, Record);
Code = pch::TYPE_TEMPLATE_SPECIALIZATION;
}
void
PCHTypeWriter::VisitDependentSizedArrayType(const DependentSizedArrayType *T) {
// FIXME: Serialize this type (C++ only)
assert(false && "Cannot serialize template specialization types");
assert(false && "Cannot serialize dependent sized array types");
}
void
PCHTypeWriter::VisitDependentSizedExtVectorType(
const DependentSizedExtVectorType *T) {
// FIXME: Serialize this type (C++ only)
assert(false && "Cannot serialize dependent sized extended vector types");
}
void
PCHTypeWriter::VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
Record.push_back(T->getDepth());
Record.push_back(T->getIndex());
Record.push_back(T->isParameterPack());
Writer.AddIdentifierRef(T->getName(), Record);
Code = pch::TYPE_TEMPLATE_TYPE_PARM;
}
void
PCHTypeWriter::VisitDependentNameType(const DependentNameType *T) {
// FIXME: Serialize this type (C++ only)
assert(false && "Cannot serialize dependent name types");
}
void
PCHTypeWriter::VisitDependentTemplateSpecializationType(
const DependentTemplateSpecializationType *T) {
// FIXME: Serialize this type (C++ only)
assert(false && "Cannot serialize dependent template specialization types");
}
void PCHTypeWriter::VisitElaboratedType(const ElaboratedType *T) {
@ -1357,16 +1391,7 @@ void PCHWriter::WriteType(QualType T) {
#define TYPE(Class, Base) \
case Type::Class: W.Visit##Class##Type(cast<Class##Type>(T)); break;
#define ABSTRACT_TYPE(Class, Base)
#define DEPENDENT_TYPE(Class, Base)
#include "clang/AST/TypeNodes.def"
// For all of the dependent type nodes (which only occur in C++
// templates), produce an error.
#define TYPE(Class, Base)
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
#include "clang/AST/TypeNodes.def"
assert(false && "Cannot serialize dependent type nodes");
break;
}
}
@ -2469,3 +2494,72 @@ void PCHWriter::AddNestedNameSpecifier(NestedNameSpecifier *NNS,
}
}
}
void PCHWriter::AddTemplateName(TemplateName Name, RecordData &Record) {
TemplateName::NameKind Kind = Name.getKind();
Record.push_back(Kind);
switch (Kind) {
case TemplateName::Template:
AddDeclRef(Name.getAsTemplateDecl(), Record);
break;
case TemplateName::OverloadedTemplate: {
OverloadedTemplateStorage *OvT = Name.getAsOverloadedTemplate();
Record.push_back(OvT->size());
for (OverloadedTemplateStorage::iterator I = OvT->begin(), E = OvT->end();
I != E; ++I)
AddDeclRef(*I, Record);
break;
}
case TemplateName::QualifiedTemplate: {
QualifiedTemplateName *QualT = Name.getAsQualifiedTemplateName();
AddNestedNameSpecifier(QualT->getQualifier(), Record);
Record.push_back(QualT->hasTemplateKeyword());
AddDeclRef(QualT->getTemplateDecl(), Record);
break;
}
case TemplateName::DependentTemplate: {
DependentTemplateName *DepT = Name.getAsDependentTemplateName();
AddNestedNameSpecifier(DepT->getQualifier(), Record);
Record.push_back(DepT->isIdentifier());
if (DepT->isIdentifier())
AddIdentifierRef(DepT->getIdentifier(), Record);
else
Record.push_back(DepT->getOperator());
break;
}
}
}
void PCHWriter::AddTemplateArgument(const TemplateArgument &Arg,
RecordData &Record) {
Record.push_back(Arg.getKind());
switch (Arg.getKind()) {
case TemplateArgument::Null:
break;
case TemplateArgument::Type:
AddTypeRef(Arg.getAsType(), Record);
break;
case TemplateArgument::Declaration:
AddDeclRef(Arg.getAsDecl(), Record);
break;
case TemplateArgument::Integral:
AddAPSInt(*Arg.getAsIntegral(), Record);
AddTypeRef(Arg.getIntegralType(), Record);
break;
case TemplateArgument::Template:
AddTemplateName(Arg.getAsTemplate(), Record);
break;
case TemplateArgument::Expression:
AddStmt(Arg.getAsExpr());
break;
case TemplateArgument::Pack:
Record.push_back(Arg.pack_size());
for (TemplateArgument::pack_iterator I=Arg.pack_begin(), E=Arg.pack_end();
I != E; ++I)
AddTemplateArgument(*I, Record);
break;
}
}

View File

@ -574,6 +574,23 @@ void PCHDeclWriter::WriteCXXBaseSpecifier(const CXXBaseSpecifier *Base) {
void PCHDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) {
// assert(false && "cannot write CXXRecordDecl");
VisitRecordDecl(D);
enum {
CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization
};
if (ClassTemplateDecl *TemplD = D->getDescribedClassTemplate()) {
Record.push_back(CXXRecTemplate);
Writer.AddDeclRef(TemplD, Record);
} else if (MemberSpecializationInfo *MSInfo
= D->getMemberSpecializationInfo()) {
Record.push_back(CXXRecMemberSpecialization);
Writer.AddDeclRef(MSInfo->getInstantiatedFrom(), Record);
Record.push_back(MSInfo->getTemplateSpecializationKind());
Writer.AddSourceLocation(MSInfo->getPointOfInstantiation(), Record);
} else {
Record.push_back(CXXRecNotTemplate);
}
if (D->isDefinition()) {
unsigned NumBases = D->getNumBases();
Record.push_back(NumBases);
@ -619,11 +636,49 @@ void PCHDeclWriter::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
}
void PCHDeclWriter::VisitTemplateDecl(TemplateDecl *D) {
assert(false && "cannot write TemplateDecl");
VisitNamedDecl(D);
Writer.AddDeclRef(D->getTemplatedDecl(), Record);
{
// TemplateParams.
TemplateParameterList *TPL = D->getTemplateParameters();
assert(TPL && "No TemplateParameters!");
Writer.AddSourceLocation(TPL->getTemplateLoc(), Record);
Writer.AddSourceLocation(TPL->getLAngleLoc(), Record);
Writer.AddSourceLocation(TPL->getRAngleLoc(), Record);
Record.push_back(TPL->size());
for (TemplateParameterList::iterator P = TPL->begin(), PEnd = TPL->end();
P != PEnd; ++P)
Writer.AddDeclRef(*P, Record);
}
}
void PCHDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
assert(false && "cannot write ClassTemplateDecl");
VisitTemplateDecl(D);
Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
if (D->getPreviousDeclaration() == 0) {
// This ClassTemplateDecl owns the CommonPtr; write it.
typedef llvm::FoldingSet<ClassTemplateSpecializationDecl> CTSDSetTy;
CTSDSetTy &CTSDSet = D->getSpecializations();
Record.push_back(CTSDSet.size());
for (CTSDSetTy::iterator I=CTSDSet.begin(), E = CTSDSet.end(); I!=E; ++I)
Writer.AddDeclRef(&*I, Record);
typedef llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> CTPSDSetTy;
CTPSDSetTy &CTPSDSet = D->getPartialSpecializations();
Record.push_back(CTPSDSet.size());
for (CTPSDSetTy::iterator I=CTPSDSet.begin(), E = CTPSDSet.end(); I!=E; ++I)
Writer.AddDeclRef(&*I, Record);
// InjectedClassNameType is computed, no need to write it.
Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record);
if (D->getInstantiatedFromMemberTemplate())
Record.push_back(D->isMemberSpecialization());
}
Code = pch::DECL_CLASS_TEMPLATE;
}
void PCHDeclWriter::VisitClassTemplateSpecializationDecl(
@ -641,7 +696,14 @@ void PCHDeclWriter::visitFunctionTemplateDecl(FunctionTemplateDecl *D) {
}
void PCHDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
assert(false && "cannot write TemplateTypeParmDecl");
VisitTypeDecl(D);
Record.push_back(D->wasDeclaredWithTypename());
Record.push_back(D->isParameterPack());
Record.push_back(D->defaultArgumentWasInherited());
Writer.AddTypeSourceInfo(D->getDefaultArgumentInfo(), Record);
Code = pch::DECL_TEMPLATE_TYPE_PARM;
}
void PCHDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {

View File

@ -0,0 +1,3 @@
// RUN: %clang_cc1 -x c++-header -emit-pch -o %t %S/cxx-templates.h
// Placeholder for stuff using the header.

View File

@ -0,0 +1,6 @@
// Header for PCH test cxx-templates.cpp
template <typename T>
struct S {
T x;
};