diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-10-08 07:24:58 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-10-08 07:24:58 +0000 |
commit | 251b4ff2578e26959a4c036140ccd61c5e9292f2 (patch) | |
tree | cacc1f2c9bfb3174e9914422eef9de64890b06cd /lib/Sema/SemaTemplate.cpp | |
parent | e9374d5e2c0915bd883dfa988db2451b844390d8 (diff) |
For instantiations of static data members of class templates, keep
track of the kind of specialization or instantiation. Also, check the
scope of the specialization and ensure that a specialization
declaration without an initializer is not a definition.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83533 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 91 |
1 files changed, 62 insertions, 29 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 9d3efa60b0..5c6ec0004a 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -2365,8 +2365,9 @@ static TemplateSpecializationKind getTemplateSpecializationKind(NamedDecl *D) { return CTS->getSpecializationKind(); if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) return Function->getTemplateSpecializationKind(); - - // FIXME: static data members! + if (VarDecl *Var = dyn_cast<VarDecl>(D)) + return Var->getTemplateSpecializationKind(); + // FIXME: member classes of class templates! return TSK_Undeclared; } @@ -3118,7 +3119,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, return false; } -/// \brief Perform semantic analysis for the given member function +/// \brief Perform semantic analysis for the given non-template member /// specialization. /// /// This routine performs all of the semantic analysis required for an @@ -3126,27 +3127,45 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, /// the function declaration \p FD will become a member function /// specialization. /// -/// \param FD the function declaration, which will be updated to become a -/// function template specialization. +/// \param Member the member declaration, which will be updated to become a +/// specialization. /// /// \param PrevDecl the set of declarations, one of which may be specialized /// by this function specialization. bool -Sema::CheckMemberFunctionSpecialization(CXXMethodDecl *FD, - NamedDecl *&PrevDecl) { - // Try to find the member function we are instantiating. - CXXMethodDecl *Instantiation = 0; - for (OverloadIterator Ovl(PrevDecl), OvlEnd; Ovl != OvlEnd; ++Ovl) { - if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*Ovl)) { - if (Context.hasSameType(FD->getType(), Method->getType())) { - Instantiation = Method; - break; +Sema::CheckMemberSpecialization(NamedDecl *Member, NamedDecl *&PrevDecl) { + assert(!isa<TemplateDecl>(Member) && "Only for non-template members"); + + // Try to find the member we are instantiating. + NamedDecl *Instantiation = 0; + NamedDecl *InstantiatedFrom = 0; + if (!PrevDecl) { + // Nowhere to look anyway. + } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Member)) { + for (OverloadIterator Ovl(PrevDecl), OvlEnd; Ovl != OvlEnd; ++Ovl) { + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*Ovl)) { + if (Context.hasSameType(Function->getType(), Method->getType())) { + Instantiation = Method; + InstantiatedFrom = Method->getInstantiatedFromMemberFunction(); + break; + } + } + } + } else if (isa<VarDecl>(Member)) { + if (VarDecl *PrevVar = dyn_cast<VarDecl>(PrevDecl)) + if (PrevVar->isStaticDataMember()) { + Instantiation = PrevDecl; + InstantiatedFrom = PrevVar->getInstantiatedFromStaticDataMember(); } + } else if (isa<RecordDecl>(Member)) { + if (CXXRecordDecl *PrevRecord = dyn_cast<CXXRecordDecl>(PrevDecl)) { + Instantiation = PrevDecl; + InstantiatedFrom = PrevRecord->getInstantiatedFromMemberClass(); } } if (!Instantiation) { - // There is no previous declaration that matches. Since member function + // There is no previous declaration that matches. Since member // specializations are always out-of-line, the caller will complain about // this mismatch later. return false; @@ -3155,30 +3174,43 @@ Sema::CheckMemberFunctionSpecialization(CXXMethodDecl *FD, // FIXME: Check if the prior declaration has a point of instantiation. // If so, we have run afoul of C++ [temp.expl.spec]p6. - // Make sure that this is a specialization of a member function. - FunctionDecl *FunctionInTemplate - = Instantiation->getInstantiatedFromMemberFunction(); - if (!FunctionInTemplate) { - Diag(FD->getLocation(), diag::err_function_spec_not_instantiated) - << FD; + // Make sure that this is a specialization of a member. + if (!InstantiatedFrom) { + Diag(Member->getLocation(), diag::err_spec_member_not_instantiated) + << Member; Diag(Instantiation->getLocation(), diag::note_specialized_decl); return true; } // Check the scope of this explicit specialization. if (CheckTemplateSpecializationScope(*this, - FunctionInTemplate, - Instantiation, FD->getLocation(), + InstantiatedFrom, + Instantiation, Member->getLocation(), false, TSK_ExplicitSpecialization)) return true; // FIXME: Check for specialization-after-instantiation errors and such. - // Note that this function is an explicit instantiation of a member function. - Instantiation->setTemplateSpecializationKind(TSK_ExplicitSpecialization); - FD->setInstantiationOfMemberFunction(FunctionInTemplate, - TSK_ExplicitSpecialization); - + // Note that this is an explicit instantiation of a member. + if (isa<FunctionDecl>(Member)) { + // FIXME: We're also setting the original instantiation we found to be + // an explicit specialization, although I'd rather not have to do this. + cast<FunctionDecl>(Instantiation)->setTemplateSpecializationKind( + TSK_ExplicitSpecialization); + cast<FunctionDecl>(Member)->setInstantiationOfMemberFunction( + cast<CXXMethodDecl>(InstantiatedFrom), + TSK_ExplicitSpecialization); + } else if (isa<VarDecl>(Member)) { + Context.setInstantiatedFromStaticDataMember(cast<VarDecl>(Member), + cast<VarDecl>(InstantiatedFrom), + TSK_ExplicitSpecialization); + } else { + assert(isa<CXXRecordDecl>(Member) && "Only member classes remain"); + // FIXME: Record TSK_ExplicitSpecialization. + cast<CXXRecordDecl>(Member)->setInstantiationOfMemberClass( + cast<CXXRecordDecl>(InstantiatedFrom)); + } + // Save the caller the trouble of having to figure out which declaration // this specialization matches. PrevDecl = Instantiation; @@ -3547,7 +3579,8 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, } // Instantiate static data member. - // FIXME: Note that this is an explicit instantiation. + // FIXME: Check for prior specializations and such. + Prev->setTemplateSpecializationKind(TSK); if (TSK == TSK_ExplicitInstantiationDefinition) InstantiateStaticDataMemberDefinition(D.getIdentifierLoc(), Prev, false); |