Author: ibiryukov Date: Wed Apr 24 01:50:24 2019 New Revision: 359076 URL: http://llvm.org/viewvc/llvm-project?rev=359076&view=rev Log: Revert r359048: C++ DR2387: a variable template declared wthi
The change breaks libc++ with the follwing error: In file included from valarray:4: .../include/c++/v1/valarray:1062:60: error: explicit instantiation declaration of 'valarray<_Tp>' with internal linkage _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS valarray<size_t>::valarray(size_t)) ^ .../include/c++/v1/valarray:1063:60: error: explicit instantiation declaration of '~valarray<_Tp>' with internal linkage _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS valarray<size_t>::~valarray()) Removed: cfe/trunk/test/CXX/drs/dr23xx.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/AST/Decl.cpp cfe/trunk/lib/Sema/SemaTemplate.cpp cfe/trunk/test/CXX/drs/dr0xx.cpp cfe/trunk/test/CXX/drs/dr17xx.cpp cfe/trunk/test/CXX/module/module.interface/p3.cpp cfe/trunk/test/CXX/module/module.interface/p5.cpp cfe/trunk/test/CodeGenCXX/cxx1y-variable-template-linkage.cpp cfe/trunk/test/SemaCXX/PR10177.cpp cfe/trunk/test/SemaCXX/warn-unused-filescoped.cpp cfe/trunk/test/SemaCXX/warn-unused-variables.cpp cfe/trunk/www/cxx_dr_status.html Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=359076&r1=359075&r2=359076&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Apr 24 01:50:24 2019 @@ -4384,8 +4384,6 @@ def err_explicit_instantiation_of_typede "explicit instantiation of typedef %0">; def err_explicit_instantiation_storage_class : Error< "explicit instantiation cannot have a storage class">; -def err_explicit_instantiation_internal_linkage : Error< - "explicit instantiation declaration of %0 with internal linkage">; def err_explicit_instantiation_not_known : Error< "explicit instantiation of %0 does not refer to a function template, " "variable template, member function, member class, or static data member">; Modified: cfe/trunk/lib/AST/Decl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=359076&r1=359075&r2=359076&view=diff ============================================================================== --- cfe/trunk/lib/AST/Decl.cpp (original) +++ cfe/trunk/lib/AST/Decl.cpp Wed Apr 24 01:50:24 2019 @@ -610,18 +610,6 @@ static LinkageInfo getExternalLinkageFor return LinkageInfo::external(); } -static StorageClass getStorageClass(const Decl *D) { - if (auto *TD = dyn_cast<TemplateDecl>(D)) - D = TD->getTemplatedDecl(); - if (D) { - if (auto *VD = dyn_cast<VarDecl>(D)) - return VD->getStorageClass(); - if (auto *FD = dyn_cast<FunctionDecl>(D)) - return FD->getStorageClass(); - } - return SC_None; -} - LinkageInfo LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, LVComputationKind computation, @@ -633,28 +621,24 @@ LinkageComputer::getLVForNamespaceScopeD // C++ [basic.link]p3: // A name having namespace scope (3.3.6) has internal linkage if it // is the name of - - if (getStorageClass(D->getCanonicalDecl()) == SC_Static) { - // - a variable, variable template, function, or function template - // that is explicitly declared static; or - // (This bullet corresponds to C99 6.2.2p3.) - return getInternalLinkageFor(D); - } - + // - an object, reference, function or function template that is + // explicitly declared static; or, + // (This bullet corresponds to C99 6.2.2p3.) if (const auto *Var = dyn_cast<VarDecl>(D)) { - // - a non-template variable of non-volatile const-qualified type, unless - // - it is explicitly declared extern, or - // - it is inline or exported, or - // - it was previously declared and the prior declaration did not have - // internal linkage - // (There is no equivalent in C99.) + // Explicitly declared static. + if (Var->getStorageClass() == SC_Static) + return getInternalLinkageFor(Var); + + // - a non-inline, non-volatile object or reference that is explicitly + // declared const or constexpr and neither explicitly declared extern + // nor previously declared to have external linkage; or (there is no + // equivalent in C99) + // The C++ modules TS adds "non-exported" to this list. if (Context.getLangOpts().CPlusPlus && Var->getType().isConstQualified() && !Var->getType().isVolatileQualified() && !Var->isInline() && - !isExportedFromModuleInterfaceUnit(Var) && - !isa<VarTemplateSpecializationDecl>(Var) && - !Var->getDescribedVarTemplate()) { + !isExportedFromModuleInterfaceUnit(Var)) { const VarDecl *PrevVar = Var->getPreviousDecl(); if (PrevVar) return getLVForDecl(PrevVar, computation); @@ -674,6 +658,14 @@ LinkageComputer::getLVForNamespaceScopeD if (PrevVar->getStorageClass() == SC_Static) return getInternalLinkageFor(Var); } + } else if (const FunctionDecl *Function = D->getAsFunction()) { + // C++ [temp]p4: + // A non-member function template can have internal linkage; any + // other template name shall have external linkage. + + // Explicitly declared static. + if (Function->getCanonicalDecl()->getStorageClass() == SC_Static) + return getInternalLinkageFor(Function); } else if (const auto *IFD = dyn_cast<IndirectFieldDecl>(D)) { // - a data member of an anonymous union. const VarDecl *VD = IFD->getVarDecl(); @@ -682,8 +674,6 @@ LinkageComputer::getLVForNamespaceScopeD } assert(!isa<FieldDecl>(D) && "Didn't expect a FieldDecl!"); - // FIXME: This gives internal linkage to names that should have no linkage - // (those not covered by [basic.link]p6). if (D->isInAnonymousNamespace()) { const auto *Var = dyn_cast<VarDecl>(D); const auto *Func = dyn_cast<FunctionDecl>(D); @@ -743,20 +733,10 @@ LinkageComputer::getLVForNamespaceScopeD // C++ [basic.link]p4: - // A name having namespace scope that has not been given internal linkage - // above and that is the name of - // [...bullets...] - // has its linkage determined as follows: - // - if the enclosing namespace has internal linkage, the name has - // internal linkage; [handled above] - // - otherwise, if the declaration of the name is attached to a named - // module and is not exported, the name has module linkage; - // - otherwise, the name has external linkage. - // LV is currently set up to handle the last two bullets. + // A name having namespace scope has external linkage if it is the + // name of // - // The bullets are: - - // - a variable; or + // - an object or reference, unless it has internal linkage; or if (const auto *Var = dyn_cast<VarDecl>(D)) { // GCC applies the following optimization to variables and static // data members, but not to functions: @@ -802,7 +782,7 @@ LinkageComputer::getLVForNamespaceScopeD mergeTemplateLV(LV, spec, computation); } - // - a function; or + // - a function, unless it has internal linkage; or } else if (const auto *Function = dyn_cast<FunctionDecl>(D)) { // In theory, we can modify the function's LV by the LV of its // type unless it has C linkage (see comment above about variables @@ -856,8 +836,7 @@ LinkageComputer::getLVForNamespaceScopeD mergeTemplateLV(LV, spec, computation); } - // FIXME: This is not part of the C++ standard any more. - // - an enumerator belonging to an enumeration with external linkage; or + // - an enumerator belonging to an enumeration with external linkage; } else if (isa<EnumConstantDecl>(D)) { LinkageInfo EnumLV = getLVForDecl(cast<NamedDecl>(D->getDeclContext()), computation); @@ -865,16 +844,16 @@ LinkageComputer::getLVForNamespaceScopeD return LinkageInfo::none(); LV.merge(EnumLV); - // - a template + // - a template, unless it is a function template that has + // internal linkage (Clause 14); } else if (const auto *temp = dyn_cast<TemplateDecl>(D)) { bool considerVisibility = !hasExplicitVisibilityAlready(computation); LinkageInfo tempLV = getLVForTemplateParameterList(temp->getTemplateParameters(), computation); LV.mergeMaybeWithVisibility(tempLV, considerVisibility); - // An unnamed namespace or a namespace declared directly or indirectly - // within an unnamed namespace has internal linkage. All other namespaces - // have external linkage. + // - a namespace (7.3), unless it is declared within an unnamed + // namespace. // // We handled names in anonymous namespaces above. } else if (isa<NamespaceDecl>(D)) { Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=359076&r1=359075&r2=359076&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Apr 24 01:50:24 2019 @@ -8619,29 +8619,6 @@ static bool CheckExplicitInstantiationSc 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()) @@ -8793,8 +8770,13 @@ DeclResult Sema::ActOnExplicitInstantiat TemplateSpecializationKind PrevDecl_TSK = PrevDecl ? PrevDecl->getTemplateSpecializationKind() : TSK_Undeclared; - if (CheckExplicitInstantiation(*this, ClassTemplate, TemplateNameLoc, - SS.isSet(), TSK)) + // 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())) return true; ClassTemplateSpecializationDecl *Specialization = nullptr; @@ -9017,7 +8999,12 @@ Sema::ActOnExplicitInstantiation(Scope * = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition : TSK_ExplicitInstantiationDeclaration; - CheckExplicitInstantiation(*this, Record, NameLoc, true, TSK); + // 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); // Verify that it is okay to explicitly instantiate here. CXXRecordDecl *PrevDecl @@ -9248,7 +9235,8 @@ DeclResult Sema::ActOnExplicitInstantiat diag::ext_explicit_instantiation_without_qualified_id) << Prev << D.getCXXScopeSpec().getRange(); - CheckExplicitInstantiation(*this, Prev, D.getIdentifierLoc(), true, TSK); + // Check the scope of this explicit instantiation. + CheckExplicitInstantiationScope(*this, Prev, D.getIdentifierLoc(), true); // Verify that it is okay to explicitly instantiate here. TemplateSpecializationKind PrevTSK = Prev->getTemplateSpecializationKind(); @@ -9456,11 +9444,11 @@ DeclResult Sema::ActOnExplicitInstantiat diag::ext_explicit_instantiation_without_qualified_id) << Specialization << D.getCXXScopeSpec().getRange(); - CheckExplicitInstantiation( - *this, - FunTmpl ? (NamedDecl *)FunTmpl - : Specialization->getInstantiatedFromMemberFunction(), - D.getIdentifierLoc(), D.getCXXScopeSpec().isSet(), TSK); + CheckExplicitInstantiationScope(*this, + FunTmpl? (NamedDecl *)FunTmpl + : Specialization->getInstantiatedFromMemberFunction(), + D.getIdentifierLoc(), + D.getCXXScopeSpec().isSet()); // FIXME: Create some kind of ExplicitInstantiationDecl here. return (Decl*) nullptr; Modified: cfe/trunk/test/CXX/drs/dr0xx.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr0xx.cpp?rev=359076&r1=359075&r2=359076&view=diff ============================================================================== --- cfe/trunk/test/CXX/drs/dr0xx.cpp (original) +++ cfe/trunk/test/CXX/drs/dr0xx.cpp Wed Apr 24 01:50:24 2019 @@ -869,17 +869,18 @@ namespace dr68 { // dr68: yes } namespace dr69 { // dr69: yes - template<typename T> static void f() {} // #dr69-f + template<typename T> static void f() {} // FIXME: Should we warn here? inline void g() { f<int>(); } - extern template void f<char>(); // expected-error {{explicit instantiation declaration of 'f' with internal linkage}} + // FIXME: This should be rejected, per [temp.explicit]p11. + extern template void f<char>(); #if __cplusplus < 201103L // expected-error@-2 {{C++11 extension}} #endif template<void(*)()> struct Q {}; Q<&f<int> > q; #if __cplusplus < 201103L - // expected-error@-2 {{internal linkage}} expected-note@#dr69-f {{here}} + // expected-error@-2 {{internal linkage}} expected-note@-11 {{here}} #endif } Modified: cfe/trunk/test/CXX/drs/dr17xx.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr17xx.cpp?rev=359076&r1=359075&r2=359076&view=diff ============================================================================== --- cfe/trunk/test/CXX/drs/dr17xx.cpp (original) +++ cfe/trunk/test/CXX/drs/dr17xx.cpp Wed Apr 24 01:50:24 2019 @@ -77,7 +77,7 @@ namespace dr1758 { // dr1758: 3.7 #endif } -namespace dr1722 { // dr1722: 9 +namespace dr1722 { // dr1722: 9.0 #if __cplusplus >= 201103L void f() { const auto lambda = [](int x) { return x + 1; }; Removed: cfe/trunk/test/CXX/drs/dr23xx.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr23xx.cpp?rev=359075&view=auto ============================================================================== --- cfe/trunk/test/CXX/drs/dr23xx.cpp (original) +++ cfe/trunk/test/CXX/drs/dr23xx.cpp (removed) @@ -1,26 +0,0 @@ -// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++2a %s -verify -fexceptions -fcxx-exceptions -pedantic-errors - -#if __cplusplus <= 201103L -// expected-no-diagnostics -#endif - -namespace dr2387 { // dr2387: 9 -#if __cplusplus >= 201402L - template<int> int a = 0; - extern template int a<0>; // ok - - template<int> static int b = 0; - extern template int b<0>; // expected-error {{internal linkage}} - - template<int> const int c = 0; - extern template const int c<0>; // ok, has external linkage despite 'const' - - template<typename T> T d = 0; - extern template int d<int>; - extern template const int d<const int>; -#endif -} Modified: cfe/trunk/test/CXX/module/module.interface/p3.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/module/module.interface/p3.cpp?rev=359076&r1=359075&r2=359076&view=diff ============================================================================== --- cfe/trunk/test/CXX/module/module.interface/p3.cpp (original) +++ cfe/trunk/test/CXX/module/module.interface/p3.cpp Wed Apr 24 01:50:24 2019 @@ -48,7 +48,7 @@ export namespace { int c; } // expected- namespace { // expected-note {{here}} export int d; // expected-error {{export declaration appears within anonymous namespace}} } -export template<typename> static int e; // expected-error {{declaration of 'e' with internal linkage cannot be exported}} +export template<typename> static int e; // FIXME export template<typename> static int f(); // expected-error {{declaration of 'f' with internal linkage cannot be exported}} export const int k = 5; export static union { int n; }; // expected-error {{declaration of 'n' with internal linkage cannot be exported}} Modified: cfe/trunk/test/CXX/module/module.interface/p5.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/module/module.interface/p5.cpp?rev=359076&r1=359075&r2=359076&view=diff ============================================================================== --- cfe/trunk/test/CXX/module/module.interface/p5.cpp (original) +++ cfe/trunk/test/CXX/module/module.interface/p5.cpp Wed Apr 24 01:50:24 2019 @@ -14,7 +14,7 @@ static union { int sg1, sg2; }; // expec namespace NS {} template<typename> int ta; -template<typename> static int sta; // expected-note {{target}} +template<typename> static int sta; template<typename> void tb(); template<typename> static void stb(); // expected-note {{target}} template<typename> struct tc {}; @@ -44,7 +44,7 @@ namespace UnnamedNS { } } -export { // expected-note 19{{here}} +export { // expected-note 18{{here}} using ::a; using ::sa; // expected-error {{using declaration referring to 'sa' with internal linkage}} using ::b; @@ -56,7 +56,7 @@ export { // expected-note 19{{here}} using ::sg1; // expected-error {{using declaration referring to 'sg1' with internal linkage}} using ::ta; - using ::sta; // expected-error {{using declaration referring to 'sta' with internal linkage}} + using ::sta; // FIXME {{using declaration referring to 'sta' with internal linkage}} using ::tb; using ::stb; // expected-error {{using declaration referring to 'stb' with internal linkage}} using ::tc; Modified: cfe/trunk/test/CodeGenCXX/cxx1y-variable-template-linkage.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx1y-variable-template-linkage.cpp?rev=359076&r1=359075&r2=359076&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/cxx1y-variable-template-linkage.cpp (original) +++ cfe/trunk/test/CodeGenCXX/cxx1y-variable-template-linkage.cpp Wed Apr 24 01:50:24 2019 @@ -6,61 +6,21 @@ // should be 'internal global' and not 'linkonce_odr global'. template <typename T> int x = 42; -// CHECK-DAG: @_Z1xIiE = linkonce_odr global -// CHECK-DAG: @_Z1xIZL3foovE3FooE = internal global - -// 'static' affects the linkage of the global -template <typename T> static int y = 42; -// CHECK-DAG: @_ZL1yIiE = internal global -// CHECK-DAG: @_ZL1yIZL3foovE3FooE = internal global - -// 'const' does not -template <typename T> const int z = 42; -// CHECK-DAG: @_Z1zIiE = linkonce_odr constant -// CHECK-DAG: @_Z1zIZL3foovE3FooE = internal constant - -template <typename T> T t = 42; -// CHECK-DAG: @_Z1tIiE = linkonce_odr global -// CHECK-DAG: @_Z1tIKiE = linkonce_odr constant -int mode; +// CHECK-DAG: @_Z1xIZL3foovE3FooE = internal global // CHECK-DAG: define internal dereferenceable(4) i32* @_ZL3foov( -static const int &foo() { +static int &foo() { struct Foo { }; - - switch (mode) { - case 0: - // CHECK-DAG: @_Z1xIiE - return x<int>; - case 1: - // CHECK-DAG: @_Z1xIZL3foovE3FooE - return x<Foo>; - case 2: - // CHECK-DAG: @_ZL1yIiE - return y<int>; - case 3: - // CHECK-DAG: @_ZL1yIZL3foovE3FooE - return y<Foo>; - case 4: - // CHECK-DAG: @_Z1zIiE - return z<int>; - case 5: - // CHECK-DAG: @_Z1zIZL3foovE3FooE - return z<Foo>; - case 6: - // CHECK-DAG: @_Z1tIiE - return t<int>; - case 7: - // CHECK-DAG: @_Z1tIKiE - return t<const int>; - } + + // CHECK-DAG: ret i32* @_Z1xIZL3foovE3FooE + return x<Foo>; } #if !__has_feature(cxx_exceptions) // File A // CHECKA-DAG: define dereferenceable(4) i32* @_Z3barv( -const int &bar() { +int &bar() { // CHECKA-DAG: call dereferenceable(4) i32* @_ZL3foov() return foo(); } @@ -68,7 +28,7 @@ const int &bar() { #else // File B // CHECKB-DAG: declare dereferenceable(4) i32* @_Z3barv( -const int &bar(); +int &bar(); int main() { // CHECKB-DAG: call dereferenceable(4) i32* @_Z3barv() Modified: cfe/trunk/test/SemaCXX/PR10177.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/PR10177.cpp?rev=359076&r1=359075&r2=359076&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/PR10177.cpp (original) +++ cfe/trunk/test/SemaCXX/PR10177.cpp Wed Apr 24 01:50:24 2019 @@ -57,10 +57,11 @@ namespace N { } #else +// expected-no-diagnostics namespace { template<typename> extern int n; } template<typename T> int g() { return n<int>; } -namespace { extern template int n<int>; } // expected-error {{explicit instantiation declaration of 'n<int>' with internal linkage}} +namespace { extern template int n<int>; } #endif Modified: cfe/trunk/test/SemaCXX/warn-unused-filescoped.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-unused-filescoped.cpp?rev=359076&r1=359075&r2=359076&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/warn-unused-filescoped.cpp (original) +++ cfe/trunk/test/SemaCXX/warn-unused-filescoped.cpp Wed Apr 24 01:50:24 2019 @@ -207,9 +207,8 @@ static void completeRedeclChainForTempla namespace test10 { #if __cplusplus >= 201103L -// FIXME: Warn on template definitions with no instantiations? template<class T> -constexpr T pi = T(3.14); +constexpr T pi = T(3.14); // expected-warning {{unused}} #endif } Modified: cfe/trunk/test/SemaCXX/warn-unused-variables.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-unused-variables.cpp?rev=359076&r1=359075&r2=359076&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/warn-unused-variables.cpp (original) +++ cfe/trunk/test/SemaCXX/warn-unused-variables.cpp Wed Apr 24 01:50:24 2019 @@ -135,9 +135,7 @@ namespace PR19305 { template<typename T> int m = 0; template<typename T> int m<T*> = 0; - // This has external linkage, so could be referenced by a declaration in a - // different translation unit. - template<> const int m<void> = 0; // no warning + template<> const int m<void> = 0; // expected-warning {{unused variable}} } namespace ctor_with_cleanups { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits