diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 5a3f6328cac9..f5b642191c6b 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -7016,8 +7016,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // for the consumer of this Decl to know it doesn't own it. // For our current ASTs this shouldn't be a problem, but will // need to be changed with DeclGroups. - if ((TUK == TUK_Reference && !PrevTagDecl->getFriendObjectKind()) || - TUK == TUK_Friend) + if ((TUK == TUK_Reference && (!PrevTagDecl->getFriendObjectKind() || + getLangOptions().Microsoft)) || TUK == TUK_Friend) return PrevTagDecl; // Diagnose attempts to redefine a tag. @@ -7259,8 +7259,12 @@ CreateNewDecl: New->setLexicalDeclContext(CurContext); // Mark this as a friend decl if applicable. + // In Microsoft mode, a friend declaration also acts as a forward + // declaration so we always pass true to setObjectOfFriendDecl to make + // the tag name visible. if (TUK == TUK_Friend) - New->setObjectOfFriendDecl(/* PreviouslyDeclared = */ !Previous.empty()); + New->setObjectOfFriendDecl(/* PreviouslyDeclared = */ !Previous.empty() || + getLangOptions().Microsoft); // Set the access specifier. if (!Invalid && SearchDC->isRecord()) diff --git a/clang/test/SemaCXX/MicrosoftExtensions.cpp b/clang/test/SemaCXX/MicrosoftExtensions.cpp index 22a06673b951..9b03feb53909 100644 --- a/clang/test/SemaCXX/MicrosoftExtensions.cpp +++ b/clang/test/SemaCXX/MicrosoftExtensions.cpp @@ -226,4 +226,29 @@ private: using B::f; // expected-warning {{using declaration refers to inaccessible member 'ms_using_declaration_bug::B::f', which refers to accessible member 'ms_using_declaration_bug::A::f', accepted for Microsoft compatibility}} }; -} \ No newline at end of file +} + + + +namespace friend_as_a_forward_decl { + +class A { + class Nested { + friend class B; + B* b; + }; + B* b; +}; +B* global_b; + + +void f() +{ + class Local { + friend class Z; + Z* b; + }; + Z* b; +} + + } \ No newline at end of file