From d943352fabd065ce2eaa21f4a550ed2ffa5353ab Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 27 Jun 2013 20:42:30 +0000 Subject: [PATCH] Under -fms-extensions, only inject a friend tag name when we didn't see a tag with that name in an enclosing scope. r177473 made us correctly consider only those declarations in the enclosing namespace scope when looking for a friend declaration. Under ms-extensions mode, where we do some level of friend injection, this meant that we were introducing a new tag type into a different scope than what Microsoft actually does. Address this by only doing the friend injection when we didn't see any tag with that name in any outer scope. Fixes . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@185100 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDecl.cpp | 10 +++++++--- test/SemaCXX/MicrosoftExtensions.cpp | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 08e8cb798a..a87cf61ccf 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -9614,7 +9614,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, Redecl = NotForRedeclaration; LookupResult Previous(*this, Name, NameLoc, LookupTagName, Redecl); - + bool FriendSawTagOutsideEnclosingNamespace = false; if (Name && SS.isNotEmpty()) { // We have a nested-name tag ('struct foo::bar'). @@ -9707,8 +9707,11 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, while (F.hasNext()) { NamedDecl *ND = F.next(); DeclContext *DC = ND->getDeclContext()->getRedeclContext(); - if (DC->isFileContext() && !EnclosingNS->Encloses(ND->getDeclContext())) + if (DC->isFileContext() && + !EnclosingNS->Encloses(ND->getDeclContext())) { F.erase(); + FriendSawTagOutsideEnclosingNamespace = true; + } } F.done(); } @@ -10208,7 +10211,8 @@ CreateNewDecl: // the tag name visible. if (TUK == TUK_Friend) New->setObjectOfFriendDecl(/* PreviouslyDeclared = */ !Previous.empty() || - getLangOpts().MicrosoftExt); + (!FriendSawTagOutsideEnclosingNamespace && + getLangOpts().MicrosoftExt)); // Set the access specifier. if (!Invalid && SearchDC->isRecord()) diff --git a/test/SemaCXX/MicrosoftExtensions.cpp b/test/SemaCXX/MicrosoftExtensions.cpp index e82c47eb58..723beb4efc 100644 --- a/test/SemaCXX/MicrosoftExtensions.cpp +++ b/test/SemaCXX/MicrosoftExtensions.cpp @@ -365,3 +365,23 @@ void SP11::UseV() { struct StructWithUnnamedMember { __declspec(property(get=GetV)) int : 10; // expected-error {{anonymous property is not supported}} }; + +namespace rdar14250378 { + class Bar {}; + + namespace NyNamespace { + class Foo { + public: + Bar* EnsureBar(); + }; + + class Baz : public Foo { + public: + friend class Bar; + }; + + Bar* Foo::EnsureBar() { + return 0; + } + } +} -- 2.40.0