diff options
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 4 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 58 | ||||
-rw-r--r-- | test/SemaCXX/cxx0x-compat.cpp | 13 | ||||
-rw-r--r-- | test/SemaTemplate/temp_explicit.cpp | 6 | ||||
-rw-r--r-- | test/SemaTemplate/temp_explicit_cxx0x.cpp | 2 |
5 files changed, 41 insertions, 42 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index f66019b76f..bc3740b49e 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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|" diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 8dda34c8ab..82a88312d7 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -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 diff --git a/test/SemaCXX/cxx0x-compat.cpp b/test/SemaCXX/cxx0x-compat.cpp index a01b26c5f9..4a7c1defee 100644 --- a/test/SemaCXX/cxx0x-compat.cpp +++ b/test/SemaCXX/cxx0x-compat.cpp @@ -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}} } diff --git a/test/SemaTemplate/temp_explicit.cpp b/test/SemaTemplate/temp_explicit.cpp index 76244c25e8..8a56d724ea 100644 --- a/test/SemaTemplate/temp_explicit.cpp +++ b/test/SemaTemplate/temp_explicit.cpp @@ -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}} } diff --git a/test/SemaTemplate/temp_explicit_cxx0x.cpp b/test/SemaTemplate/temp_explicit_cxx0x.cpp index 9d6dc80b5b..e37fcd7c6a 100644 --- a/test/SemaTemplate/temp_explicit_cxx0x.cpp +++ b/test/SemaTemplate/temp_explicit_cxx0x.cpp @@ -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}} } |