Skip to content

Commit 57254cb

Browse files
committed
ClangImporter: Build type-checked AST for constants
1 parent 7a630f4 commit 57254cb

File tree

1 file changed

+97
-10
lines changed

1 file changed

+97
-10
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 97 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5554,7 +5554,10 @@ Decl *SwiftDeclConverter::importEnumCaseAlias(
55545554
auto constantRef =
55555555
new (Impl.SwiftContext) DeclRefExpr(original, DeclNameLoc(),
55565556
/*implicit*/ true);
5557+
constantRef->setType(original->getInterfaceType());
5558+
55575559
Type importedEnumTy = importedEnum->getDeclaredInterfaceType();
5560+
55585561
auto typeRef = TypeExpr::createImplicit(importedEnumTy, Impl.SwiftContext);
55595562
auto instantiate = new (Impl.SwiftContext)
55605563
DotSyntaxCallExpr(constantRef, SourceLoc(), typeRef);
@@ -8147,6 +8150,21 @@ ClangImporter::Implementation::importDeclContextOf(
81478150
return ext;
81488151
}
81498152

8153+
static Type getConstantLiteralType(ClangImporter::Implementation &Impl,
8154+
Type type, ConstantConvertKind convertKind) {
8155+
switch (convertKind) {
8156+
case ConstantConvertKind::Construction:
8157+
case ConstantConvertKind::ConstructionWithUnwrap: {
8158+
auto found = Impl.RawTypes.find(type->getAnyNominal());
8159+
assert(found != Impl.RawTypes.end());
8160+
return found->second;
8161+
}
8162+
8163+
default:
8164+
return type;
8165+
}
8166+
}
8167+
81508168
ValueDecl *
81518169
ClangImporter::Implementation::createConstant(Identifier name, DeclContext *dc,
81528170
Type type,
@@ -8188,20 +8206,49 @@ ClangImporter::Implementation::createConstant(Identifier name, DeclContext *dc,
81888206
if (isNegative)
81898207
printedValue = printedValue.drop_front();
81908208

8209+
auto literalType = getConstantLiteralType(*this, type, convertKind);
8210+
81918211
// Create the expression node.
81928212
StringRef printedValueCopy(context.AllocateCopy(printedValue));
81938213
if (value.getKind() == clang::APValue::Int) {
81948214
if (type->getCanonicalType()->isBool()) {
8195-
expr = new (context) BooleanLiteralExpr(value.getInt().getBoolValue(),
8196-
SourceLoc(),
8197-
/**Implicit=*/true);
8215+
auto *boolExpr =
8216+
new (context) BooleanLiteralExpr(value.getInt().getBoolValue(),
8217+
SourceLoc(),
8218+
/**Implicit=*/true);
8219+
8220+
boolExpr->setBuiltinInitializer(
8221+
context.getBoolBuiltinInitDecl());
8222+
boolExpr->setType(literalType);
8223+
8224+
expr = boolExpr;
81988225
} else {
8199-
expr = new (context) IntegerLiteralExpr(printedValueCopy, SourceLoc(),
8200-
/*Implicit=*/true);
8226+
auto *intExpr =
8227+
new (context) IntegerLiteralExpr(printedValueCopy, SourceLoc(),
8228+
/*Implicit=*/true);
8229+
8230+
auto *intDecl = literalType->getAnyNominal();
8231+
intExpr->setBuiltinInitializer(
8232+
context.getIntBuiltinInitDecl(intDecl));
8233+
intExpr->setType(literalType);
8234+
8235+
expr = intExpr;
82018236
}
82028237
} else {
8203-
expr = new (context) FloatLiteralExpr(printedValueCopy, SourceLoc(),
8204-
/*Implicit=*/true);
8238+
auto *floatExpr =
8239+
new (context) FloatLiteralExpr(printedValueCopy, SourceLoc(),
8240+
/*Implicit=*/true);
8241+
8242+
auto maxFloatTypeDecl = context.get_MaxBuiltinFloatTypeDecl();
8243+
floatExpr->setBuiltinType(
8244+
maxFloatTypeDecl->getUnderlyingTypeLoc().getType());
8245+
8246+
auto *floatDecl = literalType->getAnyNominal();
8247+
floatExpr->setBuiltinInitializer(
8248+
context.getFloatBuiltinInitDecl(floatDecl));
8249+
floatExpr->setType(literalType);
8250+
8251+
expr = floatExpr;
82058252
}
82068253

82078254
if (isNegative)
@@ -8223,6 +8270,13 @@ ClangImporter::Implementation::createConstant(Identifier name, DeclContext *dc,
82238270
bool isStatic,
82248271
ClangNode ClangN) {
82258272
auto expr = new (SwiftContext) StringLiteralExpr(value, SourceRange());
8273+
8274+
auto literalType = getConstantLiteralType(*this, type, convertKind);
8275+
auto *stringDecl = literalType->getAnyNominal();
8276+
expr->setBuiltinInitializer(
8277+
SwiftContext.getStringBuiltinInitDecl(stringDecl));
8278+
expr->setType(literalType);
8279+
82268280
return createConstant(name, dc, type, expr, convertKind, isStatic, ClangN);
82278281
}
82288282

@@ -8287,10 +8341,42 @@ ClangImporter::Implementation::createConstant(Identifier name, DeclContext *dc,
82878341
case ConstantConvertKind::Construction:
82888342
case ConstantConvertKind::ConstructionWithUnwrap: {
82898343
auto typeRef = TypeExpr::createImplicit(type, C);
8290-
8291-
expr = CallExpr::createImplicit(C, typeRef, { expr }, { C.Id_rawValue });
8292-
if (convertKind == ConstantConvertKind::ConstructionWithUnwrap)
8344+
8345+
// Reference init(rawValue: T)
8346+
auto found = RawInits.find(type->getAnyNominal());
8347+
assert(found != RawInits.end());
8348+
8349+
auto *init = found->second;
8350+
auto initTy = init->getInterfaceType()->removeArgumentLabels(1);
8351+
auto declRef =
8352+
new (C) DeclRefExpr(init, DeclNameLoc(), /*Implicit=*/true,
8353+
AccessSemantics::Ordinary, initTy);
8354+
8355+
// (Self) -> ...
8356+
initTy = initTy->castTo<FunctionType>()->getResult();
8357+
auto initRef = new (C) DotSyntaxCallExpr(declRef, SourceLoc(),
8358+
typeRef, initTy);
8359+
initRef->setThrows(false);
8360+
8361+
// (rawValue: T) -> ...
8362+
initTy = initTy->castTo<FunctionType>()->getResult();
8363+
8364+
auto initCall = CallExpr::createImplicit(C, initRef, { expr },
8365+
{ C.Id_rawValue });
8366+
initCall->setType(initTy);
8367+
initCall->setThrows(false);
8368+
8369+
expr = initCall;
8370+
8371+
// Force unwrap if our init(rawValue:) is failable, which is currently
8372+
// the case with enums.
8373+
if (convertKind == ConstantConvertKind::ConstructionWithUnwrap) {
8374+
initTy = initTy->getOptionalObjectType();
82938375
expr = new (C) ForceValueExpr(expr, SourceLoc());
8376+
expr->setType(initTy);
8377+
}
8378+
8379+
assert(initTy->isEqual(type));
82948380
break;
82958381
}
82968382
}
@@ -8302,6 +8388,7 @@ ClangImporter::Implementation::createConstant(Identifier name, DeclContext *dc,
83028388
func->setBody(BraceStmt::create(C, SourceLoc(),
83038389
ASTNode(ret),
83048390
SourceLoc()));
8391+
func->setBodyTypeCheckedIfPresent();
83058392
}
83068393

83078394
// Mark the function transparent so that we inline it away completely.

0 commit comments

Comments
 (0)