if (auto *DeductionGuide = ND->getDeclName().getCXXDeductionGuideTemplate())
return SemaRef.hasReachableDefinition(DeductionGuide);
+ // FIXME: The lookup for allocation function is a standalone process.
+ // (We can find the logics in Sema::FindAllocationFunctions)
+ //
+ // Such structure makes it a problem when we instantiate a template
+ // declaration using placement allocation function if the placement
+ // allocation function is invisible.
+ // (See https://github.com/llvm/llvm-project/issues/59601)
+ //
+ // Here we workaround it by making the placement allocation functions
+ // always acceptable. The downside is that we can't diagnose the direct
+ // use of the invisible placement allocation functions. (Although such uses
+ // should be rare).
+ if (auto *FD = dyn_cast<FunctionDecl>(ND);
+ FD && FD->isReservedGlobalPlacementOperator())
+ return true;
+
auto *DC = ND->getDeclContext();
// If ND is not visible and it is at namespace scope, it shouldn't be found
// by name lookup.
--- /dev/null
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
+
+//--- placement.h
+namespace std {
+ using size_t = decltype(sizeof(0));
+}
+void *operator new(std::size_t, void *p) { return p; }
+
+//--- A.cppm
+module;
+#include "placement.h"
+export module A;
+export template<class T>
+struct A {
+ A(void *p) : ptr(new (p) T(43)) {}
+private:
+ void *ptr;
+};
+
+export struct B {
+ B(void *p) : ptr(new (p) int(43)) {}
+private:
+ void *ptr;
+};
+
+//--- Use.cpp
+// expected-no-diagnostics
+import A;
+void bar(int *);
+void foo(void *ptr) {
+ A<int>(nullptr); // Good. It should be OK to construct A.
+ void *p = ::operator new(sizeof(int), ptr); // Bad. The function shouldn't be visible here.
+ void *q = new (ptr) int(43); // Good. We don't call the placement allocation function directly.
+}