summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaTemplate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r--lib/Sema/SemaTemplate.cpp87
1 files changed, 73 insertions, 14 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 1e7176222b57..37eeee2f8867 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -836,7 +836,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
AccessSpecifier AS, SourceLocation ModulePrivateLoc,
SourceLocation FriendLoc,
unsigned NumOuterTemplateParamLists,
- TemplateParameterList** OuterTemplateParamLists) {
+ TemplateParameterList** OuterTemplateParamLists,
+ SkipBodyInfo *SkipBody) {
assert(TemplateParams && TemplateParams->size() > 0 &&
"No template parameters");
assert(TUK != TUK_Reference && "Can only declare or define class templates");
@@ -993,6 +994,19 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// Check for redefinition of this class template.
if (TUK == TUK_Definition) {
if (TagDecl *Def = PrevRecordDecl->getDefinition()) {
+ // If we have a prior definition that is not visible, treat this as
+ // simply making that previous definition visible.
+ NamedDecl *Hidden = nullptr;
+ if (SkipBody && !hasVisibleDefinition(Def, &Hidden)) {
+ SkipBody->ShouldSkip = true;
+ auto *Tmpl = cast<CXXRecordDecl>(Hidden)->getDescribedClassTemplate();
+ assert(Tmpl && "original definition of a class template is not a "
+ "class template?");
+ makeMergedDefinitionVisible(Hidden, KWLoc);
+ makeMergedDefinitionVisible(Tmpl, KWLoc);
+ return Def;
+ }
+
Diag(NameLoc, diag::err_redefinition) << Name;
Diag(Def->getLocation(), diag::note_previous_definition);
// FIXME: Would it make sense to try to "forget" the previous
@@ -1296,6 +1310,9 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
// Merge default arguments for template type parameters.
TemplateTypeParmDecl *OldTypeParm
= OldParams? cast<TemplateTypeParmDecl>(*OldParam) : nullptr;
+ // FIXME: There might be a visible declaration of this template parameter.
+ if (OldTypeParm && !LookupResult::isVisible(*this, OldTypeParm))
+ OldTypeParm = nullptr;
if (NewTypeParm->isParameterPack()) {
assert(!NewTypeParm->hasDefaultArgument() &&
@@ -1341,6 +1358,8 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
// Merge default arguments for non-type template parameters
NonTypeTemplateParmDecl *OldNonTypeParm
= OldParams? cast<NonTypeTemplateParmDecl>(*OldParam) : nullptr;
+ if (OldNonTypeParm && !LookupResult::isVisible(*this, OldNonTypeParm))
+ OldNonTypeParm = nullptr;
if (NewNonTypeParm->isParameterPack()) {
assert(!NewNonTypeParm->hasDefaultArgument() &&
"Parameter packs can't have a default argument!");
@@ -1388,6 +1407,8 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
// Merge default arguments for template template parameters
TemplateTemplateParmDecl *OldTemplateParm
= OldParams? cast<TemplateTemplateParmDecl>(*OldParam) : nullptr;
+ if (OldTemplateParm && !LookupResult::isVisible(*this, OldTemplateParm))
+ OldTemplateParm = nullptr;
if (NewTemplateParm->isParameterPack()) {
assert(!NewTemplateParm->hasDefaultArgument() &&
"Parameter packs can't have a default argument!");
@@ -1798,7 +1819,7 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
}
} else if (const TemplateSpecializationType *TST
= T->getAs<TemplateSpecializationType>()) {
- if (TemplateDecl *Template = TST->getTemplateName().getAsTemplateDecl()) {
+ if (TemplateDecl *Template = TST->getTemplateName().getAsTemplateDecl()) {
ExpectedTemplateParams = Template->getTemplateParameters();
NeedNonemptyTemplateHeader = true;
}
@@ -5835,11 +5856,13 @@ static bool CheckTemplateSpecializationScope(Sema &S,
if (isa<TranslationUnitDecl>(SpecializedContext))
S.Diag(Loc, diag::err_template_spec_redecl_global_scope)
<< EntityKind << Specialized;
- else if (isa<NamespaceDecl>(SpecializedContext))
- S.Diag(Loc, diag::err_template_spec_redecl_out_of_scope)
- << EntityKind << Specialized
- << cast<NamedDecl>(SpecializedContext);
- else
+ else if (isa<NamespaceDecl>(SpecializedContext)) {
+ int Diag = diag::err_template_spec_redecl_out_of_scope;
+ if (S.getLangOpts().MicrosoftExt)
+ Diag = diag::ext_ms_template_spec_redecl_out_of_scope;
+ S.Diag(Loc, Diag) << EntityKind << Specialized
+ << cast<NamedDecl>(SpecializedContext);
+ } else
llvm_unreachable("unexpected namespace context for specialization");
S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
@@ -6036,7 +6059,9 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
SourceLocation ModulePrivateLoc,
TemplateIdAnnotation &TemplateId,
AttributeList *Attr,
- MultiTemplateParamsArg TemplateParameterLists) {
+ MultiTemplateParamsArg
+ TemplateParameterLists,
+ SkipBodyInfo *SkipBody) {
assert(TUK != TUK_Reference && "References are not specializations");
CXXScopeSpec &SS = TemplateId.SS;
@@ -6347,7 +6372,14 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
// Check that this isn't a redefinition of this specialization.
if (TUK == TUK_Definition) {
- if (RecordDecl *Def = Specialization->getDefinition()) {
+ RecordDecl *Def = Specialization->getDefinition();
+ NamedDecl *Hidden = nullptr;
+ if (Def && SkipBody && !hasVisibleDefinition(Def, &Hidden)) {
+ SkipBody->ShouldSkip = true;
+ makeMergedDefinitionVisible(Hidden, KWLoc);
+ // From here on out, treat this as just a redeclaration.
+ TUK = TUK_Declaration;
+ } else if (Def) {
SourceRange Range(TemplateNameLoc, RAngleLoc);
Diag(TemplateNameLoc, diag::err_redefinition)
<< Context.getTypeDeclType(Specialization) << Range;
@@ -7177,9 +7209,27 @@ Sema::ActOnExplicitInstantiation(Scope *S,
// There are two forms of explicit instantiation: an explicit instantiation
// definition and an explicit instantiation declaration. An explicit
// instantiation declaration begins with the extern keyword. [...]
- TemplateSpecializationKind TSK
- = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition
- : TSK_ExplicitInstantiationDeclaration;
+ TemplateSpecializationKind TSK = ExternLoc.isInvalid()
+ ? TSK_ExplicitInstantiationDefinition
+ : TSK_ExplicitInstantiationDeclaration;
+
+ if (TSK == TSK_ExplicitInstantiationDeclaration) {
+ // Check for dllexport class template instantiation declarations.
+ for (AttributeList *A = Attr; A; A = A->getNext()) {
+ if (A->getKind() == AttributeList::AT_DLLExport) {
+ Diag(ExternLoc,
+ diag::warn_attribute_dllexport_explicit_instantiation_decl);
+ Diag(A->getLoc(), diag::note_attribute);
+ break;
+ }
+ }
+
+ if (auto *A = ClassTemplate->getTemplatedDecl()->getAttr<DLLExportAttr>()) {
+ Diag(ExternLoc,
+ diag::warn_attribute_dllexport_explicit_instantiation_decl);
+ Diag(A->getLocation(), diag::note_attribute);
+ }
+ }
// Translate the parser's template argument list in our AST format.
TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
@@ -7315,10 +7365,19 @@ Sema::ActOnExplicitInstantiation(Scope *S,
// Fix a TSK_ExplicitInstantiationDeclaration followed by a
// TSK_ExplicitInstantiationDefinition
if (Old_TSK == TSK_ExplicitInstantiationDeclaration &&
- TSK == TSK_ExplicitInstantiationDefinition)
+ TSK == TSK_ExplicitInstantiationDefinition) {
// FIXME: Need to notify the ASTMutationListener that we did this.
Def->setTemplateSpecializationKind(TSK);
+ if (!getDLLAttr(Def) && getDLLAttr(Specialization)) {
+ auto *A = cast<InheritableAttr>(
+ getDLLAttr(Specialization)->clone(getASTContext()));
+ A->setInherited(true);
+ Def->addAttr(A);
+ checkClassLevelDLLAttribute(Def);
+ }
+ }
+
InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);
}
@@ -8285,7 +8344,7 @@ void Sema::MarkAsLateParsedTemplate(FunctionDecl *FD, Decl *FnD,
// Take tokens to avoid allocations
LPT->Toks.swap(Toks);
LPT->D = FnD;
- LateParsedTemplateMap[FD] = LPT;
+ LateParsedTemplateMap.insert(std::make_pair(FD, LPT));
FD->setLateTemplateParsed(true);
}