From aaba5e346dffdbad5d1c42765a89e4a7afb0da67 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 4 Feb 2009 19:02:06 +0000 Subject: [PATCH] Basic representation of C++ class templates, from Andrew Sutton. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63750 91177308-0d34-0410-b5e6-96231b3b80d8 --- Driver/ASTConsumers.cpp | 15 ++ include/clang/AST/AST.h | 1 + include/clang/AST/DeclBase.h | 4 + include/clang/AST/DeclCXX.h | 92 --------- include/clang/AST/DeclNodes.def | 5 + include/clang/AST/DeclTemplate.h | 325 ++++++++++++++++++++++++++++++ include/clang/AST/Type.h | 2 + include/clang/Parse/Action.h | 31 ++- lib/AST/ASTContext.cpp | 1 + lib/AST/CMakeLists.txt | 1 + lib/AST/DeclBase.cpp | 3 +- lib/AST/DeclCXX.cpp | 30 --- lib/AST/DeclSerialization.cpp | 48 ++++- lib/AST/DeclTemplate.cpp | 108 ++++++++++ lib/AST/Expr.cpp | 1 + lib/AST/Type.cpp | 1 + lib/Parse/ParseDecl.cpp | 2 +- lib/Parse/ParseDeclCXX.cpp | 12 +- lib/Parse/ParseTemplate.cpp | 39 ++-- lib/Parse/Parser.cpp | 1 - lib/Sema/Sema.h | 21 +- lib/Sema/SemaDecl.cpp | 46 ++++- lib/Sema/SemaDeclCXX.cpp | 1 + lib/Sema/SemaExpr.cpp | 1 + lib/Sema/SemaLookup.cpp | 2 +- lib/Sema/SemaTemplate.cpp | 70 ++++++- test/Parser/cxx-template-decl.cpp | 6 +- 27 files changed, 690 insertions(+), 179 deletions(-) create mode 100644 include/clang/AST/DeclTemplate.h create mode 100644 lib/AST/DeclTemplate.cpp diff --git a/Driver/ASTConsumers.cpp b/Driver/ASTConsumers.cpp index 6fec595e51..78b199680a 100644 --- a/Driver/ASTConsumers.cpp +++ b/Driver/ASTConsumers.cpp @@ -52,6 +52,8 @@ namespace { void PrintObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID); void PrintObjCPropertyDecl(ObjCPropertyDecl *PD); void PrintObjCPropertyImplDecl(ObjCPropertyImplDecl *PID); + + void PrintTemplateDecl(TemplateDecl *TD); }; } // end anonymous namespace @@ -116,6 +118,8 @@ void DeclPrinter:: PrintDecl(Decl *D) { Out << "};\n"; } else if (TagDecl *TD = dyn_cast(D)) { Out << "Read top-level tag decl: '" << TD->getNameAsString() << "'\n"; + } else if (TemplateDecl *TempD = dyn_cast(D)) { + PrintTemplateDecl(TempD); } else if (LinkageSpecDecl *LSD = dyn_cast(D)) { PrintLinkageSpec(LSD); } else if (FileScopeAsmDecl *AD = dyn_cast(D)) { @@ -437,6 +441,17 @@ void DeclPrinter::PrintObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) { Out << "=" << PID->getPropertyIvarDecl()->getNameAsString(); Out << ";\n"; } + +/// PrintTemplateParams - Print a template parameter list and recursively print +/// it's underlying top-level definition. +void DeclPrinter::PrintTemplateDecl(TemplateDecl *TD) { + // TODO: Write template parameters. + Out << "template <...> "; + PrintDecl(TD->getTemplatedDecl()); +} + + + //===----------------------------------------------------------------------===// /// ASTPrinter - Pretty-printer of ASTs diff --git a/include/clang/AST/AST.h b/include/clang/AST/AST.h index 96e887cfc0..164c5fbbb6 100644 --- a/include/clang/AST/AST.h +++ b/include/clang/AST/AST.h @@ -19,6 +19,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/Type.h" diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 3aaadedb15..eaecb1e5c8 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -237,6 +237,10 @@ public: return IDNS_Tag; case Namespace: + case Template: + case FunctionTemplate: + case ClassTemplate: + case TemplateTemplateParm: return IdentifierNamespace(IDNS_Tag | IDNS_Ordinary); } } diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 7c248fd9e3..e41dc1802d 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -24,70 +24,6 @@ class CXXDestructorDecl; class CXXConversionDecl; class CXXMethodDecl; -/// TemplateTypeParmDecl - Declaration of a template type parameter, -/// e.g., "T" in -/// @code -/// template class vector; -/// @endcode -class TemplateTypeParmDecl : public TypeDecl { - /// Typename - Whether this template type parameter was declaration - /// with the 'typename' keyword. If false, it was declared with the - /// 'class' keyword. - bool Typename : 1; - - TemplateTypeParmDecl(DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, bool Typename) - : TypeDecl(TemplateTypeParm, DC, L, Id), Typename(Typename) { } - -public: - static TemplateTypeParmDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - bool Typename); - - /// wasDeclarationWithTypename - Whether this template type - /// parameter was declared with the 'typename' keyword. If not, it - /// was declared with the 'class' keyword. - bool wasDeclaredWithTypename() const { return Typename; } - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { - return D->getKind() == TemplateTypeParm; - } - static bool classof(const TemplateTypeParmDecl *D) { return true; } - -protected: - /// EmitImpl - Serialize this TemplateTypeParmDecl. Called by Decl::Emit. - virtual void EmitImpl(llvm::Serializer& S) const; - - /// CreateImpl - Deserialize a TemplateTypeParmDecl. Called by Decl::Create. - static TemplateTypeParmDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C); - - friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C); -}; - -/// NonTypeTemplateParmDecl - Declares a non-type template parameter, -/// e.g., "Size" in -/// @code -/// template class array { }; -/// @endcode -class NonTypeTemplateParmDecl : public VarDecl { - NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, QualType T, - SourceLocation TSSL = SourceLocation()) - : VarDecl(NonTypeTemplateParm, DC, L, Id, T, VarDecl::None, TSSL) { } - -public: - static NonTypeTemplateParmDecl * - Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - QualType T, SourceLocation TypeSpecStartLoc = SourceLocation()); - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { - return D->getKind() == NonTypeTemplateParm; - } - static bool classof(const NonTypeTemplateParmDecl *D) { return true; } -}; - /// OverloadedFunctionDecl - An instance of this class represents a /// set of overloaded functions. All of the functions have the same /// name and occur within the same scope. @@ -1024,34 +960,6 @@ public: friend class DeclContext; }; -/// TemplateParameterList - Stores a list of template parameters. -class TemplateParameterList { - /// NumParams - The number of template parameters in this template - /// parameter list. - unsigned NumParams; - - TemplateParameterList(Decl **Params, unsigned NumParams); - -public: - static TemplateParameterList *Create(ASTContext &C, Decl **Params, - unsigned NumParams); - - /// iterator - Iterates through the template parameters in this list. - typedef Decl** iterator; - - /// const_iterator - Iterates through the template parameters in this list. - typedef Decl* const* const_iterator; - - iterator begin() { return reinterpret_cast(this + 1); } - const_iterator begin() const { - return reinterpret_cast(this + 1); - } - iterator end() { return begin() + NumParams; } - const_iterator end() const { return begin() + NumParams; } - - unsigned size() const { return NumParams; } -}; - } // end namespace clang #endif diff --git a/include/clang/AST/DeclNodes.def b/include/clang/AST/DeclNodes.def index 17a8bc3835..195553ccef 100644 --- a/include/clang/AST/DeclNodes.def +++ b/include/clang/AST/DeclNodes.def @@ -97,6 +97,10 @@ ABSTRACT_DECL(Named, Decl) DECL(ParmVar, VarDecl) DECL(OriginalParmVar, ParmVarDecl) DECL(NonTypeTemplateParm, VarDecl) + DECL(Template, NamedDecl) + DECL(FunctionTemplate, TemplateDecl) + DECL(ClassTemplate, TemplateDecl) + DECL(TemplateTemplateParm, TemplateDecl) DECL(ObjCMethod, NamedDecl) DECL(ObjCContainer, NamedDecl) DECL(ObjCCategory, ObjCContainerDecl) @@ -139,6 +143,7 @@ DECL_RANGE(Tag, Enum, CXXRecord) DECL_RANGE(Record, Record, CXXRecord) DECL_RANGE(Value, EnumConstant, NonTypeTemplateParm) DECL_RANGE(Function, Function, CXXConversion) +DECL_RANGE(Template, Template, TemplateTemplateParm) LAST_DECL_RANGE(Var, Var, NonTypeTemplateParm) #undef LAST_DECL_RANGE diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h new file mode 100644 index 0000000000..98fd42df43 --- /dev/null +++ b/include/clang/AST/DeclTemplate.h @@ -0,0 +1,325 @@ +//===-- DeclTemplate.h - Classes for representing C++ templates -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the C++ template declaration subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_DECLTEMPLATE_H +#define LLVM_CLANG_AST_DECLTEMPLATE_H + +namespace clang { + +class TemplateParameterList; +class TemplateDecl; +class FunctionTemplateDecl; +class ClassTemplateDecl; +class TemplateTypeParmDecl; +class NonTypeTemplateParmDecl; +class TemplateTemplateParmDecl; + +/// TemplateParameterList - Stores a list of template parameters for a +/// TemplateDecl and its derived classes. +class TemplateParameterList { + /// NumParams - The number of template parameters in this template + /// parameter list. + unsigned NumParams; + + TemplateParameterList(Decl **Params, unsigned NumParams); + +public: + static TemplateParameterList *Create(ASTContext &C, Decl **Params, + unsigned NumParams); + + /// iterator - Iterates through the template parameters in this list. + typedef Decl** iterator; + + /// const_iterator - Iterates through the template parameters in this list. + typedef Decl* const* const_iterator; + + iterator begin() { return reinterpret_cast(this + 1); } + const_iterator begin() const { + return reinterpret_cast(this + 1); + } + iterator end() { return begin() + NumParams; } + const_iterator end() const { return begin() + NumParams; } + + unsigned size() const { return NumParams; } +}; + +//===----------------------------------------------------------------------===// +// Kinds of Templates +//===----------------------------------------------------------------------===// + +/// TemplateDecl - The base class of all kinds of template declarations (e.g., +/// class, function, etc.). The TemplateDecl class stores the list of template +/// parameters and a reference to the templated scoped declaration: the +/// underlying AST node. +class TemplateDecl : public NamedDecl { +protected: + // This is probably never used. + TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, + DeclarationName Name) + : NamedDecl(DK, DC, L, Name), TemplatedDecl(0), TemplateParams(0) + { } + + // Construct a template decl with the given name and parameters. + // Used when there is not templated element (tt-params, alias?). + TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, + DeclarationName Name, TemplateParameterList *Params) + : NamedDecl(DK, DC, L, Name), TemplatedDecl(0), TemplateParams(Params) + { } + + // Construct a template decl with name, parameters, and templated element. + TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, + DeclarationName Name, TemplateParameterList *Params, + NamedDecl *Decl) + : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl), + TemplateParams(Params) { } +public: + ~TemplateDecl(); + + /// Get the list of template parameters + TemplateParameterList *GetTemplateParameters() const { + return TemplateParams; + } + + /// Get the underlying, templated declaration. + NamedDecl *getTemplatedDecl() const { return TemplatedDecl; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() >= TemplateFirst && D->getKind() <= TemplateLast; + } + static bool classof(const TemplateDecl *D) { return true; } + static bool classof(const FunctionTemplateDecl *D) { return true; } + static bool classof(const ClassTemplateDecl *D) { return true; } + static bool classof(const TemplateTemplateParmDecl *D) { return true; } + +protected: + NamedDecl *TemplatedDecl; + TemplateParameterList* TemplateParams; +}; + +/// Declaration of a template function. +class FunctionTemplateDecl : public TemplateDecl { +protected: + FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, + TemplateParameterList *Params, NamedDecl *Decl) + : TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl) { } +public: + /// Get the underling function declaration of the template. + FunctionDecl *getTemplatedDecl() const { + return static_cast(TemplatedDecl); + } + + /// Create a template function node. + static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, + DeclarationName Name, + TemplateParameterList *Params, + NamedDecl *Decl); + + // Implement isa/cast/dyncast support + static bool classof(const Decl *D) + { return D->getKind() == FunctionTemplate; } + static bool classof(const FunctionTemplateDecl *D) + { return true; } +}; + +/// Declaration of a template class. +class ClassTemplateDecl : public TemplateDecl { +protected: + ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, + TemplateParameterList *Params, NamedDecl *Decl) + : TemplateDecl(ClassTemplate, DC, L, Name, Params, Decl) { } +public: + /// Get the underlying class declarations of the template. + CXXRecordDecl *getTemplatedDecl() const { + return static_cast(TemplatedDecl); + } + + /// Create a class teplate node. + static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, + DeclarationName Name, + TemplateParameterList *Params, + NamedDecl *Decl); + + // Implement isa/cast/dyncast support + static bool classof(const Decl *D) + { return D->getKind() == ClassTemplate; } + static bool classof(const ClassTemplateDecl *D) + { return true; } +}; + +//===----------------------------------------------------------------------===// +// Kinds of Template Parameters +//===----------------------------------------------------------------------===// + + +/// The TemplateParmPosition class defines the position of a template parameter +/// within a template parameter list. Because template parameter can be listed +/// sequentially for out-of-line template members, each template parameter is +/// given a Depth - the nesting of template parameter scopes - and a Position - +/// the occurrence within the parameter list. +/// This class is inheritedly privately by different kinds of template +/// parameters and is not part of the Decl hierarchy. Just a facility. +class TemplateParmPosition +{ +protected: + // FIXME: This should probably never be called, but it's here as + TemplateParmPosition() + : Depth(0), Position(0) + { /* assert(0 && "Cannot create positionless template parameter"); */ } + + TemplateParmPosition(unsigned D, unsigned P) + : Depth(D), Position(P) + { } + + // FIXME: These probably don't need to be ints. int:5 for depth, int:8 for + // position? Maybe? + unsigned Depth; + unsigned Position; + +public: + /// Get the nesting depth of the template parameter. + unsigned getDepth() const { return Depth; } + + /// Get the position of the template parameter within its parameter list. + unsigned getPosition() const { return Position; } +}; + +/// TemplateTypeParmDecl - Declaration of a template type parameter, +/// e.g., "T" in +/// @code +/// template class vector; +/// @endcode +class TemplateTypeParmDecl + : public TypeDecl, protected TemplateParmPosition { + /// Typename - Whether this template type parameter was declaration + /// with the 'typename' keyword. If false, it was declared with the + /// 'class' keyword. + bool Typename : 1; + + TemplateTypeParmDecl(DeclContext *DC, SourceLocation L, unsigned D, + unsigned P, IdentifierInfo *Id, bool Typename) + : TypeDecl(TemplateTypeParm, DC, L, Id), TemplateParmPosition(D, P), + Typename(Typename) { } +public: + static TemplateTypeParmDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, unsigned D, unsigned P, + IdentifierInfo *Id, bool Typename); + + /// wasDeclarationWithTypename - Whether this template type + /// parameter was declared with the 'typename' keyword. If not, it + /// was declared with the 'class' keyword. + bool wasDeclaredWithTypename() const { return Typename; } + + using TemplateParmPosition::getDepth; + using TemplateParmPosition::getPosition; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() == TemplateTypeParm; + } + static bool classof(const TemplateTypeParmDecl *D) { return true; } + +protected: + /// EmitImpl - Serialize this TemplateTypeParmDecl. Called by Decl::Emit. + virtual void EmitImpl(llvm::Serializer& S) const; + + /// CreateImpl - Deserialize a TemplateTypeParmDecl. Called by Decl::Create. + static TemplateTypeParmDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C); + + friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C); +}; + +/// NonTypeTemplateParmDecl - Declares a non-type template parameter, +/// e.g., "Size" in +/// @code +/// template class array { }; +/// @endcode +class NonTypeTemplateParmDecl + : public VarDecl, protected TemplateParmPosition { + NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, + unsigned P, IdentifierInfo *Id, QualType T, + SourceLocation TSSL = SourceLocation()) + : VarDecl(NonTypeTemplateParm, DC, L, Id, T, VarDecl::None, TSSL), + TemplateParmPosition(D, P) { } +public: + static NonTypeTemplateParmDecl * + Create(ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, + unsigned P, IdentifierInfo *Id, QualType T, + SourceLocation TypeSpecStartLoc = SourceLocation()); + + using TemplateParmPosition::getDepth; + using TemplateParmPosition::getPosition; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() == NonTypeTemplateParm; + } + static bool classof(const NonTypeTemplateParmDecl *D) { return true; } + +protected: + /// EmitImpl - Serialize this TemplateTypeParmDecl. Called by Decl::Emit. + virtual void EmitImpl(llvm::Serializer& S) const; + + /// CreateImpl - Deserialize a TemplateTypeParmDecl. Called by Decl::Create. + static NonTypeTemplateParmDecl* CreateImpl(llvm::Deserializer& D, + ASTContext& C); + + friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C); +}; + +/// TemplateTemplateParmDecl - Declares a template template parameter, +/// e.g., "T" in +/// @code +/// template