diff options
-rw-r--r-- | Driver/ASTConsumers.cpp | 15 | ||||
-rw-r--r-- | include/clang/AST/AST.h | 1 | ||||
-rw-r--r-- | include/clang/AST/DeclBase.h | 4 | ||||
-rw-r--r-- | include/clang/AST/DeclCXX.h | 92 | ||||
-rw-r--r-- | include/clang/AST/DeclNodes.def | 5 | ||||
-rw-r--r-- | include/clang/AST/DeclTemplate.h | 325 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 2 | ||||
-rw-r--r-- | include/clang/Parse/Action.h | 31 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 1 | ||||
-rw-r--r-- | lib/AST/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/AST/DeclBase.cpp | 3 | ||||
-rw-r--r-- | lib/AST/DeclCXX.cpp | 30 | ||||
-rw-r--r-- | lib/AST/DeclSerialization.cpp | 48 | ||||
-rw-r--r-- | lib/AST/DeclTemplate.cpp | 108 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 1 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 1 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 2 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 12 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 39 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 21 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 46 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 70 | ||||
-rw-r--r-- | test/Parser/cxx-template-decl.cpp | 6 |
27 files changed, 690 insertions, 179 deletions
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<TagDecl>(D)) { Out << "Read top-level tag decl: '" << TD->getNameAsString() << "'\n"; + } else if (TemplateDecl *TempD = dyn_cast<TemplateDecl>(D)) { + PrintTemplateDecl(TempD); } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) { PrintLinkageSpec(LSD); } else if (FileScopeAsmDecl *AD = dyn_cast<FileScopeAsmDecl>(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<typename T> 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<int Size> 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<Decl **>(this + 1); } - const_iterator begin() const { - return reinterpret_cast<Decl * const *>(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<Decl **>(this + 1); } + const_iterator begin() const { + return reinterpret_cast<Decl * const *>(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<FunctionDecl*>(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<CXXRecordDecl*>(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<typename T> 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<int Size> 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 <template <typename> class T> class container { }; +/// @endcode +/// A template template parameter is a TemplateDecl because it defines the +/// name of a template and the template parameters allowable for substitution. +class TemplateTemplateParmDecl + : public TemplateDecl, protected TemplateParmPosition { + TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, + unsigned D, unsigned P, + IdentifierInfo *Id, TemplateParameterList *Params) + : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params), + TemplateParmPosition(D, P) + { } +public: + static TemplateTemplateParmDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, unsigned D, + unsigned P, IdentifierInfo *Id, + TemplateParameterList *Params); + + using TemplateParmPosition::getDepth; + using TemplateParmPosition::getPosition; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() == TemplateTemplateParm; + } + static bool classof(const TemplateTemplateParmDecl *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 TemplateTemplateParmDecl* CreateImpl(llvm::Deserializer& D, + ASTContext& C); + + friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C); +}; + +} /* end of namespace clang */ + +#endif diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 7697f4a01d..6b2797307f 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -31,6 +31,8 @@ namespace clang { class Type; class TypedefDecl; class TemplateTypeParmDecl; + class NonTypeTemplateParmDecl; + class TemplateTemplateParamDecl; class TagDecl; class RecordDecl; class CXXRecordDecl; diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 7d5bf4579e..bf67b7873f 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -1019,16 +1019,16 @@ public: /// (otherwise, "class" was used), and KeyLoc is the location of the /// "class" or "typename" keyword. ParamName is the name of the /// parameter (NULL indicates an unnamed template parameter) and - /// ParamName is the location of the parameter name (if any). + /// ParamNameLoc is the location of the parameter name (if any). /// If the type parameter has a default argument, it will be added /// later via ActOnTypeParameterDefault. Depth and Position provide /// the number of enclosing templates (see /// ActOnTemplateParameterList) and the number of previous /// parameters within this template parameter list. - virtual DeclTy *ActOnTypeParameter(Scope *S, bool Typename, - SourceLocation KeyLoc, - IdentifierInfo *ParamName, - SourceLocation ParamNameLoc, + virtual DeclTy *ActOnTypeParameter(Scope *S, bool Typename, + SourceLocation KeyLoc, + IdentifierInfo *ParamName, + SourceLocation ParamNameLoc, unsigned Depth, unsigned Position) { return 0; } @@ -1041,8 +1041,8 @@ public: /// ActOnNonTypeTemplateParameter - Called when a C++ non-type /// template parameter (e.g., "int Size" in "template<int Size> /// class Array") has been parsed. S is the current scope and D is - /// the parsed declarator. Depth and Position provide - /// the number of enclosing templates (see + /// the parsed declarator. Depth and Position provide the number of + /// enclosing templates (see /// ActOnTemplateParameterList) and the number of previous /// parameters within this template parameter list. virtual DeclTy *ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, @@ -1051,6 +1051,22 @@ public: return 0; } + /// ActOnTemplateTemplateParameter - Called when a C++ template template + /// parameter (e.g., "int T" in "template<template <typename> class T> class + /// Array") has been parsed. TmpLoc is the location of the "template" keyword, + /// TemplateParams is the sequence of parameters required by the template, + /// ParamName is the name of the parameter (null if unnamed), and ParamNameLoc + /// is the source location of the identifier (if given). + virtual DeclTy *ActOnTemplateTemplateParameter(Scope *S, + SourceLocation TmpLoc, + TemplateParamsTy *Params, + IdentifierInfo *ParamName, + SourceLocation ParamNameLoc, + unsigned Depth, + unsigned Position) { + return 0; + } + /// ActOnTemplateParameterList - Called when a complete template /// parameter list has been parsed, e.g., /// @@ -1090,6 +1106,7 @@ public: return 0; } + //===----------------------- Obj-C Declarations -------------------------===// // ActOnStartClassInterface - this action is called immediately after parsing diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 7892c84f92..7784aed764 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -14,6 +14,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/RecordLayout.h" #include "clang/Basic/TargetInfo.h" diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index c49a0eeee5..9687f34be8 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -13,6 +13,7 @@ add_clang_library(clangAST DeclGroup.cpp DeclObjC.cpp DeclSerialization.cpp + DeclTemplate.cpp ExprConstant.cpp Expr.cpp ExprCXX.cpp diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 21e1e0ce10..1e3683c857 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -13,8 +13,9 @@ #include "clang/AST/DeclBase.h" #include "clang/AST/Decl.h" -#include "clang/AST/DeclObjC.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Type.h" #include "llvm/ADT/DenseMap.h" diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 5e1875ab65..6de575411b 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -21,36 +21,6 @@ using namespace clang; // Decl Allocation/Deallocation Method Implementations //===----------------------------------------------------------------------===// -TemplateTypeParmDecl * -TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - bool Typename) { - return new (C) TemplateTypeParmDecl(DC, L, Id, Typename); -} - -NonTypeTemplateParmDecl * -NonTypeTemplateParmDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - QualType T, SourceLocation TypeSpecStartLoc) { - return new (C) NonTypeTemplateParmDecl(DC, L, Id, T, TypeSpecStartLoc); -} - -TemplateParameterList::TemplateParameterList(Decl **Params, unsigned NumParams) - : NumParams(NumParams) { - for (unsigned Idx = 0; Idx < NumParams; ++Idx) - begin()[Idx] = Params[Idx]; -} - -TemplateParameterList * -TemplateParameterList::Create(ASTContext &C, Decl **Params, - unsigned NumParams) { - // FIXME: how do I pass in Size to ASTContext::new? - unsigned Size = sizeof(TemplateParameterList) + sizeof(Decl *) * NumParams; - unsigned Align = llvm::AlignOf<TemplateParameterList>::Alignment; - void *Mem = C.Allocate(Size, Align); - return new (Mem) TemplateParameterList(Params, NumParams); -} - CXXRecordDecl::CXXRecordDecl(TagKind TK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id) : RecordDecl(CXXRecord, TK, DC, L, Id), diff --git a/lib/AST/DeclSerialization.cpp b/lib/AST/DeclSerialization.cpp index a10b229fcd..dcb8cda33b 100644 --- a/lib/AST/DeclSerialization.cpp +++ b/lib/AST/DeclSerialization.cpp @@ -14,6 +14,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "llvm/Bitcode/Serialize.h" #include "llvm/Bitcode/Deserialize.h" @@ -597,15 +598,60 @@ TypedefDecl* TypedefDecl::CreateImpl(Deserializer& D, ASTContext& C) { //===----------------------------------------------------------------------===// void TemplateTypeParmDecl::EmitImpl(Serializer& S) const { + S.EmitInt(Depth); + S.EmitInt(Position); S.EmitBool(Typename); NamedDecl::EmitInRec(S); } TemplateTypeParmDecl * TemplateTypeParmDecl::CreateImpl(Deserializer& D, ASTContext& C) { + unsigned Depth = D.ReadInt(); + unsigned Position = D.ReadInt(); bool Typename = D.ReadBool(); TemplateTypeParmDecl *decl - = new (C) TemplateTypeParmDecl(0, SourceLocation(), NULL, Typename); + = new (C) TemplateTypeParmDecl(0, SourceLocation(), Depth, Position, + 0, Typename); + decl->NamedDecl::ReadInRec(D, C); + return decl; +} + +//===----------------------------------------------------------------------===// +// NonTypeTemplateParmDecl Serialization. +//===----------------------------------------------------------------------===// +void NonTypeTemplateParmDecl::EmitImpl(Serializer& S) const { + S.EmitInt(Depth); + S.EmitInt(Position); + NamedDecl::Emit(S); +} + +NonTypeTemplateParmDecl* +NonTypeTemplateParmDecl::CreateImpl(Deserializer& D, ASTContext& C) { + unsigned Depth = D.ReadInt(); + unsigned Position = D.ReadInt(); + NonTypeTemplateParmDecl *decl + = new (C) NonTypeTemplateParmDecl(0, SourceLocation(), Depth, Position, + 0, QualType(), SourceLocation()); + decl->NamedDecl::ReadInRec(D, C); + return decl; +} + +//===----------------------------------------------------------------------===// +// TemplateTemplateParmDecl Serialization. +//===----------------------------------------------------------------------===// +void TemplateTemplateParmDecl::EmitImpl(Serializer& S) const { + S.EmitInt(Depth); + S.EmitInt(Position); + NamedDecl::EmitInRec(S); +} + +TemplateTemplateParmDecl* +TemplateTemplateParmDecl::CreateImpl(Deserializer& D, ASTContext& C) { + unsigned Depth = D.ReadInt(); + unsigned Position = D.ReadInt(); + TemplateTemplateParmDecl *decl + = new (C) TemplateTemplateParmDecl(0, SourceLocation(), Depth, Position, + 0, 0); decl->NamedDecl::ReadInRec(D, C); return decl; } diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp new file mode 100644 index 0000000000..08cd5b377d --- /dev/null +++ b/lib/AST/DeclTemplate.cpp @@ -0,0 +1,108 @@ +//===--- DeclCXX.cpp - C++ Declaration AST Node Implementation ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the C++ related Decl classes for templates. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/ASTContext.h" +#include "clang/Basic/IdentifierTable.h" +#include "llvm/ADT/STLExtras.h" +using namespace clang; + +//===----------------------------------------------------------------------===// +// TemplateParameterList Implementation +//===----------------------------------------------------------------------===// + +TemplateParameterList::TemplateParameterList(Decl **Params, unsigned NumParams) + : NumParams(NumParams) { + for (unsigned Idx = 0; Idx < NumParams; ++Idx) + begin()[Idx] = Params[Idx]; +} + +TemplateParameterList * +TemplateParameterList::Create(ASTContext &C, Decl **Params, + unsigned NumParams) { + unsigned Size = sizeof(TemplateParameterList) + sizeof(Decl *) * NumParams; + unsigned Align = llvm::AlignOf<TemplateParameterList>::Alignment; + void *Mem = C.Allocate(Size, Align); + return new (Mem) TemplateParameterList(Params, NumParams); +} + +//===----------------------------------------------------------------------===// +// TemplateDecl Implementation +//===----------------------------------------------------------------------===// + +TemplateDecl::~TemplateDecl() { +} + +//===----------------------------------------------------------------------===// +// FunctionTemplateDecl Implementation +//===----------------------------------------------------------------------===// + +FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C, + DeclContext *DC, + SourceLocation L, + DeclarationName Name, + TemplateParameterList *Params, + NamedDecl *Decl) { + return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl); +} + +//===----------------------------------------------------------------------===// +// ClassTemplateDecl Implementation +//===----------------------------------------------------------------------===// + +ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, + DeclContext *DC, + SourceLocation L, + DeclarationName Name, + TemplateParameterList *Params, + NamedDecl *Decl) { + return new (C) ClassTemplateDecl(DC, L, Name, Params, Decl); +} + +//===----------------------------------------------------------------------===// +// TemplateTypeParm Allocation/Deallocation Method Implementations +//===----------------------------------------------------------------------===// + +TemplateTypeParmDecl * +TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation L, unsigned D, unsigned P, + IdentifierInfo *Id, bool Typename) { + return new (C) TemplateTypeParmDecl(DC, L, D, P, Id, Typename); +} + +//===----------------------------------------------------------------------===// +// NonTypeTemplateParmDecl Method Implementations +//===----------------------------------------------------------------------===// + +NonTypeTemplateParmDecl * +NonTypeTemplateParmDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation L, unsigned D, unsigned P, + IdentifierInfo *Id, QualType T, + SourceLocation TypeSpecStartLoc) { + return new (C) NonTypeTemplateParmDecl(DC, L, D, P, Id, T, + TypeSpecStartLoc); +} + +//===----------------------------------------------------------------------===// +// TemplateTemplateParmDecl Method Implementations +//===----------------------------------------------------------------------===// + +TemplateTemplateParmDecl * +TemplateTemplateParmDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation L, unsigned D, unsigned P, + IdentifierInfo *Id, + TemplateParameterList *Params) { + return new (C) TemplateTemplateParmDecl(DC, L, D, P, Id, Params); +} + diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 35384d880c..ce13c34012 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -16,6 +16,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtVisitor.h" #include "clang/Basic/TargetInfo.h" diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 5d3478b2ea..f39a325e0d 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -15,6 +15,7 @@ #include "clang/AST/Type.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "llvm/ADT/StringExtras.h" diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 114f4cb570..e2601b6cf4 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1726,7 +1726,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) { // If this identifier is followed by a '<', we may have a template-id. DeclTy *Template; - if (NextToken().is(tok::less) && + if (getLang().CPlusPlus && NextToken().is(tok::less) && (Template = Actions.isTemplateName(*Tok.getIdentifierInfo(), CurScope))) { IdentifierInfo *II = Tok.getIdentifierInfo(); diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 1fbe32a459..b2b0d8f59f 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -345,8 +345,8 @@ void Parser::ParseClassSpecifier(DeclSpec &DS, return; } - // Parse the tag portion of this. - DeclTy *TagDecl + // Create the tag portion of the class, possibly resulting in a template. + DeclTy *TagOrTempDecl = Actions.ActOnTag(CurScope, TagType, TK, StartLoc, SS, Name, NameLoc, Attr, Action::MultiTemplateParamsArg( @@ -356,15 +356,15 @@ void Parser::ParseClassSpecifier(DeclSpec &DS, // Parse the optional base clause (C++ only). if (getLang().CPlusPlus && Tok.is(tok::colon)) { - ParseBaseClause(TagDecl); + ParseBaseClause(TagOrTempDecl); } // If there is a body, parse it and inform the actions module. if (Tok.is(tok::l_brace)) if (getLang().CPlusPlus) - ParseCXXMemberSpecification(StartLoc, TagType, TagDecl); + ParseCXXMemberSpecification(StartLoc, TagType, TagOrTempDecl); else - ParseStructUnionBody(StartLoc, TagType, TagDecl); + ParseStructUnionBody(StartLoc, TagType, TagOrTempDecl); else if (TK == Action::TK_Definition) { // FIXME: Complain that we have a base-specifier list but no // definition. @@ -372,7 +372,7 @@ void Parser::ParseClassSpecifier(DeclSpec &DS, } const char *PrevSpec = 0; - if (DS.SetTypeSpecType(TagType, StartLoc, PrevSpec, TagDecl)) + if (DS.SetTypeSpecType(TagType, StartLoc, PrevSpec, TagOrTempDecl)) Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec; } diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index b9a55147b8..e95c106f28 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -39,7 +39,7 @@ Parser::DeclTy *Parser::ParseTemplateDeclaration(unsigned Context) { // // We parse multiple levels non-recursively so that we can build a // single data structure containing all of the template parameter - // lists, and easily differentiate between the case above and: + // lists easily differentiate between the case above and: // // template<typename T> // class A { @@ -82,19 +82,16 @@ Parser::DeclTy *Parser::ParseTemplateDeclaration(unsigned Context) { } while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template)); // Parse the actual template declaration. - DeclTy *TemplateDecl = ParseDeclarationOrFunctionDefinition(&ParamLists); - - return TemplateDecl; + return ParseDeclarationOrFunctionDefinition(&ParamLists); } /// ParseTemplateParameters - Parses a template-parameter-list enclosed in -/// angle brackets. Depth is the depth of this -/// template-parameter-list, which is the number of template headers -/// directly enclosing this template header. TemplateParams is the -/// current list of template parameters we're building. The template -/// parameter we parse will be added to this list. LAngleLoc and -/// RAngleLoc will receive the positions of the '<' and '>', -/// respectively, that enclose this template parameter list. +/// angle brackets. Depth is the depth of this template-parameter-list, which +/// is the number of template headers directly enclosing this template header. +/// TemplateParams is the current list of template parameters we're building. +/// The template parameter we parse will be added to this list. LAngleLoc and +/// RAngleLoc will receive the positions of the '<' and '>', respectively, +/// that enclose this template parameter list. bool Parser::ParseTemplateParameters(unsigned Depth, TemplateParameterList &TemplateParams, SourceLocation &LAngleLoc, @@ -223,8 +220,8 @@ Parser::DeclTy *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) { return 0; } - DeclTy *TypeParam = Actions.ActOnTypeParameter(CurScope, TypenameKeyword, - KeyLoc, ParamName, NameLoc, + DeclTy *TypeParam = Actions.ActOnTypeParameter(CurScope, TypenameKeyword, + KeyLoc, ParamName, NameLoc, Depth, Position); // Grab a default type id (if given). @@ -251,7 +248,7 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { SourceLocation TemplateLoc = ConsumeToken(); TemplateParameterList TemplateParams; SourceLocation LParenLoc, RParenLoc; - if(!ParseTemplateParameters(Depth+1, TemplateParams, LParenLoc, + if(!ParseTemplateParameters(Depth + 1, TemplateParams, LParenLoc, RParenLoc)) { return 0; } @@ -266,10 +263,11 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { SourceLocation ClassLoc = ConsumeToken(); // Get the identifier, if given. - IdentifierInfo* ident = 0; + SourceLocation NameLoc; + IdentifierInfo* ParamName = 0; if(Tok.is(tok::identifier)) { - ident = Tok.getIdentifierInfo(); - ConsumeToken(); + ParamName = Tok.getIdentifierInfo(); + NameLoc = ConsumeToken(); } else if(Tok.is(tok::equal) || Tok.is(tok::comma) || Tok.is(tok::greater)) { // Unnamed template parameter. Don't have to do anything here, just // don't consume this token. @@ -279,6 +277,8 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { } // Get the a default value, if given. + // FIXME: I think that the results of this block need to be passed to the + // act-on call, so we can assemble the parameter correctly. OwningExprResult DefaultExpr(Actions); if(Tok.is(tok::equal)) { ConsumeToken(); @@ -288,8 +288,9 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { } } - // FIXME: Add an action for template template parameters. - return 0; + return Actions.ActOnTemplateTemplateParameter(CurScope, TemplateLoc, + &TemplateParams, ParamName, + NameLoc, Depth, Position); } /// ParseNonTypeTemplateParameter - Handle the parsing of non-type diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index c5c7dd4733..2f7e2ea0fc 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -379,7 +379,6 @@ Parser::DeclTy *Parser::ParseExternalDeclaration() { case tok::kw_export: // As in 'export template' // A function definition cannot start with a these keywords. return ParseDeclaration(Declarator::FileContext); - default: // We can't tell whether this is a function-definition or declaration yet. return ParseDeclarationOrFunctionDefinition(); diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index b0e24f5d14..b27f11b77c 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -60,6 +60,7 @@ namespace clang { class SwitchStmt; class ExtVectorType; class TypedefDecl; + class TemplateDecl; class ObjCInterfaceDecl; class ObjCCompatibleAliasDecl; class ObjCProtocolDecl; @@ -1479,14 +1480,23 @@ public: virtual DeclTy *isTemplateName(IdentifierInfo &II, Scope *S, const CXXScopeSpec *SS = 0); bool DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl); - virtual DeclTy *ActOnTypeParameter(Scope *S, bool Typename, - SourceLocation KeyLoc, - IdentifierInfo *ParamName, - SourceLocation ParamNameLoc, + TemplateDecl *AdjustDeclIfTemplate(DeclTy *&Decl); + + virtual DeclTy *ActOnTypeParameter(Scope *S, bool Typename, + SourceLocation KeyLoc, + IdentifierInfo *ParamName, + SourceLocation ParamNameLoc, unsigned Depth, unsigned Position); virtual DeclTy *ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, - unsigned Depth, + unsigned Depth, unsigned Position); + virtual DeclTy *ActOnTemplateTemplateParameter(Scope *S, + SourceLocation TmpLoc, + TemplateParamsTy *Params, + IdentifierInfo *ParamName, + SourceLocation ParamNameLoc, + unsigned Depth, + unsigned Position); virtual TemplateParamsTy * ActOnTemplateParameterList(unsigned Depth, SourceLocation ExportLoc, @@ -1495,6 +1505,7 @@ public: DeclTy **Params, unsigned NumParams, SourceLocation RAngleLoc); + // Objective-C declarations. virtual DeclTy *ActOnStartClassInterface(SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index a3ca97b5cb..3e501f450a 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -16,6 +16,7 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" #include "clang/Parse/DeclSpec.h" #include "clang/Basic/TargetInfo.h" @@ -1170,7 +1171,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl, // The scope passed in may not be a decl scope. Zip up the scope tree until // we find one that is. while ((S->getFlags() & Scope::DeclScope) == 0 || - (S->getFlags() & Scope::TemplateParamScope) != 0) + (S->getFlags() & Scope::TemplateParamScope) != 0) S = S->getParent(); DeclContext *DC; @@ -2778,6 +2779,9 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, /// former case, Name will be non-null. In the later case, Name will be null. /// TagSpec indicates what kind of tag this is. TK indicates whether this is a /// reference/declaration/definition of a tag. +/// +/// This creates and returns template declarations if any template parameter +/// lists are given. Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, SourceLocation KWLoc, const CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, @@ -2786,7 +2790,12 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, // If this is not a definition, it must have a name. assert((Name != 0 || TK == TK_Definition) && "Nameless record must be a definition!"); - + assert((TemplateParameterLists.size() == 0 || TK != TK_Reference) && + "Can't have a reference to a template"); + assert((TemplateParameterLists.size() == 0 || + TagSpec != DeclSpec::TST_enum) && + "No such thing as an enum template"); + TagDecl::TagKind Kind; switch (TagSpec) { default: assert(0 && "Unknown tag type!"); @@ -2799,6 +2808,7 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, DeclContext *SearchDC = CurContext; DeclContext *DC = CurContext; NamedDecl *PrevDecl = 0; + TemplateDecl *PrevTemplate = 0; bool Invalid = false; @@ -2863,6 +2873,11 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, } if (PrevDecl) { + // If we found a template, keep track of the template and its + // underlying declaration. + if ((PrevTemplate = dyn_cast_or_null<ClassTemplateDecl>(PrevDecl))) + PrevDecl = PrevTemplate->getTemplatedDecl(); + if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) { // If this is a use of a previous tag, or if the tag is already declared // in the same scope (so that the definition/declaration completes or @@ -2877,6 +2892,7 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, Name = 0; PrevDecl = 0; Invalid = true; + // FIXME: Add template/non-template redecl check } else { // If this is a use, just return the declaration we found. @@ -2886,7 +2902,7 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, // need to be changed with DeclGroups. if (TK == TK_Reference) return PrevDecl; - + // Diagnose attempts to redefine a tag. if (TK == TK_Definition) { if (TagDecl *Def = PrevTagDecl->getDefinition(Context)) { @@ -2990,6 +3006,7 @@ CreateNewDecl: // declaration of the same entity, the two will be linked via // PrevDecl. TagDecl *New; + ClassTemplateDecl *NewTemplate = 0; if (Kind == TagDecl::TK_enum) { // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.: @@ -3003,11 +3020,28 @@ CreateNewDecl: // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.: // struct X { int A; } D; D should chain to X. - if (getLangOptions().CPlusPlus) + if (getLangOptions().CPlusPlus) { // FIXME: Look for a way to use RecordDecl for simple structs. New = CXXRecordDecl::Create(Context, Kind, SearchDC, Loc, Name, cast_or_null<CXXRecordDecl>(PrevDecl)); - else + + // If there's are template parameters, then this must be a class + // template. Create the template decl node also. + // FIXME: Do we always create template decls? We may not for forward + // declarations. + // FIXME: What are we actually going to do with the template decl? + if (TemplateParameterLists.size() > 0) { + // FIXME: The allocation of the parameters is probably incorrect. + // FIXME: Does the TemplateDecl have the same name as the class? + TemplateParameterList *Params = + TemplateParameterList::Create(Context, + (Decl **)TemplateParameterLists.get(), + TemplateParameterLists.size()); + NewTemplate = ClassTemplateDecl::Create(Context, DC, Loc, + DeclarationName(Name), Params, + New); + } + } else New = RecordDecl::Create(Context, Kind, SearchDC, Loc, Name, cast_or_null<RecordDecl>(PrevDecl)); } @@ -3080,6 +3114,7 @@ CreateNewDecl: } void Sema::ActOnTagStartDefinition(Scope *S, DeclTy *TagD) { + AdjustDeclIfTemplate(TagD); TagDecl *Tag = cast<TagDecl>((Decl *)TagD); // Enter the tag context. @@ -3105,6 +3140,7 @@ void Sema::ActOnTagStartDefinition(Scope *S, DeclTy *TagD) { } void Sema::ActOnTagFinishDefinition(Scope *S, DeclTy *TagD) { + AdjustDeclIfTemplate(TagD); TagDecl *Tag = cast<TagDecl>((Decl *)TagD); if (isa<CXXRecordDecl>(Tag)) diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 5595215d55..35050e517b 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -757,6 +757,7 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, DeclTy *TagDecl, SourceLocation LBrac, SourceLocation RBrac) { + AdjustDeclIfTemplate(TagDecl); ActOnFields(S, RLoc, TagDecl, (DeclTy**)FieldCollector->getCurFields(), FieldCollector->getCurNumFields(), LBrac, RBrac, 0); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 0c755f6d1f..66cbdfd26a 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -16,6 +16,7 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/Lex/Preprocessor.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Basic/SourceManager.h" diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 65dd9490d2..1aa2ea0207 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -536,7 +536,7 @@ Sema::CppLookupName(Scope *S, DeclarationName Name, IEnd = IdResolver.end(); // First we lookup local scope. - // We don't consider using-dirctives, as per 7.3.4.p1 [namespace.udir] + // We don't consider using-directives, as per 7.3.4.p1 [namespace.udir] // ...During unqualified name lookup (3.4.1), the names appear as if // they were declared in the nearest enclosing namespace which contains // both the using-directive and the nominated namespace. diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index c46731e515..e15343a042 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -13,6 +13,7 @@ #include "Sema.h" #include "clang/AST/Expr.h" +#include "clang/AST/DeclTemplate.h" #include "clang/Parse/DeclSpec.h" #include "clang/Basic/LangOptions.h" @@ -38,6 +39,9 @@ Sema::DeclTy *Sema::isTemplateName(IdentifierInfo &II, Scope *S, // FIXME: We need to represent templates via some kind of // TemplateDecl, because what follows is a hack that only works in // one specific case. + if (isa<TemplateDecl>(IIDecl)) + return IIDecl; + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(IIDecl)) { if (FD->getType()->isDependentType()) return FD; @@ -50,7 +54,6 @@ Sema::DeclTy *Sema::isTemplateName(IdentifierInfo &II, Scope *S, return Ovl; } } - return 0; } return 0; } @@ -75,6 +78,18 @@ bool Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl) { return true; } +/// AdjustDeclForTemplates - If the given decl happens to be a template, reset +/// the parameter D to reference the templated declaration and return a pointer +/// to the template declaration. Otherwise, do nothing to D and return null. +TemplateDecl *Sema::AdjustDeclIfTemplate(DeclTy *&D) +{ + if(TemplateDecl *Temp = dyn_cast<TemplateDecl>(static_cast<Decl*>(D))) { + D = Temp->getTemplatedDecl(); + return Temp; + } + return 0; +} + /// ActOnTypeParameter - Called when a C++ template type parameter /// (e.g., "typename T") has been parsed. Typename specifies whether /// the keyword "typename" was used to declare the type parameter @@ -101,8 +116,8 @@ Sema::DeclTy *Sema::ActOnTypeParameter(Scope *S, bool Typename, } TemplateTypeParmDecl *Param - = TemplateTypeParmDecl::Create(Context, CurContext, - ParamNameLoc, ParamName, Typename); + = TemplateTypeParmDecl::Create(Context, CurContext, ParamNameLoc, + Depth, Position, ParamName, Typename); if (Invalid) Param->setInvalidDecl(); @@ -124,8 +139,8 @@ Sema::DeclTy *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, unsigned Position) { QualType T = GetTypeForDeclarator(D, S); - assert(S->isTemplateParamScope() && - "Template type parameter not in template parameter scope!"); + assert(S->isTemplateParamScope() && + "Non-type template parameter not in template parameter scope!"); bool Invalid = false; IdentifierInfo *ParamName = D.getIdentifier(); @@ -133,12 +148,12 @@ Sema::DeclTy *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, NamedDecl *PrevDecl = LookupName(S, ParamName, LookupTagName); if (PrevDecl && PrevDecl->isTemplateParameter()) Invalid = Invalid || DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), - PrevDecl); + PrevDecl); } NonTypeTemplateParmDecl *Param = NonTypeTemplateParmDecl::Create(Context, CurContext, D.getIdentifierLoc(), - ParamName, T); + Depth, Position, ParamName, T); if (Invalid) Param->setInvalidDecl(); @@ -150,6 +165,46 @@ Sema::DeclTy *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, return Param; } + +/// ActOnTemplateTemplateParameter - Called when a C++ template template +/// parameter (e.g. T in template <template <typename> class T> class array) +/// has been parsed. S is the current scope. +Sema::DeclTy *Sema::ActOnTemplateTemplateParameter(Scope* S, + SourceLocation TmpLoc, + TemplateParamsTy *Params, + IdentifierInfo *Name, + SourceLocation NameLoc, + unsigned Depth, + unsigned Position) +{ + assert(S->isTemplateParamScope() && + "Template template parameter not in template parameter scope!"); + + // Construct the parameter object. + TemplateTemplateParmDecl *Param = + TemplateTemplateParmDecl::Create(Context, CurContext, TmpLoc, Depth, + Position, Name, + (TemplateParameterList*)Params); + + // Make sure the parameter is valid. + // FIXME: Decl object is not currently invalidated anywhere so this doesn't + // do anything yet. However, if the template parameter list or (eventual) + // default value is ever invalidated, that will propagate here. + bool Invalid = false; + if (Invalid) { + Param->setInvalidDecl(); + } + + // If the tt-param has a name, then link the identifier into the scope + // and lookup mechanisms. + if (Name) { + S->AddDecl(Param); + IdResolver.AddDecl(Param); + } + + return Param; +} + /// ActOnTemplateParameterList - Builds a TemplateParameterList that /// contains the template parameters in Params/NumParams. Sema::TemplateParamsTy * @@ -164,3 +219,4 @@ Sema::ActOnTemplateParameterList(unsigned Depth, return TemplateParameterList::Create(Context, (Decl**)Params, NumParams); } + diff --git a/test/Parser/cxx-template-decl.cpp b/test/Parser/cxx-template-decl.cpp index 79b04cfc79..08b05cf823 100644 --- a/test/Parser/cxx-template-decl.cpp +++ b/test/Parser/cxx-template-decl.cpp @@ -32,9 +32,9 @@ template <typename = int> X2; // Forward declarations w/template template parameters template <template <typename> class T> class TTP1; template <template <typename> class> class TTP2; -template <template <typename> class T = foo> TTP3; -template <template <typename> class = foo> TTP3; -template <template <typename X, typename Y> class T> TTP5; +template <template <typename> class T = foo> class TTP3; +template <template <typename> class = foo> class TTP3; +template <template <typename X, typename Y> class T> class TTP5; // Forward declararations with non-type params template <int> class NTP0; |