aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td4
-rw-r--r--lib/Sema/SemaTemplate.cpp58
-rw-r--r--test/SemaCXX/cxx0x-compat.cpp13
-rw-r--r--test/SemaTemplate/temp_explicit.cpp6
-rw-r--r--test/SemaTemplate/temp_explicit_cxx0x.cpp2
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}}
}