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:
Richard Smith 2011-10-18 02:28:33 +00:00
parent d80d90d658
commit 3e2e91e934
5 changed files with 41 additions and 42 deletions

View File

@ -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|"

View File

@ -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

View File

@ -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}}
}

View File

@ -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}}
}

View File

@ -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}}
}