Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -4724,6 +4724,9 @@ def err_standalone_class_nested_name_specifier : Error< "forward declaration of %select{class|struct|interface|union|enum}0 cannot " "have a nested name specifier">; +def ext_standalone_class_nested_name_specifier : ExtWarn< + "forward declaration of %select{class|struct|interface|union|enum}0 with a " + "nested name specifier is a Microsoft extension">, InGroup; def err_typecheck_sclass_func : Error<"illegal storage class on function">; def err_static_block_func : Error< "function declared in block scope cannot have 'static' storage class">; Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -3286,7 +3286,10 @@ // nested-name-specifier unless it is an explicit instantiation // or an explicit specialization. // Per C++ [dcl.enum]p1, an opaque-enum-declaration can't either. - Diag(SS.getBeginLoc(), diag::err_standalone_class_nested_name_specifier) + Diag(SS.getBeginLoc(), + getLangOpts().MicrosoftExt ? + diag::ext_standalone_class_nested_name_specifier : + diag::err_standalone_class_nested_name_specifier) << (DS.getTypeSpecType() == DeclSpec::TST_class ? 0 : DS.getTypeSpecType() == DeclSpec::TST_struct ? 1 : DS.getTypeSpecType() == DeclSpec::TST_interface ? 2 : Index: test/SemaCXX/MicrosoftExtensions.cpp =================================================================== --- test/SemaCXX/MicrosoftExtensions.cpp +++ test/SemaCXX/MicrosoftExtensions.cpp @@ -418,3 +418,19 @@ _Static_assert(__alignof(s1) == 8, ""); _Static_assert(__alignof(s2) == 4, ""); } + +namespace forward_decl_nested_name_NS { + struct X; + template struct Y; +} + +struct forward_decl_nested_name_NS::X; // expected-warning {{forward declaration of struct with a nested name specifier is a Microsoft extension}} +template struct forward_decl_nested_name_NS::Y; // expected-warning {{forward declaration of struct with a nested name specifier is a Microsoft extension}} + +struct forward_decl_nested_name_struct { + struct A; + union B; +}; + +struct forward_decl_nested_name_struct::A; // expected-warning {{forward declaration of struct with a nested name specifier is a Microsoft extension}} +union forward_decl_nested_name_struct::B; // expected-warning {{forward declaration of union with a nested name specifier is a Microsoft extension}}