diff options
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 87 |
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); } |