diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 6f582f584bdf6..d6b498ced6ca2 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -539,6 +539,9 @@ Bug Fixes to C++ Support - Allow omitting ``typename`` in the parameter declaration of a friend constructor declaration. (`#63119 `_) +- Fix access of a friend class declared in a local class. Clang previously + emitted an error when a friend of a local class tried to access it's + private data members. Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 12fd378fb170c..992d497ca915a 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -17066,11 +17066,14 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, S = getTagInjectionScope(S, getLangOpts()); } else { assert(TUK == TUK_Friend); + CXXRecordDecl *RD = dyn_cast(SearchDC); + // C++ [namespace.memdef]p3: // If a friend declaration in a non-local class first declares a // class or function, the friend class or function is a member of // the innermost enclosing namespace. - SearchDC = SearchDC->getEnclosingNamespaceContext(); + SearchDC = RD->isLocalClass() ? RD->isLocalClass() + : SearchDC->getEnclosingNamespaceContext(); } // In C++, we need to do a redeclaration lookup to properly diff --git a/clang/test/Sema/local-class-friend.cpp b/clang/test/Sema/local-class-friend.cpp new file mode 100644 index 0000000000000..6f9af7132c2a1 --- /dev/null +++ b/clang/test/Sema/local-class-friend.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -verify -fsyntax-only %s +// expected-no-diagnostics + +void foo() +{ class c1 { + private: + int testVar; + public: + friend class c2; + }; + + class c2 { + void f(c1 obj) { + int a = obj.testVar; // Ok + } + }; +}