summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td6
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp12
-rw-r--r--clang/test/SemaTemplate/ext_ms_template_spec.cpp33
3 files changed, 46 insertions, 5 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index a3ab5dff8c8..b9737f23c00 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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 "
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 6cba79a5fbb..fad15bbc4f6 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -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/clang/test/SemaTemplate/ext_ms_template_spec.cpp b/clang/test/SemaTemplate/ext_ms_template_spec.cpp
new file mode 100644
index 00000000000..fc2ed16f9f8
--- /dev/null
+++ b/clang/test/SemaTemplate/ext_ms_template_spec.cpp
@@ -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}}
+
+}
+
OpenPOWER on IntegriCloud