diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-08-25 17:23:04 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-08-25 17:23:04 +0000 |
commit | 05396e20d68535612f58c84e0dfc7647c75a7da1 (patch) | |
tree | 6ebd628caace99d4ec89d58cc21cbcf6c30221e6 /lib/Sema/SemaTemplate.cpp | |
parent | c87efbd2cbd13e68ea771275f03d1bbd1b741e47 (diff) |
Implement out-of-line definitions of nested class templates. Most of
the logic is there for out-of-line definitions with multiple levels of
nested templates, but this is still a work-in-progress: we're having
trouble determining when we should look into a dependent
nested-name-specifier.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80003 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 145 |
1 files changed, 66 insertions, 79 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 7b29c9432a..bb6fe92283 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -444,14 +444,15 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, const CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, AttributeList *Attr, - MultiTemplateParamsArg TemplateParameterLists, + TemplateParameterList *TemplateParams, AccessSpecifier AS) { - assert(TemplateParameterLists.size() > 0 && "No template parameter lists?"); + assert(TemplateParams && TemplateParams->size() > 0 && + "No template parameters"); assert(TUK != TUK_Reference && "Can only declare or define class templates"); bool Invalid = false; // Check that we can declare a template here. - if (CheckTemplateDeclScope(S, TemplateParameterLists)) + if (CheckTemplateDeclScope(S, TemplateParams)) return true; TagDecl::TagKind Kind; @@ -469,27 +470,30 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, } // Find any previous declaration with this name. - LookupResult Previous = LookupParsedName(S, &SS, Name, LookupOrdinaryName, - true); + DeclContext *SemanticContext; + LookupResult Previous; + if (SS.isNotEmpty() && !SS.isInvalid()) { + SemanticContext = computeDeclContext(SS, true); + if (!SemanticContext) { + // FIXME: Produce a reasonable diagnostic here + return true; + } + + Previous = LookupQualifiedName(SemanticContext, Name, LookupOrdinaryName, + true); + } else { + SemanticContext = CurContext; + Previous = LookupName(S, Name, LookupOrdinaryName, true); + } + assert(!Previous.isAmbiguous() && "Ambiguity in class template redecl?"); NamedDecl *PrevDecl = 0; if (Previous.begin() != Previous.end()) PrevDecl = *Previous.begin(); - if (PrevDecl && !isDeclInScope(PrevDecl, CurContext, S)) + if (PrevDecl && !isDeclInScope(PrevDecl, SemanticContext, S)) PrevDecl = 0; - DeclContext *SemanticContext = CurContext; - if (SS.isNotEmpty() && !SS.isInvalid()) { - SemanticContext = computeDeclContext(SS); - - // FIXME: need to match up several levels of template parameter lists here. - } - - // FIXME: member templates! - TemplateParameterList *TemplateParams - = static_cast<TemplateParameterList *>(*TemplateParameterLists.release()); - // If there is a previous declaration with the same name, check // whether this is a valid redeclaration. ClassTemplateDecl *PrevClassTemplate @@ -2106,28 +2110,20 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New, /// If the template declaration is valid in this scope, returns /// false. Otherwise, issues a diagnostic and returns true. bool -Sema::CheckTemplateDeclScope(Scope *S, - MultiTemplateParamsArg &TemplateParameterLists) { - assert(TemplateParameterLists.size() > 0 && "Not a template"); - +Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) { // Find the nearest enclosing declaration scope. while ((S->getFlags() & Scope::DeclScope) == 0 || (S->getFlags() & Scope::TemplateParamScope) != 0) S = S->getParent(); - TemplateParameterList *TemplateParams = - static_cast<TemplateParameterList*>(*TemplateParameterLists.get()); - SourceLocation TemplateLoc = TemplateParams->getTemplateLoc(); - SourceRange TemplateRange - = SourceRange(TemplateLoc, TemplateParams->getRAngleLoc()); - // C++ [temp]p2: // A template-declaration can appear only as a namespace scope or // class scope declaration. DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity()); if (Ctx && isa<LinkageSpecDecl>(Ctx) && cast<LinkageSpecDecl>(Ctx)->getLanguage() != LinkageSpecDecl::lang_cxx) - return Diag(TemplateLoc, diag::err_template_linkage) << TemplateRange; + return Diag(TemplateParams->getTemplateLoc(), diag::err_template_linkage) + << TemplateParams->getSourceRange(); while (Ctx && isa<LinkageSpecDecl>(Ctx)) Ctx = Ctx->getParent(); @@ -2135,8 +2131,9 @@ Sema::CheckTemplateDeclScope(Scope *S, if (Ctx && (Ctx->isFileContext() || Ctx->isRecord())) return false; - return Diag(TemplateLoc, diag::err_template_outside_namespace_or_class_scope) - << TemplateRange; + return Diag(TemplateParams->getTemplateLoc(), + diag::err_template_outside_namespace_or_class_scope) + << TemplateParams->getSourceRange(); } /// \brief Check whether a class template specialization or explicit @@ -2369,57 +2366,47 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // Check the validity of the template headers that introduce this // template. - // FIXME: Once we have member templates, we'll need to check - // C++ [temp.expl.spec]p17-18, where we could have multiple levels of - // template<> headers. - if (TemplateParameterLists.size() == 0) - Diag(KWLoc, diag::err_template_spec_needs_header) - << CodeModificationHint::CreateInsertion(KWLoc, "template<> "); - else { - TemplateParameterList *TemplateParams - = static_cast<TemplateParameterList*>(*TemplateParameterLists.get()); - if (TemplateParameterLists.size() > 1) { - Diag(TemplateParams->getTemplateLoc(), - diag::err_template_spec_extra_headers); - return true; - } - - if (TemplateParams->size() > 0) { - isPartialSpecialization = true; - - // C++ [temp.class.spec]p10: - // The template parameter list of a specialization shall not - // contain default template argument values. - for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) { - Decl *Param = TemplateParams->getParam(I); - if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) { - if (TTP->hasDefaultArgument()) { - Diag(TTP->getDefaultArgumentLoc(), - diag::err_default_arg_in_partial_spec); - TTP->setDefaultArgument(QualType(), SourceLocation(), false); - } - } else if (NonTypeTemplateParmDecl *NTTP - = dyn_cast<NonTypeTemplateParmDecl>(Param)) { - if (Expr *DefArg = NTTP->getDefaultArgument()) { - Diag(NTTP->getDefaultArgumentLoc(), - diag::err_default_arg_in_partial_spec) - << DefArg->getSourceRange(); - NTTP->setDefaultArgument(0); - DefArg->Destroy(Context); - } - } else { - TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(Param); - if (Expr *DefArg = TTP->getDefaultArgument()) { - Diag(TTP->getDefaultArgumentLoc(), - diag::err_default_arg_in_partial_spec) - << DefArg->getSourceRange(); - TTP->setDefaultArgument(0); - DefArg->Destroy(Context); - } + TemplateParameterList *TemplateParams + = MatchTemplateParametersToScopeSpecifier(TemplateNameLoc, SS, + (TemplateParameterList**)TemplateParameterLists.get(), + TemplateParameterLists.size()); + if (TemplateParams && TemplateParams->size() > 0) { + isPartialSpecialization = true; + + // C++ [temp.class.spec]p10: + // The template parameter list of a specialization shall not + // contain default template argument values. + for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) { + Decl *Param = TemplateParams->getParam(I); + if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) { + if (TTP->hasDefaultArgument()) { + Diag(TTP->getDefaultArgumentLoc(), + diag::err_default_arg_in_partial_spec); + TTP->setDefaultArgument(QualType(), SourceLocation(), false); + } + } else if (NonTypeTemplateParmDecl *NTTP + = dyn_cast<NonTypeTemplateParmDecl>(Param)) { + if (Expr *DefArg = NTTP->getDefaultArgument()) { + Diag(NTTP->getDefaultArgumentLoc(), + diag::err_default_arg_in_partial_spec) + << DefArg->getSourceRange(); + NTTP->setDefaultArgument(0); + DefArg->Destroy(Context); + } + } else { + TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(Param); + if (Expr *DefArg = TTP->getDefaultArgument()) { + Diag(TTP->getDefaultArgumentLoc(), + diag::err_default_arg_in_partial_spec) + << DefArg->getSourceRange(); + TTP->setDefaultArgument(0); + DefArg->Destroy(Context); } } } - } + } else if (!TemplateParams) + Diag(KWLoc, diag::err_template_spec_needs_header) + << CodeModificationHint::CreateInsertion(KWLoc, "template<> "); // Check that the specialization uses the same tag kind as the // original template. @@ -2482,7 +2469,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, ClassTemplate->getIdentifier(), TemplateNameLoc, Attr, - move(TemplateParameterLists), + TemplateParams, AS_none); } |