diff options
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 81 |
1 files changed, 70 insertions, 11 deletions
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 92ba095..3c19641 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -13,6 +13,7 @@ #include "clang/Sema/SemaInternal.h" #include "TreeTransform.h" #include "clang/Sema/DeclSpec.h" +#include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Template.h" #include "clang/Sema/TemplateDeduction.h" @@ -58,9 +59,13 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D, Result.addOuterTemplateArguments(Innermost); DeclContext *Ctx = dyn_cast<DeclContext>(D); - if (!Ctx) + if (!Ctx) { Ctx = D->getDeclContext(); - + + assert((!D->isTemplateParameter() || !Ctx->isTranslationUnit()) && + "Template parameter doesn't have its context yet!"); + } + while (!Ctx->isFileContext()) { // Add template arguments from a class template instantiation. if (ClassTemplateSpecializationDecl *Spec @@ -446,10 +451,15 @@ void Sema::PrintInstantiationStack() { Diags.Report(Active->PointOfInstantiation, DiagID) << Function << Active->InstantiationRange; - } else { + } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) { Diags.Report(Active->PointOfInstantiation, diag::note_template_static_data_member_def_here) - << cast<VarDecl>(D) + << VD + << Active->InstantiationRange; + } else { + Diags.Report(Active->PointOfInstantiation, + diag::note_template_type_alias_instantiation_here) + << cast<TypeAliasTemplateDecl>(D) << Active->InstantiationRange; } break; @@ -918,7 +928,8 @@ TemplateInstantiator::RebuildElaboratedType(SourceLocation KeywordLoc, // like it's likely to produce a lot of spurious errors. if (Keyword != ETK_None && Keyword != ETK_Typename) { TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForKeyword(Keyword); - if (!SemaRef.isAcceptableTagRedeclaration(TD, Kind, TagLocation, *Id)) { + if (!SemaRef.isAcceptableTagRedeclaration(TD, Kind, /*isDefinition*/false, + TagLocation, *Id)) { SemaRef.Diag(TagLocation, diag::err_use_with_wrong_tag) << Id << FixItHint::CreateReplacement(SourceRange(TagLocation), @@ -968,8 +979,7 @@ TemplateName TemplateInstantiator::TransformTemplateName(CXXScopeSpec &SS, } TemplateName Template = Arg.getAsTemplate(); - assert(!Template.isNull() && Template.getAsTemplateDecl() && - "Wrong kind of template template argument"); + assert(!Template.isNull() && "Null template template argument"); // We don't ever want to substitute for a qualified template name, since // the qualifier is handled separately. So, look through the qualified @@ -1384,6 +1394,12 @@ static bool NeedsInstantiationAsFunctionType(TypeSourceInfo *T) { for (unsigned I = 0, E = FP.getNumArgs(); I != E; ++I) { ParmVarDecl *P = FP.getArg(I); + // The parameter's type as written might be dependent even if the + // decayed type was not dependent. + if (TypeSourceInfo *TSInfo = P->getTypeSourceInfo()) + if (TSInfo->getType()->isDependentType()) + return true; + // TODO: currently we always rebuild expressions. When we // properly get lazier about this, we should use the same // logic to avoid rebuilding prototypes here. @@ -1729,6 +1745,8 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, TemplateDeclInstantiator Instantiator(*this, Instantiation, TemplateArgs); llvm::SmallVector<Decl*, 4> Fields; + llvm::SmallVector<std::pair<FieldDecl*, FieldDecl*>, 4> + FieldsWithMemberInitializers; for (RecordDecl::decl_iterator Member = Pattern->decls_begin(), MemberEnd = Pattern->decls_end(); Member != MemberEnd; ++Member) { @@ -1751,9 +1769,13 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, Decl *NewMember = Instantiator.Visit(*Member); if (NewMember) { - if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember)) + if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember)) { Fields.push_back(Field); - else if (NewMember->isInvalidDecl()) + FieldDecl *OldField = cast<FieldDecl>(*Member); + if (OldField->getInClassInitializer()) + FieldsWithMemberInitializers.push_back(std::make_pair(OldField, + Field)); + } else if (NewMember->isInvalidDecl()) Invalid = true; } else { // FIXME: Eventually, a NULL return will mean that one of the @@ -1767,6 +1789,43 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, Fields.data(), Fields.size(), SourceLocation(), SourceLocation(), 0); CheckCompletedCXXClass(Instantiation); + + // Attach any in-class member initializers now the class is complete. + for (unsigned I = 0, N = FieldsWithMemberInitializers.size(); I != N; ++I) { + FieldDecl *OldField = FieldsWithMemberInitializers[I].first; + FieldDecl *NewField = FieldsWithMemberInitializers[I].second; + Expr *OldInit = OldField->getInClassInitializer(); + ExprResult NewInit = SubstExpr(OldInit, TemplateArgs); + + // If the initialization is no longer dependent, check it now. + if ((OldField->getType()->isDependentType() || OldInit->isTypeDependent()) + && !NewField->getType()->isDependentType() + && !NewInit.get()->isTypeDependent()) { + // FIXME: handle list-initialization + SourceLocation EqualLoc = NewField->getLocation(); + NewInit = PerformCopyInitialization( + InitializedEntity::InitializeMember(NewField), EqualLoc, + NewInit.release()); + + if (!NewInit.isInvalid()) { + CheckImplicitConversions(NewInit.get(), EqualLoc); + + // C++0x [class.base.init]p7: + // The initialization of each base and member constitutes a + // full-expression. + NewInit = MaybeCreateExprWithCleanups(NewInit); + } + } + + if (NewInit.isInvalid()) + NewField->setInvalidDecl(); + else + NewField->setInClassInitializer(NewInit.release()); + } + + if (!FieldsWithMemberInitializers.empty()) + ActOnFinishDelayedMemberInitializers(Instantiation); + if (Instantiation->isInvalidDecl()) Invalid = true; else { @@ -2009,7 +2068,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation, SuppressNew) continue; - if (Function->hasBody()) + if (Function->isDefined()) continue; if (TSK == TSK_ExplicitInstantiationDefinition) { @@ -2019,7 +2078,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation, // specialization and is only an explicit instantiation definition // of members whose definition is visible at the point of // instantiation. - if (!Pattern->hasBody()) + if (!Pattern->isDefined()) continue; Function->setTemplateSpecializationKind(TSK, PointOfInstantiation); |