diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaCXXScopeSpec.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 17 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 34 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 15 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 5 |
6 files changed, 66 insertions, 20 deletions
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index 5e6c27b15d..5a0fceca20 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -246,10 +246,14 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS, EnumDecl *ED = enumType->getDecl(); if (EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) { MemberSpecializationInfo *MSI = ED->getMemberSpecializationInfo(); - if (MSI->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) - return InstantiateEnum(loc, ED, Pattern, - getTemplateInstantiationArgs(ED), - TSK_ImplicitInstantiation); + if (MSI->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) { + if (InstantiateEnum(loc, ED, Pattern, getTemplateInstantiationArgs(ED), + TSK_ImplicitInstantiation)) { + SS.SetInvalid(SS.getRange()); + return true; + } + return false; + } } Diag(loc, diag::err_incomplete_nested_name_spec) diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 15cd745d07..71f567f47a 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -8283,10 +8283,19 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // If we're defining a specialization and the previous definition // is from an implicit instantiation, don't emit an error // here; we'll catch this in the general case below. - if (!isExplicitSpecialization || - !isa<CXXRecordDecl>(Def) || - cast<CXXRecordDecl>(Def)->getTemplateSpecializationKind() - == TSK_ExplicitSpecialization) { + bool IsExplicitSpecializationAfterInstantiation = false; + if (isExplicitSpecialization) { + if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Def)) + IsExplicitSpecializationAfterInstantiation = + RD->getTemplateSpecializationKind() != + TSK_ExplicitSpecialization; + else if (EnumDecl *ED = dyn_cast<EnumDecl>(Def)) + IsExplicitSpecializationAfterInstantiation = + ED->getTemplateSpecializationKind() != + TSK_ExplicitSpecialization; + } + + if (!IsExplicitSpecializationAfterInstantiation) { // A redeclaration in function prototype scope in C isn't // visible elsewhere, so merely issue a warning. if (!getLangOpts().CPlusPlus && S->containedInPrototypeScope()) diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 0382a83548..e47bc1c8b1 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -1413,8 +1413,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, assert((!isa<TagDecl>(LookupCtx) || LookupCtx->isDependentContext() || cast<TagDecl>(LookupCtx)->isCompleteDefinition() || - Context.getTypeDeclType(cast<TagDecl>(LookupCtx))->getAs<TagType>() - ->isBeingDefined()) && + cast<TagDecl>(LookupCtx)->isBeingDefined()) && "Declaration context must already be complete!"); // Perform qualified name lookup into the LookupCtx. diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 680e6eaf2e..3a4a6f5312 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -4699,8 +4699,11 @@ static bool CheckTemplateSpecializationScope(Sema &S, EntityKind = 4; else if (isa<RecordDecl>(Specialized)) EntityKind = 5; + else if (isa<EnumDecl>(Specialized) && S.getLangOpts().CPlusPlus0x) + EntityKind = 6; else { - S.Diag(Loc, diag::err_template_spec_unknown_kind); + S.Diag(Loc, diag::err_template_spec_unknown_kind) + << S.getLangOpts().CPlusPlus0x; S.Diag(Specialized->getLocation(), diag::note_specialized_entity); return true; } @@ -5816,6 +5819,14 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) { InstantiatedFrom = PrevRecord->getInstantiatedFromMemberClass(); MSInfo = PrevRecord->getMemberSpecializationInfo(); } + } else if (isa<EnumDecl>(Member)) { + EnumDecl *PrevEnum; + if (Previous.isSingleResult() && + (PrevEnum = dyn_cast<EnumDecl>(Previous.getFoundDecl()))) { + Instantiation = PrevEnum; + InstantiatedFrom = PrevEnum->getInstantiatedFromMemberEnum(); + MSInfo = PrevEnum->getMemberSpecializationInfo(); + } } if (!Instantiation) { @@ -5906,8 +5917,7 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) { cast<VarDecl>(InstantiatedFrom), TSK_ExplicitSpecialization); MarkUnusedFileScopedDecl(InstantiationVar); - } else { - assert(isa<CXXRecordDecl>(Member) && "Only member classes remain"); + } else if (isa<CXXRecordDecl>(Member)) { CXXRecordDecl *InstantiationClass = cast<CXXRecordDecl>(Instantiation); if (InstantiationClass->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) { @@ -5919,6 +5929,18 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) { cast<CXXRecordDecl>(Member)->setInstantiationOfMemberClass( cast<CXXRecordDecl>(InstantiatedFrom), TSK_ExplicitSpecialization); + } else { + assert(isa<EnumDecl>(Member) && "Only member enums remain"); + EnumDecl *InstantiationEnum = cast<EnumDecl>(Instantiation); + if (InstantiationEnum->getTemplateSpecializationKind() == + TSK_ImplicitInstantiation) { + InstantiationEnum->setTemplateSpecializationKind( + TSK_ExplicitSpecialization); + InstantiationEnum->setLocation(Member->getLocation()); + } + + cast<EnumDecl>(Member)->setInstantiationOfMemberEnum( + cast<EnumDecl>(InstantiatedFrom), TSK_ExplicitSpecialization); } // Save the caller the trouble of having to figure out which declaration @@ -6219,11 +6241,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, return true; TagDecl *Tag = cast<TagDecl>(TagD); - if (Tag->isEnum()) { - Diag(TemplateLoc, diag::err_explicit_instantiation_enum) - << Context.getTypeDeclType(Tag); - return true; - } + assert(!Tag->isEnum() && "shouldn't see enumerations here"); if (Tag->isInvalidDecl()) return true; diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index c2ebbf4b55..afa65ea9ee 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -1843,7 +1843,20 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, if (OldField->getInClassInitializer()) FieldsWithMemberInitializers.push_back(std::make_pair(OldField, Field)); - } else if (NewMember->isInvalidDecl()) + } else if (EnumDecl *Enum = dyn_cast<EnumDecl>(NewMember)) { + // C++11 [temp.inst]p1: The implicit instantiation of a class template + // specialization causes the implicit instantiation of the definitions + // of unscoped member enumerations. + // Record a point of instantiation for this implicit instantiation. + if (TSK == TSK_ImplicitInstantiation && !Enum->isScoped()) { + MemberSpecializationInfo *MSInfo =Enum->getMemberSpecializationInfo(); + assert(MSInfo && "no spec info for member enum specialization"); + MSInfo->setTemplateSpecializationKind(TSK_ImplicitInstantiation); + MSInfo->setPointOfInstantiation(PointOfInstantiation); + } + } + + if (NewMember->isInvalidDecl()) Invalid = true; } else { // FIXME: Eventually, a NULL return will mean that one of the diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index d0ba4db0b5..ebc43d443d 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -600,7 +600,7 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { // not the definitions of scoped member enumerations. // FIXME: There appears to be no wording for what happens for an enum defined // within a block scope, but we treat that like a member of a class template. - if (!Enum->isScoped()) + if (!Enum->isScoped() && D->getDefinition()) InstantiateEnumDefinition(Enum, D); return Enum; @@ -610,6 +610,9 @@ void TemplateDeclInstantiator::InstantiateEnumDefinition( EnumDecl *Enum, EnumDecl *Pattern) { Enum->startDefinition(); + // Update the location to refer to the definition. + Enum->setLocation(Pattern->getLocation()); + SmallVector<Decl*, 4> Enumerators; EnumConstantDecl *LastEnumConst = 0; |