Skip to content

Commit 8f7baa3

Browse files
committed
[ClangImporter] Import nullary function macros
Resolves SR-2402. Import function-like macros that take no arguments, assuming their bodies are something ClangImporter would otherwise be able to import. * Modify `shouldIgnoreMacro` such that it only ignores function-like macros if they take more than zero arguments. * ClangImporter's macro importing normally creates `VarDecl`. Modify that to create FuncDecl if the original macro is function-like.
1 parent 13def2e commit 8f7baa3

File tree

9 files changed

+208
-96
lines changed

9 files changed

+208
-96
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ CHANGELOG
4242
Swift 3.1
4343
---------
4444
45+
* [SR-2402](https://bugs.swift.org/browse/SR-2402)
46+
47+
Swift now imports "function-like" macros from C and Objective-C. For now,
48+
only function-like macros that take no arguments, such as
49+
`#define MyMacro() 1`, are imported.
50+
4551
* [SE-0080][]:
4652
4753
Adds a new family of conversion initializers to all numeric types that

lib/ClangImporter/ImportDecl.cpp

Lines changed: 84 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -2897,7 +2897,8 @@ namespace {
28972897
auto result = Impl.createConstant(name, dc, type,
28982898
clang::APValue(decl->getInitVal()),
28992899
ConstantConvertKind::Coerce,
2900-
/*static*/ false, decl);
2900+
/*isStatic*/false,
2901+
/*isFunctionLike*/false, decl);
29012902
Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = result;
29022903

29032904
// If this is a Swift 2 stub, mark it as such.
@@ -2936,7 +2937,8 @@ namespace {
29362937
auto result = Impl.createConstant(name, dc, enumType,
29372938
clang::APValue(decl->getInitVal()),
29382939
ConstantConvertKind::Construction,
2939-
/*static*/ false, decl);
2940+
/*isStatic*/false,
2941+
/*isFunctionLike*/false, decl);
29402942
Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = result;
29412943

29422944
// If this is a Swift 2 stub, mark it as such.
@@ -4864,7 +4866,8 @@ SwiftDeclConverter::importOptionConstant(const clang::EnumConstantDecl *decl,
48644866
convertKind = ConstantConvertKind::ConstructionWithUnwrap;
48654867
Decl *CD = Impl.createConstant(
48664868
name, theStruct, theStruct->getDeclaredTypeInContext(),
4867-
clang::APValue(decl->getInitVal()), convertKind, /*isStatic*/ true, decl);
4869+
clang::APValue(decl->getInitVal()), convertKind, /*isStatic*/true,
4870+
/*isFunctionLike*/false, decl);
48684871
Impl.importAttributes(decl, CD);
48694872

48704873
// NS_OPTIONS members that have a value of 0 (typically named "None") do
@@ -7201,6 +7204,7 @@ ClangImporter::Implementation::createConstant(Identifier name, DeclContext *dc,
72017204
const clang::APValue &value,
72027205
ConstantConvertKind convertKind,
72037206
bool isStatic,
7207+
bool isFunctionLike,
72047208
ClangNode ClangN) {
72057209
auto &context = SwiftContext;
72067210

@@ -7260,73 +7264,62 @@ ClangImporter::Implementation::createConstant(Identifier name, DeclContext *dc,
72607264
}
72617265

72627266
assert(expr);
7263-
return createConstant(name, dc, type, expr, convertKind, isStatic, ClangN);
7267+
if (isFunctionLike)
7268+
return createFunction(name, dc, type, expr, convertKind, isStatic, ClangN);
7269+
else
7270+
return createConstant(name, dc, type, expr, convertKind, isStatic, ClangN);
72647271
}
72657272

7266-
72677273
ValueDecl *
72687274
ClangImporter::Implementation::createConstant(Identifier name, DeclContext *dc,
72697275
Type type, StringRef value,
72707276
ConstantConvertKind convertKind,
72717277
bool isStatic,
7278+
bool isFunctionLike,
72727279
ClangNode ClangN) {
72737280
auto expr = new (SwiftContext) StringLiteralExpr(value, SourceRange());
7274-
return createConstant(name, dc, type, expr, convertKind, isStatic, ClangN);
7281+
if (isFunctionLike)
7282+
return createFunction(name, dc, type, expr, convertKind, isStatic, ClangN);
7283+
else
7284+
return createConstant(name, dc, type, expr, convertKind, isStatic, ClangN);
72757285
}
72767286

7277-
7278-
ValueDecl *
7279-
ClangImporter::Implementation::createConstant(Identifier name, DeclContext *dc,
7280-
Type type, Expr *valueExpr,
7281-
ConstantConvertKind convertKind,
7282-
bool isStatic,
7283-
ClangNode ClangN) {
7284-
auto &C = SwiftContext;
7285-
7286-
VarDecl *var = nullptr;
7287-
if (ClangN) {
7288-
var = createDeclWithClangNode<VarDecl>(ClangN, Accessibility::Public,
7289-
/*IsStatic*/isStatic, /*IsLet*/false,
7290-
/*IsCaptureList*/false, SourceLoc(),
7291-
name, type, dc);
7292-
} else {
7293-
var = new (SwiftContext)
7294-
VarDecl(/*IsStatic*/isStatic, /*IsLet*/false, /*IsCaptureList*/false,
7295-
SourceLoc(), name, type, dc);
7296-
}
7297-
7298-
var->setInterfaceType(type);
7299-
7300-
// Form the argument patterns.
7301-
SmallVector<ParameterList*, 3> getterArgs;
7302-
7303-
// 'self'
7287+
/// A helper function that creates a FuncDecl which simply returns the given
7288+
/// constant value expression, and performs any additional conversion requested
7289+
/// via the \c convertKind parameter. An unnamed FuncDecl (suitable for a getter
7290+
/// function) may be created using the \c isNamed parameter.
7291+
static FuncDecl *
7292+
createValueGetterFuncDecl(ClangImporter::Implementation &Impl, Identifier name,
7293+
ASTContext &C, DeclContext *dc,
7294+
ConstantConvertKind convertKind, Type type,
7295+
Expr *valueExpr, bool isStatic, bool isNamed) {
7296+
// Form the parameters.
7297+
SmallVector<ParameterList*, 3> parameters;
7298+
// The first parameter is 'self'.
73047299
if (dc->isTypeContext()) {
73057300
auto *selfDecl = ParamDecl::createSelf(SourceLoc(), dc, isStatic);
7306-
getterArgs.push_back(ParameterList::createWithoutLoc(selfDecl));
7301+
parameters.push_back(ParameterList::createWithoutLoc(selfDecl));
73077302
}
7308-
7309-
// empty tuple
7310-
getterArgs.push_back(ParameterList::createEmpty(C));
7303+
// The second is an empty tuple.
7304+
parameters.push_back(ParameterList::createEmpty(C));
73117305

7312-
// Form the type of the getter.
7313-
auto getterType = ParameterList::getFullInterfaceType(type, getterArgs, C);
7306+
// Form the type of the function.
7307+
auto funcType = ParameterList::getFullInterfaceType(type, parameters, C);
73147308

7315-
// Create the getter function declaration.
7316-
auto func =
7317-
FuncDecl::create(C, /*StaticLoc=*/SourceLoc(), StaticSpellingKind::None,
7318-
/*FuncLoc=*/SourceLoc(),
7319-
/*Name=*/Identifier(), /*NameLoc=*/SourceLoc(),
7320-
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
7321-
/*AccessorKeywordLoc=*/SourceLoc(),
7322-
/*GenericParams=*/nullptr, getterArgs,
7323-
TypeLoc::withoutLoc(type), dc);
7309+
// Create the function declaration.
7310+
auto func = FuncDecl::create(
7311+
C, /*StaticLoc=*/SourceLoc(), StaticSpellingKind::None,
7312+
/*FuncLoc=*/SourceLoc(),
7313+
/*Name=*/isNamed ? DeclName(C, name, parameters[0]) : Identifier(),
7314+
/*NameLoc=*/SourceLoc(), /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
7315+
/*AccessorKeywordLoc=*/SourceLoc(), /*GenericParams=*/nullptr, parameters,
7316+
/*TypeLoc=*/TypeLoc::withoutLoc(type), dc);
73247317
func->setStatic(isStatic);
7325-
func->setInterfaceType(getterType);
7318+
func->setInterfaceType(funcType);
73267319
func->setAccessibility(getOverridableAccessibility(dc));
73277320

73287321
// If we're not done type checking, build the getter body.
7329-
if (!hasFinishedTypeChecking()) {
7322+
if (!Impl.hasFinishedTypeChecking()) {
73307323
auto expr = valueExpr;
73317324

73327325
// If we need a conversion, add one now.
@@ -7337,7 +7330,7 @@ ClangImporter::Implementation::createConstant(Identifier name, DeclContext *dc,
73377330
case ConstantConvertKind::Construction:
73387331
case ConstantConvertKind::ConstructionWithUnwrap: {
73397332
auto typeRef = TypeExpr::createImplicit(type, C);
7340-
7333+
73417334
expr = CallExpr::createImplicit(C, typeRef, { expr }, { C.Id_rawValue });
73427335
if (convertKind == ConstantConvertKind::ConstructionWithUnwrap)
73437336
expr = new (C) ForceValueExpr(expr, SourceLoc());
@@ -7359,20 +7352,53 @@ ClangImporter::Implementation::createConstant(Identifier name, DeclContext *dc,
73597352
auto ret = new (C) ReturnStmt(SourceLoc(), expr);
73607353

73617354
// Finally, set the body.
7362-
func->setBody(BraceStmt::create(C, SourceLoc(),
7363-
ASTNode(ret),
7364-
SourceLoc()));
7355+
func->setBody(BraceStmt::create(C, SourceLoc(), { ret }, SourceLoc()));
73657356
}
73667357

7358+
// Register this thunk as an external definition.
7359+
Impl.registerExternalDecl(func);
7360+
7361+
return func;
7362+
}
7363+
7364+
ValueDecl *
7365+
ClangImporter::Implementation::createFunction(Identifier name, DeclContext *dc,
7366+
Type type, Expr *valueExpr,
7367+
ConstantConvertKind convertKind,
7368+
bool isStatic,
7369+
ClangNode ClangN) {
7370+
return createValueGetterFuncDecl(*this, name, SwiftContext, dc, convertKind,
7371+
type, valueExpr, isStatic, /*isNamed*/true);
7372+
}
7373+
7374+
ValueDecl *
7375+
ClangImporter::Implementation::createConstant(Identifier name, DeclContext *dc,
7376+
Type type, Expr *valueExpr,
7377+
ConstantConvertKind convertKind,
7378+
bool isStatic,
7379+
ClangNode ClangN) {
7380+
auto &C = SwiftContext;
7381+
7382+
VarDecl *var = nullptr;
7383+
if (ClangN) {
7384+
var = createDeclWithClangNode<VarDecl>(ClangN, Accessibility::Public,
7385+
/*IsStatic*/isStatic, /*IsLet*/false,
7386+
/*IsCaptureList*/false, SourceLoc(),
7387+
name, type, dc);
7388+
} else {
7389+
var = new (SwiftContext)
7390+
VarDecl(/*IsStatic*/isStatic, /*IsLet*/false, /*IsCaptureList*/false,
7391+
SourceLoc(), name, type, dc);
7392+
}
7393+
var->setInterfaceType(type);
7394+
7395+
auto func = createValueGetterFuncDecl(*this, name, C, dc, convertKind, type,
7396+
valueExpr, isStatic, /*isNamed*/false);
73677397
// Mark the function transparent so that we inline it away completely.
73687398
func->getAttrs().add(new (C) TransparentAttr(/*implicit*/ true));
7369-
73707399
// Set the function up as the getter.
73717400
var->makeComputed(SourceLoc(), func, nullptr, nullptr, SourceLoc());
73727401

7373-
// Register this thunk as an external definition.
7374-
registerExternalDecl(func);
7375-
73767402
return var;
73777403
}
73787404

0 commit comments

Comments
 (0)