From ee1be282241b1253847e663af000f7082b7f03a3 Mon Sep 17 00:00:00 2001 From: Chuanqi Xu Date: Mon, 9 Jan 2023 10:39:35 +0800 Subject: [PATCH] [C++20] [Modules] Make placement allocation functions always visible Close https://github.com/llvm/llvm-project/issues/59601. This is actually a workaround for the issue. See the comments and the test for example. The proper fix should make the placement allocation functions acceptable based on the context. But it is harder and more complex on the one side. On the other side, such workaround won't be too bad in practice since users rarely call the placement allocation functions directly. So personally I prefer to address such problems in the simpler way. Reviewed By: royjacobson Differential Revision: https://reviews.llvm.org/D141023 --- clang/lib/Sema/SemaLookup.cpp | 16 ++++++++ .../test/Modules/placement-new-reachable.cpp | 39 +++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 clang/test/Modules/placement-new-reachable.cpp diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 97b3c97a9e51..4ec8a373ed47 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -2099,6 +2099,22 @@ bool LookupResult::isAvailableForLookup(Sema &SemaRef, NamedDecl *ND) { 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(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. diff --git a/clang/test/Modules/placement-new-reachable.cpp b/clang/test/Modules/placement-new-reachable.cpp new file mode 100644 index 000000000000..29263173d78f --- /dev/null +++ b/clang/test/Modules/placement-new-reachable.cpp @@ -0,0 +1,39 @@ +// 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 +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(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. +} -- 2.34.1