diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index a06f409d78d97a..0fe00974008239 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -329,6 +329,8 @@ Bug Fixes - Fix sanity check when value initializing an empty union so that it takes into account anonymous structs which is a GNU extension. This fixes `Issue 58800 `_ +- Fix an issue that triggers a crash if we instantiate a hidden friend functions. + This fixes `Issue 54457 `_ Improvements to Clang's diagnostics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index a05eceac739885..a645ffe1cf2915 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -6155,9 +6155,8 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, // Move to the outer template scope. if (FunctionDecl *FD = dyn_cast(DC)) { - // FIXME: We should use `getNonTransparentDeclContext()` here instead - // of `getDeclContext()` once we find the invalid test case. - if (FD->getFriendObjectKind() && FD->getDeclContext()->isFileContext()){ + if (FD->getFriendObjectKind() && + FD->getNonTransparentDeclContext()->isFileContext()) { DC = FD->getLexicalDeclContext(); continue; } diff --git a/clang/test/Modules/pr54457.cppm b/clang/test/Modules/pr54457.cppm new file mode 100644 index 00000000000000..ed67ec1065376e --- /dev/null +++ b/clang/test/Modules/pr54457.cppm @@ -0,0 +1,61 @@ +// https://github.com/llvm/llvm-project/issues/54457 +// +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/A.cppm -verify -S -o - +// RUN: %clang_cc1 -std=c++20 %t/B.cppm -verify -S -o - +// RUN: %clang_cc1 -std=c++20 %t/C.cppm -emit-module-interface -o %t/C.pcm +// RUN: %clang_cc1 -std=c++20 %t/UseC.cppm -fprebuilt-module-path=%t -verify -S -o - + +//--- A.cppm +// expected-no-diagnostics +export module A; + +export template +struct s { + friend s f(s) { + return s(); + } +}; + +void g() { + f(s()); +} + +//--- B.cppm +// expected-no-diagnostics +export module B; + +export template +struct s { + friend constexpr auto f(s) -> s { + return s(); + } +}; + +void g() { + constexpr auto first = f(s()); +} + +//--- C.cppm +// expected-no-diagnostics +export module C; + +export template +struct basic_symbol_text { + template + constexpr friend basic_symbol_text operator+( + const basic_symbol_text&, const basic_symbol_text&) noexcept + { + return basic_symbol_text{}; + } +}; + +constexpr auto xxx = basic_symbol_text{} + basic_symbol_text{}; + +//--- UseC.cppm +// expected-no-diagnostics +import C; +void foo() {}