]> granicus.if.org Git - clang/commitdiff
Refactor the checking for explicit template instantiations being performed in
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 18 Oct 2011 02:28:33 +0000 (02:28 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 18 Oct 2011 02:28:33 +0000 (02:28 +0000)
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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaTemplate.cpp
test/SemaCXX/cxx0x-compat.cpp
test/SemaTemplate/temp_explicit.cpp
test/SemaTemplate/temp_explicit_cxx0x.cpp

index f66019b76f8327a2cb7aae3bdaf78078d55d3ad1..bc3740b49e183990dc45b7ca26490dd612c45ee2 100644 (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|"
index 8dda34c8ab5d5832cfd73427276ce365244c42a4..82a88312d7b7c99a1303529592376efcbd4811c8 100644 (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
index a01b26c5f91b47238d0c8ee96f9d5140b19b940b..4a7c1defee0f4781a25ea9e1d8f8f4e476896b98 100644 (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}}
 }
 
index 76244c25e8245bd8a5f9aef1deaa75ad971181db..8a56d724ea1fa1c2f84ddf290cf022352fa9bbe8 100644 (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}}
 }
index 9d6dc80b5b0a4a1b8b344f652326cddcbf2a9026..e37fcd7c6a5dff5b0bf4af377e773a664c0e55d0 100644 (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}}
 }