aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-05-14 00:28:11 +0000
committerDouglas Gregor <dgregor@apple.com>2009-05-14 00:28:11 +0000
commit3f5b61c394f4f205bcb4d316eb2a7a0a68b8af86 (patch)
tree4da57b179612b81db0cd320a032aa390044f29db /lib/Sema
parent88f1ba0f0439e31ab57ffc088aa91137cadee585 (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.h9
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp3
-rw-r--r--lib/Sema/SemaDecl.cpp9
-rw-r--r--lib/Sema/SemaExprCXX.cpp5
-rw-r--r--lib/Sema/SemaTemplate.cpp81
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp2
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;
}