mirror of https://github.com/microsoft/clang.git
Refactor the checking for explicit template instantiations being performed in
the right namespace in C++11 mode. Teach the code to prefer the 'must be in precisely this namespace' diagnostic whenever that's true, and fix a defect which resulted in the -Wc++11-compat warning in C++98 mode sometimes being omitted. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142329 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d80d90d658
commit
3e2e91e934
|
@ -2434,9 +2434,9 @@ def ext_explicit_instantiation_without_qualified_id : Extension<
|
|||
"qualifier in explicit instantiation of %q0 requires a template-id "
|
||||
"(a typedef is not permitted)">;
|
||||
def err_explicit_instantiation_unqualified_wrong_namespace : Error<
|
||||
"explicit instantiation of %q0 must occur in %1">;
|
||||
"explicit instantiation of %q0 must occur in namespace %1">;
|
||||
def warn_explicit_instantiation_unqualified_wrong_namespace_0x : Warning<
|
||||
"explicit instantiation of %q0 must occur in %1">,
|
||||
"explicit instantiation of %q0 must occur in namespace %1">,
|
||||
InGroup<CXX11Compat>;
|
||||
def err_explicit_instantiation_undefined_member : Error<
|
||||
"explicit instantiation of undefined %select{member class|member function|"
|
||||
|
|
|
@ -5728,45 +5728,41 @@ static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
|
|||
return true;
|
||||
}
|
||||
|
||||
// C++0x [temp.explicit]p2:
|
||||
// C++11 [temp.explicit]p3:
|
||||
// An explicit instantiation shall appear in an enclosing namespace of its
|
||||
// template.
|
||||
// template. If the name declared in the explicit instantiation is an
|
||||
// unqualified name, the explicit instantiation shall appear in the
|
||||
// namespace where its template is declared or, if that namespace is inline
|
||||
// (7.3.1), any namespace from its enclosing namespace set.
|
||||
//
|
||||
// This is DR275, which we do not retroactively apply to C++98/03.
|
||||
if (S.getLangOptions().CPlusPlus0x &&
|
||||
!CurContext->Encloses(OrigContext)) {
|
||||
if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(OrigContext))
|
||||
if (WasQualifiedName) {
|
||||
if (CurContext->Encloses(OrigContext))
|
||||
return false;
|
||||
} else {
|
||||
if (CurContext->InEnclosingNamespaceSetOf(OrigContext))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(OrigContext)) {
|
||||
if (WasQualifiedName)
|
||||
S.Diag(InstLoc,
|
||||
S.getLangOptions().CPlusPlus0x?
|
||||
diag::err_explicit_instantiation_out_of_scope
|
||||
: diag::warn_explicit_instantiation_out_of_scope_0x)
|
||||
diag::err_explicit_instantiation_out_of_scope :
|
||||
diag::warn_explicit_instantiation_out_of_scope_0x)
|
||||
<< D << NS;
|
||||
else
|
||||
S.Diag(InstLoc,
|
||||
S.getLangOptions().CPlusPlus0x?
|
||||
diag::err_explicit_instantiation_must_be_global
|
||||
: diag::warn_explicit_instantiation_out_of_scope_0x)
|
||||
<< D;
|
||||
S.Diag(D->getLocation(), diag::note_explicit_instantiation_here);
|
||||
return false;
|
||||
}
|
||||
|
||||
// C++0x [temp.explicit]p2:
|
||||
// If the name declared in the explicit instantiation is an unqualified
|
||||
// name, the explicit instantiation shall appear in the namespace where
|
||||
// its template is declared or, if that namespace is inline (7.3.1), any
|
||||
// namespace from its enclosing namespace set.
|
||||
if (WasQualifiedName)
|
||||
return false;
|
||||
|
||||
if (CurContext->InEnclosingNamespaceSetOf(OrigContext))
|
||||
return false;
|
||||
|
||||
S.Diag(InstLoc,
|
||||
S.getLangOptions().CPlusPlus0x?
|
||||
diag::err_explicit_instantiation_unqualified_wrong_namespace
|
||||
: diag::warn_explicit_instantiation_unqualified_wrong_namespace_0x)
|
||||
<< D << OrigContext;
|
||||
diag::err_explicit_instantiation_unqualified_wrong_namespace :
|
||||
diag::warn_explicit_instantiation_unqualified_wrong_namespace_0x)
|
||||
<< D << NS;
|
||||
} else
|
||||
S.Diag(InstLoc,
|
||||
S.getLangOptions().CPlusPlus0x?
|
||||
diag::err_explicit_instantiation_must_be_global :
|
||||
diag::warn_explicit_instantiation_must_be_global_0x)
|
||||
<< D;
|
||||
S.Diag(D->getLocation(), diag::note_explicit_instantiation_here);
|
||||
return false;
|
||||
}
|
||||
|
@ -5776,7 +5772,7 @@ static bool ScopeSpecifierHasTemplateId(const CXXScopeSpec &SS) {
|
|||
if (!SS.isSet())
|
||||
return false;
|
||||
|
||||
// C++0x [temp.explicit]p2:
|
||||
// C++11 [temp.explicit]p3:
|
||||
// If the explicit instantiation is for a member function, a member class
|
||||
// or a static data member of a class template specialization, the name of
|
||||
// the class template specialization in the qualified-id for the member
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -std=c++98 -Wc++0x-compat -verify %s
|
||||
|
||||
namespace N {
|
||||
template<typename T> void f(T) {} // expected-note {{here}}
|
||||
template<typename T> void f(T) {} // expected-note 2{{here}}
|
||||
namespace M {
|
||||
template void f<int>(int); // expected-warning {{explicit instantiation of 'N::f' must occur in namespace 'N'}}
|
||||
template void ::N::f<int>(int); // expected-warning {{explicit instantiation of 'f' not in a namespace enclosing 'N'}}
|
||||
}
|
||||
}
|
||||
using namespace N;
|
||||
template void f<char>(char); // expected-warning {{explicit instantiation of 'N::f' must occur in namespace 'N'}}
|
||||
|
||||
template<typename T> void f(T) {} // expected-note {{here}}
|
||||
template<typename T> void g(T) {} // expected-note 2{{here}}
|
||||
namespace M {
|
||||
template void f<int>(int); // expected-warning {{explicit instantiation of 'f' must occur in the global namespace}}
|
||||
template void g<int>(int); // expected-warning {{explicit instantiation of 'g' must occur at global scope}}
|
||||
template void ::g<char>(char); // expected-warning {{explicit instantiation of 'g' must occur at global scope}}
|
||||
}
|
||||
|
||||
void f() {
|
||||
void g() {
|
||||
auto int n = 0; // expected-warning {{'auto' storage class specifier is redundant and incompatible with C++11}}
|
||||
}
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ struct X5 {
|
|||
void f(T&);
|
||||
};
|
||||
|
||||
struct Inner2 {
|
||||
struct Inner2 { // expected-note {{here}}
|
||||
struct VeryInner {
|
||||
void g(T*); // expected-error 2{{pointer to a reference}}
|
||||
};
|
||||
|
@ -98,7 +98,7 @@ void f4(X5<float&>::Inner2);
|
|||
template struct X5<float&>::Inner2; // expected-note{{instantiation}}
|
||||
|
||||
namespace N3 {
|
||||
template struct N2::X5<int>::Inner2;
|
||||
template struct N2::X5<int>::Inner2; // expected-warning {{explicit instantiation of 'Inner2' not in a namespace enclosing 'N2'}}
|
||||
}
|
||||
|
||||
struct X6 {
|
||||
|
@ -147,5 +147,5 @@ namespace N2 {
|
|||
|
||||
template struct X7<double>; // expected-warning{{must occur in namespace}}
|
||||
|
||||
template struct X9<float>; // expected-warning{{must occur in the global}}
|
||||
template struct X9<float>; // expected-warning{{must occur at global scope}}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ template struct ::N1::Inner::X1<float>;
|
|||
namespace N2 {
|
||||
using namespace N1;
|
||||
|
||||
template struct X0<double>; // expected-error{{not in a namespace enclosing}}
|
||||
template struct X0<double>; // expected-error{{must occur in namespace 'N1'}}
|
||||
|
||||
template struct X2<float>; // expected-error{{at global scope}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue