This is tracked in: https://github.com/llvm/llvm-project/issues/61465
-Ambiguous deduction guide
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Currently, when we call deduction guides in global module fragment,
-we may get incorrect diagnosing message like: `ambiguous deduction`.
-
-So if we're using deduction guide from global module fragment, we probably need to write:
-
-.. code-block:: c++
-
- std::lock_guard<std::mutex> lk(mutex);
-
-instead of
-
-.. code-block:: c++
-
- std::lock_guard lk(mutex);
-
-This is tracked in: https://github.com/llvm/llvm-project/issues/56916
-
Ignored PreferredName Attribute
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// FIXME: Skip constructors for which deduction must necessarily fail (those
// for which some class template parameter without a default argument never
// appears in a deduced context).
+ llvm::SmallPtrSet<NamedDecl *, 8> ProcessedCtors;
bool AddedAny = false;
for (NamedDecl *D : LookupConstructors(Transform.Primary)) {
D = D->getUnderlyingDecl();
if (D->isInvalidDecl() || D->isImplicit())
continue;
+
D = cast<NamedDecl>(D->getCanonicalDecl());
+ // Within C++20 modules, we may have multiple same constructors in
+ // multiple same RecordDecls. And it doesn't make sense to create
+ // duplicated deduction guides for the duplicated constructors.
+ if (ProcessedCtors.count(D))
+ continue;
+
auto *FTD = dyn_cast<FunctionTemplateDecl>(D);
auto *CD =
dyn_cast_or_null<CXXConstructorDecl>(FTD ? FTD->getTemplatedDecl() : D);
}))
continue;
+ ProcessedCtors.insert(D);
Transform.transformConstructor(FTD, CD);
AddedAny = true;
}
--- /dev/null
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/M-A.pcm
+// RUN: %clang_cc1 -std=c++20 %t/B.cppm -emit-module-interface -o %t/M-B.pcm
+// RUN: %clang_cc1 -std=c++20 %t/M.cppm -emit-module-interface -o %t/M.pcm \
+// RUN: -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fmodule-file=M=%t/M.pcm -fsyntax-only \
+// RUN: -verify
+
+//--- foo.h
+template <typename T>
+class Templ {
+public:
+ Templ(T a) {}
+};
+
+//--- A.cppm
+module;
+#include "foo.h"
+export module M:A;
+export using ::Templ;
+
+//--- B.cppm
+module;
+#include "foo.h"
+export module M:B;
+
+//--- M.cppm
+export module M;
+export import :A;
+export import :B;
+
+//--- Use.cpp
+// expected-no-diagnostics
+import M;
+
+void func() {
+ Templ t(5);
+}
#define _FOO
template <typename T> struct Foo {
- Foo(T) {}
+ Foo(T f) {}
};
template <typename T> Foo(T&) -> Foo<T>;
void baz() const {}
};
+template <typename T> struct Foo2 {
+ Foo2(T f) {}
+};
+
+struct Bar2 {
+ template <typename T>
+ requires requires { Foo2{T()}; }
+ void baz2() const {}
+};
+
#endif
//--- A.cppm
export module A;
export using ::Foo;
export using ::Bar;
+export using ::Bar2;
//--- B.cppm
module;
void use() {
Bar _;
_.baz<int>();
+
+ Bar2 __;
+ __.baz2<int>();
}