diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-04-26 01:51:07 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-04-26 01:51:07 +0000 |
commit | 0d923af49270ef4beb5d479dac5bda80fc0082ef (patch) | |
tree | 20ee0d3dde5e845d9827bc7ae54f4121310ad68b /clang/lib/Sema/SemaTemplate.cpp | |
parent | 0184819e818ffad2a9be6987753458eeb729f858 (diff) | |
download | bcm5719-llvm-0d923af49270ef4beb5d479dac5bda80fc0082ef.tar.gz bcm5719-llvm-0d923af49270ef4beb5d479dac5bda80fc0082ef.zip |
Add missing diagnostic for explicit instantiation declarations naming
internal linkage entities.
Such constructs are ill-formed by [temp.explicit]p13. We make a special
exception to permit an invalid construct used by libc++ in some build
modes: its <valarray> header declares some functions with the
internal_linkage attribute and then (meaninglessly) provides explicit
instantiation declarations for them. Luckily, Clang happens to
effectively ignore the explicit instantiation declaration when
generating code in this case, and this change codifies that behavior.
This reinstates part of r359048, reverted in r359076. (The libc++ issue
triggering the rollback has been addressed.)
llvm-svn: 359259
Diffstat (limited to 'clang/lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 66 |
1 files changed, 46 insertions, 20 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 10103708384..973911eb840 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -8619,6 +8619,29 @@ static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D, return false; } +/// Common checks for whether an explicit instantiation of \p D is valid. +static bool CheckExplicitInstantiation(Sema &S, NamedDecl *D, + SourceLocation InstLoc, + bool WasQualifiedName, + TemplateSpecializationKind TSK) { + // C++ [temp.explicit]p13: + // An explicit instantiation declaration shall not name a specialization of + // a template with internal linkage. + if (TSK == TSK_ExplicitInstantiationDeclaration && + D->getFormalLinkage() == InternalLinkage) { + S.Diag(InstLoc, diag::err_explicit_instantiation_internal_linkage) << D; + return true; + } + + // C++11 [temp.explicit]p3: [DR 275] + // An explicit instantiation shall appear in an enclosing namespace of its + // template. + if (CheckExplicitInstantiationScope(S, D, InstLoc, WasQualifiedName)) + return true; + + return false; +} + /// Determine whether the given scope specifier has a template-id in it. static bool ScopeSpecifierHasTemplateId(const CXXScopeSpec &SS) { if (!SS.isSet()) @@ -8770,13 +8793,8 @@ DeclResult Sema::ActOnExplicitInstantiation( TemplateSpecializationKind PrevDecl_TSK = PrevDecl ? PrevDecl->getTemplateSpecializationKind() : TSK_Undeclared; - // C++0x [temp.explicit]p2: - // [...] An explicit instantiation shall appear in an enclosing - // namespace of its template. [...] - // - // This is C++ DR 275. - if (CheckExplicitInstantiationScope(*this, ClassTemplate, TemplateNameLoc, - SS.isSet())) + if (CheckExplicitInstantiation(*this, ClassTemplate, TemplateNameLoc, + SS.isSet(), TSK)) return true; ClassTemplateSpecializationDecl *Specialization = nullptr; @@ -8999,12 +9017,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc, = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition : TSK_ExplicitInstantiationDeclaration; - // C++0x [temp.explicit]p2: - // [...] An explicit instantiation shall appear in an enclosing - // namespace of its template. [...] - // - // This is C++ DR 275. - CheckExplicitInstantiationScope(*this, Record, NameLoc, true); + CheckExplicitInstantiation(*this, Record, NameLoc, true, TSK); // Verify that it is okay to explicitly instantiate here. CXXRecordDecl *PrevDecl @@ -9235,8 +9248,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, diag::ext_explicit_instantiation_without_qualified_id) << Prev << D.getCXXScopeSpec().getRange(); - // Check the scope of this explicit instantiation. - CheckExplicitInstantiationScope(*this, Prev, D.getIdentifierLoc(), true); + CheckExplicitInstantiation(*this, Prev, D.getIdentifierLoc(), true, TSK); // Verify that it is okay to explicitly instantiate here. TemplateSpecializationKind PrevTSK = Prev->getTemplateSpecializationKind(); @@ -9411,6 +9423,20 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, return (Decl*) nullptr; } + // HACK: libc++ has a bug where it attempts to explicitly instantiate the + // functions + // valarray<size_t>::valarray(size_t) and + // valarray<size_t>::~valarray() + // that it declared to have internal linkage with the internal_linkage + // attribute. Ignore the explicit instantiation declaration in this case. + if (Specialization->hasAttr<InternalLinkageAttr>() && + TSK == TSK_ExplicitInstantiationDeclaration) { + if (auto *RD = dyn_cast<CXXRecordDecl>(Specialization->getDeclContext())) + if (RD->getIdentifier() && RD->getIdentifier()->isStr("valarray") && + RD->isInStdNamespace()) + return (Decl*) nullptr; + } + ProcessDeclAttributeList(S, Specialization, D.getDeclSpec().getAttributes()); // In MSVC mode, dllimported explicit instantiation definitions are treated as @@ -9444,11 +9470,11 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, diag::ext_explicit_instantiation_without_qualified_id) << Specialization << D.getCXXScopeSpec().getRange(); - CheckExplicitInstantiationScope(*this, - FunTmpl? (NamedDecl *)FunTmpl - : Specialization->getInstantiatedFromMemberFunction(), - D.getIdentifierLoc(), - D.getCXXScopeSpec().isSet()); + CheckExplicitInstantiation( + *this, + FunTmpl ? (NamedDecl *)FunTmpl + : Specialization->getInstantiatedFromMemberFunction(), + D.getIdentifierLoc(), D.getCXXScopeSpec().isSet(), TSK); // FIXME: Create some kind of ExplicitInstantiationDecl here. return (Decl*) nullptr; |