mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[PrintAsCxx] Fix printing of C++ enum args
Because imported enums are @objc, they were treated as unsupported in C++ and therefore ineligible to be printed in a C++ generated header. Narrow this logic so that only @objc *classes* are excluded, and update related printing logic to support enums correctly. Fixes rdar://124262637.
This commit is contained in:
@@ -102,18 +102,45 @@ struct CFunctionSignatureTypePrinterModifierDelegate {
|
||||
|
||||
class ClangTypeHandler {
|
||||
public:
|
||||
ClangTypeHandler(const clang::Decl *typeDecl) : typeDecl(typeDecl) {}
|
||||
ClangTypeHandler(const clang::Decl *typeDecl)
|
||||
: typeDecl(dyn_cast<clang::TagDecl>(typeDecl)) {}
|
||||
|
||||
bool isRepresentable() const {
|
||||
// We can only return trivial types, or
|
||||
// types that can be moved or copied.
|
||||
if (auto *record = dyn_cast<clang::CXXRecordDecl>(typeDecl)) {
|
||||
return record->isTrivial() || record->hasMoveConstructor() ||
|
||||
record->hasCopyConstructorWithConstParam();
|
||||
// We can only return tag types.
|
||||
if (typeDecl) {
|
||||
// We can return trivial types.
|
||||
if (isTrivial(typeDecl))
|
||||
return true;
|
||||
|
||||
// We can return nontrivial types iff they can be moved or copied.
|
||||
if (auto *record = dyn_cast<clang::CXXRecordDecl>(typeDecl)) {
|
||||
return record->hasMoveConstructor() ||
|
||||
record->hasCopyConstructorWithConstParam();
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, we can't return this type.
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Is the tag type trivial?
|
||||
static bool isTrivial(const clang::TagDecl *typeDecl) {
|
||||
if (!typeDecl)
|
||||
return false;
|
||||
|
||||
if (auto *record = dyn_cast<clang::CXXRecordDecl>(typeDecl))
|
||||
return record->isTrivial();
|
||||
|
||||
// FIXME: If we can get plain clang::RecordDecls here, we need to figure out
|
||||
// how nontrivial (i.e. ARC) fields work.
|
||||
assert(!isa<clang::RecordDecl>(typeDecl));
|
||||
|
||||
// C-family enums are always trivial.
|
||||
return isa<clang::EnumDecl>(typeDecl);
|
||||
}
|
||||
|
||||
public:
|
||||
void printTypeName(raw_ostream &os) const {
|
||||
ClangSyntaxPrinter(os).printClangTypeReference(typeDecl);
|
||||
}
|
||||
@@ -133,7 +160,7 @@ public:
|
||||
llvm::raw_string_ostream typeNameOS(fullQualifiedType);
|
||||
printTypeName(typeNameOS);
|
||||
llvm::raw_string_ostream unqualTypeNameOS(typeName);
|
||||
unqualTypeNameOS << cast<clang::NamedDecl>(typeDecl)->getName();
|
||||
unqualTypeNameOS << typeDecl->getName();
|
||||
}
|
||||
printReturnScaffold(typeDecl, os, fullQualifiedType, typeName,
|
||||
bodyOfReturn);
|
||||
@@ -141,7 +168,7 @@ public:
|
||||
|
||||
private:
|
||||
static void
|
||||
printReturnScaffold(const clang::Decl *typeDecl, raw_ostream &os,
|
||||
printReturnScaffold(const clang::TagDecl *typeDecl, raw_ostream &os,
|
||||
StringRef fullQualifiedType, StringRef typeName,
|
||||
llvm::function_ref<void(StringRef)> bodyOfReturn) {
|
||||
os << "alignas(alignof(" << fullQualifiedType << ")) char storage[sizeof("
|
||||
@@ -150,7 +177,7 @@ private:
|
||||
<< fullQualifiedType << " *>(storage);\n";
|
||||
bodyOfReturn("storage");
|
||||
os << ";\n";
|
||||
if (typeDecl && cast<clang::CXXRecordDecl>(typeDecl)->isTrivial()) {
|
||||
if (isTrivial(typeDecl)) {
|
||||
// Trivial object can be just copied and not destroyed.
|
||||
os << "return *storageObjectPtr;\n";
|
||||
return;
|
||||
@@ -162,7 +189,7 @@ private:
|
||||
os << "return result;\n";
|
||||
}
|
||||
|
||||
const clang::Decl *typeDecl;
|
||||
const clang::TagDecl *typeDecl;
|
||||
};
|
||||
|
||||
// Prints types in the C function signature that corresponds to the
|
||||
@@ -371,6 +398,7 @@ public:
|
||||
return ClangRepresentation::unsupported;
|
||||
|
||||
if (decl->hasClangNode()) {
|
||||
assert(genericArgs.empty() && "this path doesn't support generic args");
|
||||
ClangTypeHandler handler(decl->getClangDecl());
|
||||
if (!handler.isRepresentable())
|
||||
return ClangRepresentation::unsupported;
|
||||
|
||||
Reference in New Issue
Block a user