forked from OSchip/llvm-project
[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:
parent
7ca9e471fe
commit
a2772fc806
|
@ -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
|
||||
---------------
|
||||
|
||||
|
|
|
@ -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.
|
||||
}];
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
Loading…
Reference in New Issue