mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-22 08:32:23 +00:00
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()) llvm-svn: 359076
This commit is contained in:
parent
40f8f7f95c
commit
b8292c955c
@ -4384,8 +4384,6 @@ def err_explicit_instantiation_of_typedef : Error<
|
||||
"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">;
|
||||
|
@ -610,18 +610,6 @@ static LinkageInfo getExternalLinkageFor(const NamedDecl *D) {
|
||||
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::getLVForNamespaceScopeDecl(const NamedDecl *D,
|
||||
// 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::getLVForNamespaceScopeDecl(const NamedDecl *D,
|
||||
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::getLVForNamespaceScopeDecl(const NamedDecl *D,
|
||||
}
|
||||
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::getLVForNamespaceScopeDecl(const NamedDecl *D,
|
||||
|
||||
// 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::getLVForNamespaceScopeDecl(const NamedDecl *D,
|
||||
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::getLVForNamespaceScopeDecl(const NamedDecl *D,
|
||||
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::getLVForNamespaceScopeDecl(const NamedDecl *D,
|
||||
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)) {
|
||||
|
@ -8619,29 +8619,6 @@ 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())
|
||||
@ -8793,8 +8770,13 @@ DeclResult Sema::ActOnExplicitInstantiation(
|
||||
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 *S, SourceLocation ExternLoc,
|
||||
= 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::ActOnExplicitInstantiation(Scope *S,
|
||||
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::ActOnExplicitInstantiation(Scope *S,
|
||||
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;
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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; };
|
||||
|
@ -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
|
||||
}
|
@ -48,7 +48,7 @@ export namespace { int c; } // expected-error {{declaration of 'c' with internal
|
||||
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}}
|
||||
|
@ -14,7 +14,7 @@ static union { int sg1, sg2; }; // expected-note {{target}}
|
||||
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;
|
||||
|
@ -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: 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()
|
||||
|
@ -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
|
||||
|
||||
|
@ -207,9 +207,8 @@ static void completeRedeclChainForTemplateSpecialization() { } // expected-warni
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user