Hi rsmith,
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.
REPOSITORY
rL LLVM
http://reviews.llvm.org/D8283
Files:
llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
llvm/tools/clang/lib/Sema/SemaTemplate.cpp
llvm/tools/clang/test/SemaTemplate/ext_ms_template_spec.cpp
Index: llvm/tools/clang/test/SemaTemplate/ext_ms_template_spec.cpp
===================================================================
--- llvm/tools/clang/test/SemaTemplate/ext_ms_template_spec.cpp
+++ llvm/tools/clang/test/SemaTemplate/ext_ms_template_spec.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -fsyntax-only -fms-compatibility -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}}
+};
+
+}
+
+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}}
+
+}
+
Index: llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3445,6 +3445,12 @@
"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: llvm/tools/clang/lib/Sema/SemaTemplate.cpp
===================================================================
--- llvm/tools/clang/lib/Sema/SemaTemplate.cpp
+++ llvm/tools/clang/lib/Sema/SemaTemplate.cpp
@@ -5835,11 +5835,13 @@
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().MSVCCompat)
+ 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);
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
Index: llvm/tools/clang/test/SemaTemplate/ext_ms_template_spec.cpp
===================================================================
--- llvm/tools/clang/test/SemaTemplate/ext_ms_template_spec.cpp
+++ llvm/tools/clang/test/SemaTemplate/ext_ms_template_spec.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -fsyntax-only -fms-compatibility -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}}
+};
+
+}
+
+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}}
+
+}
+
Index: llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3445,6 +3445,12 @@
"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: llvm/tools/clang/lib/Sema/SemaTemplate.cpp
===================================================================
--- llvm/tools/clang/lib/Sema/SemaTemplate.cpp
+++ llvm/tools/clang/lib/Sema/SemaTemplate.cpp
@@ -5835,11 +5835,13 @@
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().MSVCCompat)
+ 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);
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits