]> granicus.if.org Git - clang/commitdiff
[MSVC] Explicit specializations can be declared in any namespace (fix for http:/...
authorAlexey Bataev <a.bataev@hotmail.com>
Fri, 20 Mar 2015 07:21:46 +0000 (07:21 +0000)
committerAlexey Bataev <a.bataev@hotmail.com>
Fri, 20 Mar 2015 07:21:46 +0000 (07:21 +0000)
MS compiler emits no errors in case of explicit specializations outside declaration enclosing namespaces, even when language extensions are disabled.
The patch is to suppress errors and emit extension warnings if explicit specializations are not declared in the corresponding namespaces.
This fixes PR13738.

Patch by Alexey Frolov.

Differential Revision: http://reviews.llvm.org/D8283

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@232800 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaTemplate.cpp
test/SemaTemplate/ext_ms_template_spec.cpp [new file with mode: 0644]

index a3ab5dff8c87a24c6fba9c08226f4617c20915d7..b9737f23c00afe33f4561330e3df8449f0e21415 100644 (file)
@@ -3443,6 +3443,12 @@ def err_template_spec_redecl_out_of_scope : Error<
   "variable template partial|function template|member "
   "function|static data member|member class|member enumeration}0 "
   "specialization of %1 not in a namespace enclosing %2">;
+def ext_ms_template_spec_redecl_out_of_scope: ExtWarn<
+  "%select{class template|class template partial|variable template|"
+  "variable template partial|function template|member "
+  "function|static data member|member class|member enumeration}0 "
+  "specialization of %1 outside namespace enclosing %2 "
+  "is a Microsoft extension">, InGroup<Microsoft>;
 def err_template_spec_redecl_global_scope : Error<
   "%select{class template|class template partial|variable template|"
   "variable template partial|function template|member "
index 6cba79a5fbba75b561245e9bda7f1de1798aa12c..fad15bbc4f661b7fabd8bf356b1662115460f50a 100644 (file)
@@ -5835,11 +5835,13 @@ static bool CheckTemplateSpecializationScope(Sema &S,
     if (isa<TranslationUnitDecl>(SpecializedContext))
       S.Diag(Loc, diag::err_template_spec_redecl_global_scope)
         << EntityKind << Specialized;
-    else if (isa<NamespaceDecl>(SpecializedContext))
-      S.Diag(Loc, diag::err_template_spec_redecl_out_of_scope)
-        << EntityKind << Specialized
-        << cast<NamedDecl>(SpecializedContext);
-    else
+    else if (isa<NamespaceDecl>(SpecializedContext)) {
+      int Diag = diag::err_template_spec_redecl_out_of_scope;
+      if (S.getLangOpts().MicrosoftExt)
+        Diag = diag::ext_ms_template_spec_redecl_out_of_scope;
+      S.Diag(Loc, Diag) << EntityKind << Specialized
+                        << cast<NamedDecl>(SpecializedContext);
+    } else
       llvm_unreachable("unexpected namespace context for specialization");
 
     S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
diff --git a/test/SemaTemplate/ext_ms_template_spec.cpp b/test/SemaTemplate/ext_ms_template_spec.cpp
new file mode 100644 (file)
index 0000000..fc2ed16
--- /dev/null
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -fsyntax-only -fms-extensions -std=c++11 -verify %s
+
+namespace A {
+
+template <class T>
+class ClassTemplate; // expected-note {{explicitly specialized declaration is here}}
+
+template <class T1, class T2>
+class ClassTemplatePartial; // expected-note {{explicitly specialized declaration is here}}
+
+template <typename T> struct X {
+  struct MemberClass; // expected-note {{explicitly specialized declaration is here}}
+  enum MemberEnumeration; // expected-note {{explicitly specialized declaration is here}} // expected-error {{ISO C++ forbids forward references to 'enum' types}}
+};
+
+}
+
+namespace B {
+
+template <>
+class A::ClassTemplate<int>; // expected-warning {{class template specialization of 'ClassTemplate' outside namespace enclosing 'A' is a Microsoft extension}}
+
+template <class T1>
+class A::ClassTemplatePartial<T1, T1 *> {}; // expected-warning {{class template partial specialization of 'ClassTemplatePartial' outside namespace enclosing 'A' is a Microsoft extension}}
+
+template <>
+struct A::X<int>::MemberClass; // expected-warning {{member class specialization of 'MemberClass' outside namespace enclosing 'A' is a Microsoft extension}}
+
+template <>
+enum A::X<int>::MemberEnumeration; // expected-warning {{member enumeration specialization of 'MemberEnumeration' outside namespace enclosing 'A' is a Microsoft extension}} // expected-error {{ISO C++ forbids forward references to 'enum' types}}
+
+}
+