diff options
Diffstat (limited to 'lib/Sema')
-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 |
6 files changed, 123 insertions, 18 deletions
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); } + |