[ClangImporter] Add check for Bool in importNumericLiteral

I somehow missed this in my original patch, make sure we also handle
the bool case here.

rdar://164916048
This commit is contained in:
Hamish Knight
2025-11-24 12:02:31 +00:00
parent d1227fb693
commit 7bca421d51
5 changed files with 67 additions and 14 deletions

View File

@@ -440,6 +440,22 @@ bool importer::isForwardDeclOfType(const clang::Decl *D) {
return false;
}
bool importer::isBoolOrBoolEnumType(Type ty) {
if (ty->isBool())
return true;
// Check if this is a C++ enum with an underlying type of "bool".
if (auto *SD = ty->getStructOrBoundGenericStruct()) {
if (auto *clangD = SD->getClangDecl()) {
if (auto *ED = dyn_cast<clang::EnumDecl>(clangD)) {
if (ED->getIntegerType()->isBooleanType())
return true;
}
}
}
return false;
}
bool ClangImporter::Implementation::shouldIgnoreBridgeHeaderTopLevelDecl(
clang::Decl *D) {
return importer::isForwardDeclOfType(D);

View File

@@ -146,15 +146,16 @@ static ValueDecl *importNumericLiteral(ClangImporter::Implementation &Impl,
}
// Make sure the destination type actually conforms to the builtin literal
// protocol before attempting to import, otherwise we'll crash since
// `createConstant` expects it to.
// protocol or is Bool before attempting to import, otherwise we'll crash
// since `createConstant` expects it to.
// FIXME: We ought to be careful checking conformance here since it can
// result in cycles. Additionally we ought to consider checking for the
// non-builtin literal protocol to allow any ExpressibleByIntegerLiteral
// type to be supported.
if (!ctx.getIntBuiltinInitDecl(constantTyNominal))
if (!isBoolOrBoolEnumType(constantType) &&
!ctx.getIntBuiltinInitDecl(constantTyNominal)) {
return nullptr;
}
return createMacroConstant(Impl, MI, name, DC, constantType,
clang::APValue(value),
ConstantConvertKind::None,

View File

@@ -1985,6 +1985,10 @@ bool recordHasReferenceSemantics(const clang::RecordDecl *decl,
/// declarations in certain cases, and instead process the real declarations.
bool isForwardDeclOfType(const clang::Decl *decl);
/// Checks whether this type is bool or is a C++ enum with a bool underlying
/// type.
bool isBoolOrBoolEnumType(Type ty);
/// Whether we should suppress the import of the given Clang declaration.
bool shouldSuppressDeclImport(const clang::Decl *decl);

View File

@@ -276,16 +276,9 @@ ValueDecl *SwiftDeclSynthesizer::createConstant(Identifier name,
// Create the expression node.
StringRef printedValueCopy(context.AllocateCopy(printedValue));
if (value.getKind() == clang::APValue::Int) {
bool isBool = type->getCanonicalType()->isBool();
// Check if "type" is a C++ enum with an underlying type of "bool".
if (!isBool && type->getStructOrBoundGenericStruct() &&
type->getStructOrBoundGenericStruct()->getClangDecl()) {
if (auto enumDecl = dyn_cast<clang::EnumDecl>(
type->getStructOrBoundGenericStruct()->getClangDecl())) {
isBool = enumDecl->getIntegerType()->isBooleanType();
}
}
if (isBool) {
// Check if "type" is Bool or a C++ enum with an underlying type of Bool.
// NOTE: This must match the condition in `importNumericLiteral`.
if (isBoolOrBoolEnumType(type)) {
auto *boolExpr = new (context)
BooleanLiteralExpr(value.getInt().getBoolValue(), SourceLoc(),
/*Implicit=*/true);

View File

@@ -0,0 +1,39 @@
// RUN: %empty-directory(%t)
// RUN: split-file %s %t
// RUN: %target-swift-frontend -emit-sil %t/valid.swift -I %t
// RUN: %target-swift-frontend -typecheck -verify %t/invalid.swift -I %t -disable-typo-correction
// REQUIRES: objc_interop
// REQUIRES: OS=macosx
//--- cmodule.h
#include <stdbool.h>
typedef _Bool UnderscoreBoolAlias;
#define usesUnderscoreBoolAlias ((UnderscoreBoolAlias)0)
#define usesUnderscoreBool ((_Bool)0)
typedef bool BoolAlias;
#define usesBoolAlias ((BoolAlias)0)
#define usesBool ((bool)0)
//--- module.modulemap
module CModule {
header "cmodule.h"
requires objc
export *
}
//--- valid.swift
import CModule
// Make sure we can import these constants.
print(usesUnderscoreBoolAlias)
print(usesBoolAlias)
//--- invalid.swift
import CModule
// FIXME: These ought to work too
print(usesUnderscoreBool) // expected-error {{cannot find 'usesUnderscoreBool' in scope}}
print(usesBool) // expected-error {{cannot find 'usesBool' in scope}}