|
20 | 20 | #include "swift/AST/ASTContext.h"
|
21 | 21 | #include "swift/AST/DiagnosticsClangImporter.h"
|
22 | 22 | #include "swift/AST/Expr.h"
|
| 23 | +#include "swift/AST/ParameterList.h" |
23 | 24 | #include "swift/AST/Stmt.h"
|
24 | 25 | #include "swift/AST/Types.h"
|
25 | 26 | #include "swift/Basic/Assertions.h"
|
|
31 | 32 | #include "clang/Lex/MacroInfo.h"
|
32 | 33 | #include "clang/Lex/Preprocessor.h"
|
33 | 34 | #include "clang/Sema/DelayedDiagnostic.h"
|
| 35 | +#include "clang/Sema/Lookup.h" |
34 | 36 | #include "clang/Sema/Sema.h"
|
35 | 37 | #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
|
36 | 38 | #include "llvm/ADT/SmallString.h"
|
@@ -371,6 +373,90 @@ getIntegerConstantForMacroToken(ClangImporter::Implementation &impl,
|
371 | 373 | return std::nullopt;
|
372 | 374 | }
|
373 | 375 |
|
| 376 | +namespace { |
| 377 | +ValueDecl *importDeclAlias(ClangImporter::Implementation &clang, |
| 378 | + swift::DeclContext *DC, const clang::ValueDecl *D, |
| 379 | + Identifier alias) { |
| 380 | + swift::ValueDecl *VD = |
| 381 | + dyn_cast_or_null<ValueDecl>(clang.importDecl(D, clang.CurrentVersion)); |
| 382 | + if (VD == nullptr) |
| 383 | + return nullptr; |
| 384 | + |
| 385 | + swift::ASTContext &Ctx = DC->getASTContext(); |
| 386 | + ImportedType Ty = |
| 387 | + clang.importType(D->getType(), ImportTypeKind::Abstract, |
| 388 | + [&clang, &D](Diagnostic &&Diag) { |
| 389 | + clang.addImportDiagnostic(D, std::move(Diag), |
| 390 | + D->getLocation()); |
| 391 | + }, /*AllowsNSUIntegerAsInt*/true, |
| 392 | + Bridgeability::None, { }); |
| 393 | + swift::Type GetterTy = FunctionType::get({}, Ty.getType(), ASTExtInfo{}); |
| 394 | + swift::Type SetterTy = |
| 395 | + FunctionType::get({AnyFunctionType::Param(Ty.getType())}, |
| 396 | + Ctx.TheEmptyTupleType, ASTExtInfo{}); |
| 397 | + |
| 398 | + /* Storage */ |
| 399 | + swift::VarDecl *V = |
| 400 | + new (Ctx) VarDecl(/*IsStatic*/false, VarDecl::Introducer::Var, |
| 401 | + SourceLoc(), alias, DC); |
| 402 | + V->setAccess(swift::AccessLevel::Public); |
| 403 | + V->setInterfaceType(Ty.getType()); |
| 404 | + V->getAttrs().add(new (Ctx) TransparentAttr(/*Implicit*/true)); |
| 405 | + V->getAttrs().add(new (Ctx) InlineAttr(InlineKind::Always)); |
| 406 | + |
| 407 | + /* Accessor */ |
| 408 | + swift::AccessorDecl *G = nullptr; |
| 409 | + { |
| 410 | + G = AccessorDecl::createImplicit(Ctx, AccessorKind::Get, V, false, false, |
| 411 | + TypeLoc(), GetterTy, DC); |
| 412 | + G->setAccess(swift::AccessLevel::Public); |
| 413 | + G->setInterfaceType(GetterTy); |
| 414 | + G->setIsTransparent(true); |
| 415 | + G->setParameters(ParameterList::createEmpty(Ctx)); |
| 416 | + |
| 417 | + DeclRefExpr *DRE = |
| 418 | + new (Ctx) DeclRefExpr(ConcreteDeclRef(VD), {}, /*Implicit*/true, |
| 419 | + AccessSemantics::Ordinary, Ty.getType()); |
| 420 | + ReturnStmt *RS = ReturnStmt::createImplicit(Ctx, DRE); |
| 421 | + |
| 422 | + G->setBody(BraceStmt::createImplicit(Ctx, {RS}), |
| 423 | + AbstractFunctionDecl::BodyKind::TypeChecked); |
| 424 | + } |
| 425 | + |
| 426 | + swift::AccessorDecl *S = nullptr; |
| 427 | + if (isa<clang::VarDecl>(D) && |
| 428 | + !cast<clang::VarDecl>(D)->getType().isConstQualified()) { |
| 429 | + S = AccessorDecl::createImplicit(Ctx, AccessorKind::Set, V, false, false, |
| 430 | + TypeLoc(), Ctx.TheEmptyTupleType, DC); |
| 431 | + S->setAccess(swift::AccessLevel::Public); |
| 432 | + S->setInterfaceType(SetterTy); |
| 433 | + S->setIsTransparent(true); |
| 434 | + S->setParameters(ParameterList::create(Ctx, { |
| 435 | + ParamDecl::createImplicit(Ctx, Identifier(), Ctx.getIdentifier("newValue"), |
| 436 | + Ty.getType(), DC) |
| 437 | + })); |
| 438 | + |
| 439 | + DeclRefExpr *LHS = |
| 440 | + new (Ctx) DeclRefExpr(ConcreteDeclRef(VD), {}, /*Implicit*/true, |
| 441 | + AccessSemantics::Ordinary, Ty.getType()); |
| 442 | + DeclRefExpr *RHS = |
| 443 | + new (Ctx) DeclRefExpr(S->getParameters()->get(0), {}, /*Implicit*/true, |
| 444 | + AccessSemantics::Ordinary, Ty.getType()); |
| 445 | + AssignExpr *AE = new (Ctx) AssignExpr(LHS, SourceLoc(), RHS, true); |
| 446 | + AE->setType(Ctx.TheEmptyTupleType); |
| 447 | + S->setBody(BraceStmt::createImplicit(Ctx, {AE}), |
| 448 | + AbstractFunctionDecl::BodyKind::TypeChecked); |
| 449 | + } |
| 450 | + |
| 451 | + /* Bind */ |
| 452 | + V->setImplInfo(S ? StorageImplInfo::getMutableComputed() |
| 453 | + : StorageImplInfo::getImmutableComputed()); |
| 454 | + V->setAccessors(SourceLoc(), S ? ArrayRef{G,S} : ArrayRef{G}, SourceLoc()); |
| 455 | + |
| 456 | + return V; |
| 457 | +} |
| 458 | +} |
| 459 | + |
374 | 460 | static ValueDecl *importMacro(ClangImporter::Implementation &impl,
|
375 | 461 | llvm::SmallSet<StringRef, 4> &visitedMacros,
|
376 | 462 | DeclContext *DC, Identifier name,
|
@@ -509,7 +595,14 @@ static ValueDecl *importMacro(ClangImporter::Implementation &impl,
|
509 | 595 | }
|
510 | 596 | }
|
511 | 597 |
|
512 |
| - // FIXME: If the identifier refers to a declaration, alias it? |
| 598 | + /* Create an alias for any Decl */ |
| 599 | + clang::Sema &S = impl.getClangSema(); |
| 600 | + clang::LookupResult R(S, {{tok.getIdentifierInfo()}, {}}, |
| 601 | + clang::Sema::LookupAnyName); |
| 602 | + if (S.LookupName(R, S.TUScope)) |
| 603 | + if (R.getResultKind() == clang::LookupResult::LookupResultKind::Found) |
| 604 | + if (const auto *VD = dyn_cast<clang::ValueDecl>(R.getFoundDecl())) |
| 605 | + return importDeclAlias(impl, DC, VD, name); |
513 | 606 | }
|
514 | 607 |
|
515 | 608 | // TODO(https://github.com/apple/swift/issues/57735): Seems rare to have a single token that is neither a literal nor an identifier, but add diagnosis.
|
|
0 commit comments