diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 47c7a61f8072f..aa87a33ce8ae1 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -2087,6 +2087,13 @@ bool LookupResult::isAvailableForLookup(Sema &SemaRef, NamedDecl *ND) { if (isVisible(SemaRef, ND)) return true; + // Deduction guide lives in namespace scope generally, but it is just a + // hint to the compilers. What we actually lookup for is the generated member + // of the corresponding template. So it is sufficient to check the + // reachability of the template decl. + if (auto *DeductionGuide = ND->getDeclName().getCXXDeductionGuideTemplate()) + return SemaRef.hasReachableDefinition(DeductionGuide); + auto *DC = ND->getDeclContext(); // If ND is not visible and it is at namespace scope, it shouldn't be found // by name lookup. diff --git a/clang/test/Modules/deduction-guide.cppm b/clang/test/Modules/deduction-guide.cppm new file mode 100644 index 0000000000000..9c959a71365da --- /dev/null +++ b/clang/test/Modules/deduction-guide.cppm @@ -0,0 +1,30 @@ +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-module-interface -o %t/Templ.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only + +//--- foo.h +template +class Templ { +public: + Templ(T a) {} +}; + +template +Templ(T t) -> Templ; + +//--- Templ.cppm +module; +#include "foo.h" +export module Templ; +export using ::Templ; + +//--- Use.cpp +// expected-no-diagnostics +import Templ; +void func() { + Templ t(5); +} + diff --git a/clang/test/Modules/deduction-guide2.cppm b/clang/test/Modules/deduction-guide2.cppm new file mode 100644 index 0000000000000..a163c36568310 --- /dev/null +++ b/clang/test/Modules/deduction-guide2.cppm @@ -0,0 +1,25 @@ +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-module-interface -o %t/Templ.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only + +//--- Templ.cppm +export module Templ; +export template +class Templ { +public: + Templ(T a) {} +}; + +template +Templ(T t) -> Templ; + +//--- Use.cpp +// expected-no-diagnostics +import Templ; +void func() { + Templ t(5); +} + diff --git a/clang/test/Modules/deduction-guide3.cppm b/clang/test/Modules/deduction-guide3.cppm new file mode 100644 index 0000000000000..8fa08a0625d7c --- /dev/null +++ b/clang/test/Modules/deduction-guide3.cppm @@ -0,0 +1,26 @@ +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-module-interface -o %t/Templ.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only + +//--- Templ.cppm +export module Templ; +template +class Templ { +public: + Templ(T a) {} +}; + +template +Templ(T t) -> Templ; + +//--- Use.cpp +import Templ; +void func() { + Templ t(5); // expected-error {{declaration of 'Templ' must be imported from module 'Templ' before it is required}} + // expected-error@-1 {{unknown type name 'Templ'}} + // expected-note@Templ.cppm:3 {{declaration here is not visible}} +} +