summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaTemplateInstantiate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiate.cpp')
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp81
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);
OpenPOWER on IntegriCloud