diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-05-14 00:28:11 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-05-14 00:28:11 +0000 |
commit | 3f5b61c394f4f205bcb4d316eb2a7a0a68b8af86 (patch) | |
tree | 4da57b179612b81db0cd320a032aa390044f29db /lib/Sema | |
parent | 88f1ba0f0439e31ab57ffc088aa91137cadee585 (diff) |
Implement explicit instantiations of member classes of class templates, e.g.,
template<typename T>
struct X {
struct Inner;
};
template struct X<int>::Inner;
This change is larger than it looks because it also fixes some
a problem with nested-name-specifiers and tags. We weren't requiring
the DeclContext associated with the scope specifier of a tag to be
complete. Therefore, when looking for something like "struct
X<int>::Inner", we weren't instantiating X<int>.
This, naturally, uncovered a problem with member pointers, where we
were requiring the left-hand side of a member pointer access
expression (e.g., x->*) to be a complete type. However, this is wrong:
the semantics of this expression does not require a complete type (EDG
agrees).
Stuart vouched for me. Blame him.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71756 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Sema.h | 9 | ||||
-rw-r--r-- | lib/Sema/SemaCXXScopeSpec.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 9 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 81 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 2 |
6 files changed, 99 insertions, 10 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 08f9b02d77..bd01ec9e51 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1919,6 +1919,15 @@ public: SourceLocation RAngleLoc, AttributeList *Attr); + virtual DeclResult + ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, + unsigned TagSpec, + SourceLocation KWLoc, + const CXXScopeSpec &SS, + IdentifierInfo *Name, + SourceLocation NameLoc, + AttributeList *Attr); + bool CheckTemplateArgumentList(TemplateDecl *Template, SourceLocation TemplateLoc, SourceLocation LAngleLoc, diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index bbc1bc52cb..11ac0bd300 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -273,8 +273,9 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S, SourceLocation CCLoc) { NestedNameSpecifier *Prefix = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); + QualType T = QualType::getFromOpaquePtr(Ty); return NestedNameSpecifier::Create(Context, Prefix, /*FIXME:*/false, - QualType::getFromOpaquePtr(Ty).getTypePtr()); + T.getTypePtr()); } /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 5914292dab..e27517e689 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3254,12 +3254,15 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, goto CreateNewDecl; } - // FIXME: RequireCompleteDeclContext(SS)? + if (RequireCompleteDeclContext(SS)) + return DeclPtrTy::make((Decl *)0); + DC = computeDeclContext(SS); SearchDC = DC; // Look-up name inside 'foo::'. - PrevDecl = dyn_cast_or_null<TagDecl>( - LookupQualifiedName(DC, Name, LookupTagName, true).getAsDecl()); + PrevDecl + = dyn_cast_or_null<TagDecl>( + LookupQualifiedName(DC, Name, LookupTagName, true).getAsDecl()); // A tag 'foo::bar' must already exist. if (PrevDecl == 0) { diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 5f2b705498..57aae29631 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -994,10 +994,7 @@ QualType Sema::CheckPointerToMemberOperands( Diag(Loc, diag::err_bad_memptr_rhs) << OpSpelling << RType << rex->getSourceRange(); return QualType(); - } else if (RequireCompleteType(Loc, QualType(MemPtr->getClass(), 0), - diag::err_memptr_rhs_incomplete, - rex->getSourceRange())) - return QualType(); + } QualType Class(MemPtr->getClass(), 0); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 22f2bef0e9..7190df107e 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -2155,6 +2155,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, return DeclPtrTy::make(Specialization); } +// Explicit instantiation of a class template specialization Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, unsigned TagSpec, @@ -2244,7 +2245,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, } if (PrevDecl->getSpecializationKind() == TSK_ExplicitSpecialization) { - // C++0x [temp.explicit]p4: + // C++ DR 259, C++0x [temp.explicit]p4: // For a given set of template parameters, if an explicit // instantiation of a template appears after a declaration of // an explicit specialization for that template, the explicit @@ -2342,6 +2343,84 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, return DeclPtrTy::make(Specialization); } +// Explicit instantiation of a member class of a class template. +Sema::DeclResult +Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, + unsigned TagSpec, + SourceLocation KWLoc, + const CXXScopeSpec &SS, + IdentifierInfo *Name, + SourceLocation NameLoc, + AttributeList *Attr) { + + DeclPtrTy TagD = ActOnTag(S, TagSpec, Action::TK_Reference, + KWLoc, SS, Name, NameLoc, Attr, AS_none); + if (!TagD) + return true; + + TagDecl *Tag = cast<TagDecl>(TagD.getAs<Decl>()); + if (Tag->isEnum()) { + Diag(TemplateLoc, diag::err_explicit_instantiation_enum) + << Context.getTypeDeclType(Tag); + return true; + } + + CXXRecordDecl *Record = cast<CXXRecordDecl>(Tag); + CXXRecordDecl *Pattern = Record->getInstantiatedFromMemberClass(); + if (!Pattern) { + Diag(TemplateLoc, diag::err_explicit_instantiation_nontemplate_type) + << Context.getTypeDeclType(Record); + Diag(Record->getLocation(), diag::note_nontemplate_decl_here); + return true; + } + + // C++0x [temp.explicit]p2: + // [...] An explicit instantiation shall appear in an enclosing + // namespace of its template. [...] + // + // This is C++ DR 275. + if (getLangOptions().CPlusPlus0x) { + // FIXME: In C++98, we would like to turn these errors into + // warnings, dependent on a -Wc++0x flag. + DeclContext *PatternContext + = Pattern->getDeclContext()->getEnclosingNamespaceContext(); + if (!CurContext->Encloses(PatternContext)) { + Diag(TemplateLoc, diag::err_explicit_instantiation_out_of_scope) + << Record << cast<NamedDecl>(PatternContext) << SS.getRange(); + Diag(Pattern->getLocation(), diag::note_previous_declaration); + } + } + + // Find the enclosing template, because we need its template + // arguments to instantiate this class. + DeclContext *EnclosingTemplateCtx = Record->getDeclContext(); + while (!isa<ClassTemplateSpecializationDecl>(EnclosingTemplateCtx)) + EnclosingTemplateCtx = EnclosingTemplateCtx->getParent(); + ClassTemplateSpecializationDecl *EnclosingTemplate + = cast<ClassTemplateSpecializationDecl>(EnclosingTemplateCtx); + + if (!Record->getDefinition(Context)) { + // If the class has a definition, instantiate it (and all of its + // members, recursively). + Pattern = cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context)); + if (Pattern && InstantiateClass(TemplateLoc, Record, Pattern, + EnclosingTemplate->getTemplateArgs(), + /*ExplicitInstantiation=*/true)) + return true; + } else { + // Instantiate all of the members of class. + InstantiatingTemplate Inst(*this, TemplateLoc, Record); + InstantiateClassMembers(TemplateLoc, Record, + EnclosingTemplate->getTemplateArgs()); + } + + // FIXME: We don't have any representation for explicit + // instantiations of member classes. Such a representation is not + // needed for compilation, but it should be available for clients + // that want to see all of the declarations in the source code. + return TagD; +} + Sema::TypeResult Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS, const IdentifierInfo &II, SourceLocation IdLoc) { diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 9c2c4230f9..5c6ed758d9 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -863,7 +863,7 @@ Sema::InstantiateNestedNameSpecifier(NestedNameSpecifier *NNS, ActOnCXXNestedNameSpecifier(0, SS, Range.getEnd(), Range.getEnd(), - *NNS->getAsIdentifier())); + *NNS->getAsIdentifier())); break; } |