[C++20] [Modules] Disable preferred_name when writing a C++20 Module interface

Currently, the use of preferred_name would block implementing std
modules in libcxx. See https://github.com/llvm/llvm-project/issues/56490
for example.
The problem is pretty hard and it looks like we couldn't solve it in a
short time. So we sent this patch as a workaround to avoid blocking us
to modularize STL. This is intended to be fixed properly in the future.

Reviewed By: erichkeane, aaron.ballman, tahonermann

Differential Revision: https://reviews.llvm.org/D130331
This commit is contained in:
Chuanqi Xu 2022-07-22 13:20:22 +08:00
parent 7ca9e471fe
commit a2772fc806
6 changed files with 72 additions and 2 deletions

View File

@ -435,6 +435,11 @@ Attribute Changes in Clang
``__attribute__((function_return("keep")))`` was added. This is intended to
be used by the Linux kernel to mitigate RETBLEED.
- Ignore the `__preferred_name__` attribute when writing for C++20 module interfaces.
This is a short-term workaround intentionally since clang doesn't take care of the
serialization and deserialization of `__preferred_name__`. See
https://github.com/llvm/llvm-project/issues/56490 for example.
Windows Support
---------------

View File

@ -5040,6 +5040,12 @@ general this requires the template to be declared at least twice. For example:
clang::preferred_name(wstring)]] basic_string {
// ...
};
Note that the ``preferred_name`` attribute will be ignored when the compiler
writes a C++20 Module interface now. This is due to a compiler issue
(https://github.com/llvm/llvm-project/issues/56490) that blocks users to modularize
declarations with `preferred_name`. This is intended to be fixed in the future.
}];
}

View File

@ -703,6 +703,10 @@ public:
bool hasChain() const { return Chain; }
ASTReader *getChain() const { return Chain; }
bool isWritingNamedModules() const {
return WritingModule && WritingModule->isModulePurview();
}
private:
// ASTDeserializationListener implementation
void ReaderInitialized(ASTReader *Reader) override;

View File

@ -2926,7 +2926,8 @@ Attr *ASTRecordReader::readAttr() {
/// Reads attributes from the current stream position.
void ASTRecordReader::readAttributes(AttrVec &Attrs) {
for (unsigned I = 0, E = readInt(); I != E; ++I)
Attrs.push_back(readAttr());
if (auto *A = readAttr())
Attrs.push_back(A);
}
//===----------------------------------------------------------------------===//

View File

@ -4347,8 +4347,12 @@ void ASTWriter::WriteModuleFileExtension(Sema &SemaRef,
void ASTRecordWriter::AddAttr(const Attr *A) {
auto &Record = *this;
if (!A)
// FIXME: Clang can't handle the serialization/deserialization of
// preferred_name properly now. See
// https://github.com/llvm/llvm-project/issues/56490 for example.
if (!A || (isa<PreferredNameAttr>(A) && Writer->isWritingNamedModules()))
return Record.push_back(0);
Record.push_back(A->getKind() + 1); // FIXME: stable encoding, target attrs
Record.AddIdentifierRef(A->getAttrName());

View File

@ -0,0 +1,50 @@
// Tests that the ODR check wouldn't produce false-positive result for preferred_name attribute.
//
// 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 -fprebuilt-module-path=%t -I%t %t/Use.cppm -verify -fsyntax-only
// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use1.cpp -verify -fsyntax-only
// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use2.cpp -verify -fsyntax-only
//
//--- foo.h
template<class _CharT>
class foo_templ;
typedef foo_templ<char> foo;
template<class _CharT>
class
__attribute__((__preferred_name__(foo)))
foo_templ {
public:
foo_templ() {}
};
inline foo_templ<char> bar()
{
return foo_templ<char>();
}
//--- A.cppm
module;
#include "foo.h"
export module A;
//--- Use.cppm
// expected-no-diagnostics
module;
#include "foo.h"
export module Use;
import A;
//--- Use1.cpp
import A; // expected-warning@foo.h:8 {{attribute declaration must precede definition}}
#include "foo.h" // expected-note@foo.h:9 {{previous definition is here}}
//--- Use2.cpp
// expected-no-diagnostics
#include "foo.h"
import A;