From d7eff68dbbbc6b3f8dfd44f6a833c2b320a96e9a Mon Sep 17 00:00:00 2001 From: John McCall Date: Wed, 2 Sep 2009 00:55:30 +0000 Subject: [PATCH] Ensure that the tag decls of friend decls aren't added to the friending class's decl list, and remove some workarounds that were due to this. Thanks to Eli for pointing this out and providing the test case. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80745 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/DeclBase.cpp | 5 ----- lib/AST/DeclPrinter.cpp | 4 +--- lib/Sema/SemaDecl.cpp | 10 +++++++++- test/CXX/class/class.friend/p1.cpp | 2 -- test/SemaCXX/friend-class-nodecl.cpp | 10 ++++++++++ 5 files changed, 20 insertions(+), 11 deletions(-) create mode 100644 test/SemaCXX/friend-class-nodecl.cpp diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index c24dac9104..acdbdbe422 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -385,11 +385,6 @@ void Decl::CheckAccessDeclContext() const { !isa(getDeclContext())) return; - // FIXME: This check should not be necessary - If a friend decl refers to an - // undeclared decl, then that decl shouldn't be in any decl context. - if (getFriendObjectKind() == FOK_Undeclared) - return; - assert(Access != AS_none && "Access specifier is AS_none inside a record decl"); } diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 275f2db82b..275fa69723 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -203,9 +203,7 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { if (PrintAccess) { AccessSpecifier AS = D->getAccess(); - if (AS != CurAS && - // FIXME: This check shouldn't be necessary. - D->getFriendObjectKind() == Decl::FOK_Undeclared) { + if (AS != CurAS) { Print(AS); Out << ":\n"; CurAS = AS; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 8eb2c717b4..86222ffe14 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -4328,7 +4328,15 @@ CreateNewDecl: New->startDefinition(); // If this has an identifier, add it to the scope stack. - if (Name && TUK != TUK_Friend) { + if (TUK == TUK_Friend) { + // Friend tag decls are visible in fairly strange ways. + if (!CurContext->isDependentContext()) { + DeclContext *DC = New->getDeclContext()->getLookupContext(); + DC->makeDeclVisibleInContext(New, /* Recoverable = */ false); + if (Scope *EnclosingScope = getScopeForDeclContext(S, DC)) + PushOnScopeChains(New, EnclosingScope, /* AddToContext = */ false); + } + } else if (Name) { S = getNonFieldDeclScope(S); PushOnScopeChains(New, S); } else { diff --git a/test/CXX/class/class.friend/p1.cpp b/test/CXX/class/class.friend/p1.cpp index 5a9114006f..9ba02727a0 100644 --- a/test/CXX/class/class.friend/p1.cpp +++ b/test/CXX/class/class.friend/p1.cpp @@ -63,8 +63,6 @@ class A { friend ftypedef typedeffed_function; // okay (because it's not declared as a member) }; -class UndeclaredSoFar { }; - A::UndeclaredSoFar y; // expected-error {{ unknown type name 'UndeclaredSoFar' }} class PreDeclared; diff --git a/test/SemaCXX/friend-class-nodecl.cpp b/test/SemaCXX/friend-class-nodecl.cpp new file mode 100644 index 0000000000..de12eaf741 --- /dev/null +++ b/test/SemaCXX/friend-class-nodecl.cpp @@ -0,0 +1,10 @@ +// RUN: clang-cc -ast-print %s -o %t && +// RUN: not grep '^ *class B' %t + +// Tests that the tag decls in friend declarations aren't added to the +// declaring class's decl chain. + +class A { + friend class B; +}; + -- 2.50.1