Skip to content

Commit 19b0a8a

Browse files
authored
Merge pull request #27633 from nkcsgexi/get-loc-return-serialized-loc
AST: teach Decl::getLoc() to return serialized source loc.
2 parents 4591811 + 1698884 commit 19b0a8a

File tree

10 files changed

+115
-17
lines changed

10 files changed

+115
-17
lines changed

include/swift/AST/Decl.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,13 @@ class alignas(1 << DeclAlignInBits) Decl {
667667
void operator=(const Decl&) = delete;
668668
SourceLoc getLocFromSource() const;
669669

670+
struct CachedExternalSourceLocs {
671+
SourceLoc Loc;
672+
SourceLoc StartLoc;
673+
SourceLoc EndLoc;
674+
};
675+
mutable CachedExternalSourceLocs const *CachedLocs = nullptr;
676+
const CachedExternalSourceLocs *calculateSerializedLocs() const;
670677
protected:
671678

672679
Decl(DeclKind kind, llvm::PointerUnion<DeclContext *, ASTContext *> context)
@@ -764,7 +771,7 @@ class alignas(1 << DeclAlignInBits) Decl {
764771

765772
/// Returns the preferred location when referring to declarations
766773
/// in diagnostics.
767-
SourceLoc getLoc() const;
774+
SourceLoc getLoc(bool SerializedOK = true) const;
768775

769776
/// Returns the source range of the entire declaration.
770777
SourceRange getSourceRange() const;

include/swift/Basic/SourceManager.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ class SourceManager {
4747
};
4848
std::map<const char *, VirtualFile> VirtualFiles;
4949
mutable std::pair<const char *, const VirtualFile*> CachedVFile = {nullptr, nullptr};
50-
5150
public:
5251
SourceManager(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS =
5352
llvm::vfs::getRealFileSystem())
@@ -245,9 +244,10 @@ class SourceManager {
245244
SourceLoc();
246245
}
247246

247+
SourceLoc getLocFromExternalSource(StringRef Path, unsigned Line, unsigned Col);
248248
private:
249249
const VirtualFile *getVirtualFile(SourceLoc Loc) const;
250-
250+
unsigned getExternalSourceBufferId(StringRef Path);
251251
int getLineOffset(SourceLoc Loc) const {
252252
if (auto VFile = getVirtualFile(Loc))
253253
return VFile->LineOffset;

lib/AST/Decl.cpp

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,10 @@ template<typename Class>
410410
inline char checkSourceLocType(SourceLoc (Class::*)() const);
411411
inline TwoChars checkSourceLocType(SourceLoc (Decl::*)() const);
412412

413+
template<typename Class>
414+
inline char checkSourceLocType(SourceLoc (Class::*)(bool) const);
415+
inline TwoChars checkSourceLocType(SourceLoc (Decl::*)(bool) const);
416+
413417
template<typename Class>
414418
inline char checkSourceRangeType(SourceRange (Class::*)() const);
415419
inline TwoChars checkSourceRangeType(SourceRange (Decl::*)() const);
@@ -482,12 +486,52 @@ case DeclKind::ID: return cast<ID##Decl>(this)->getLocFromSource();
482486
llvm_unreachable("Unknown decl kind");
483487
}
484488

485-
SourceLoc Decl::getLoc() const {
489+
const Decl::CachedExternalSourceLocs *Decl::calculateSerializedLocs() const {
490+
auto *File = cast<FileUnit>(getDeclContext()->getModuleScopeContext());
491+
auto Locs = File->getBasicLocsForDecl(this);
492+
if (!Locs.hasValue()) {
493+
static const Decl::CachedExternalSourceLocs NullLocs{};
494+
return &NullLocs;
495+
}
496+
auto *Result = getASTContext().Allocate<Decl::CachedExternalSourceLocs>();
497+
auto &SM = getASTContext().SourceMgr;
498+
#define CASE(X) \
499+
Result->X = SM.getLocFromExternalSource(Locs->SourceFilePath, Locs->X.Line, \
500+
Locs->X.Column);
501+
CASE(Loc)
502+
CASE(StartLoc)
503+
CASE(EndLoc)
504+
#undef CASE
505+
return Result;
506+
}
507+
508+
SourceLoc Decl::getLoc(bool SerializedOK) const {
486509
#define DECL(ID, X) \
487510
static_assert(sizeof(checkSourceLocType(&ID##Decl::getLoc)) == 2, \
488511
#ID "Decl is re-defining getLoc()");
489512
#include "swift/AST/DeclNodes.def"
490-
return getLocFromSource();
513+
if (isa<ModuleDecl>(this))
514+
return SourceLoc();
515+
// When the decl is context-free, we should get loc from source buffer.
516+
if (!getDeclContext())
517+
return getLocFromSource();
518+
auto *File = cast<FileUnit>(getDeclContext()->getModuleScopeContext());
519+
switch(File->getKind()) {
520+
case FileUnitKind::Source:
521+
return getLocFromSource();
522+
case FileUnitKind::SerializedAST: {
523+
if (!SerializedOK)
524+
return SourceLoc();
525+
if (!CachedLocs) {
526+
CachedLocs = calculateSerializedLocs();
527+
}
528+
return CachedLocs->Loc;
529+
}
530+
case FileUnitKind::Builtin:
531+
case FileUnitKind::ClangModule:
532+
case FileUnitKind::DWARFModule:
533+
return SourceLoc();
534+
}
491535
}
492536

493537
Expr *AbstractFunctionDecl::getSingleExpressionBody() const {

lib/Basic/SourceLoc.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,3 +357,30 @@ llvm::Optional<unsigned> SourceManager::resolveFromLineCol(unsigned BufferId,
357357
return None;
358358
}
359359

360+
unsigned SourceManager::getExternalSourceBufferId(StringRef Path) {
361+
auto It = BufIdentIDMap.find(Path);
362+
if (It != BufIdentIDMap.end()) {
363+
return It->getSecond();
364+
}
365+
unsigned Id = 0u;
366+
auto InputFileOrErr = swift::vfs::getFileOrSTDIN(*getFileSystem(), Path);
367+
if (InputFileOrErr) {
368+
// This assertion ensures we can look up from the map in the future when
369+
// using the same Path.
370+
assert(InputFileOrErr.get()->getBufferIdentifier() == Path);
371+
Id = addNewSourceBuffer(std::move(InputFileOrErr.get()));
372+
}
373+
return Id;
374+
}
375+
376+
SourceLoc
377+
SourceManager::getLocFromExternalSource(StringRef Path, unsigned Line,
378+
unsigned Col) {
379+
auto BufferId = getExternalSourceBufferId(Path);
380+
if (BufferId == 0u)
381+
return SourceLoc();
382+
auto Offset = resolveFromLineCol(BufferId, Line, Col);
383+
if (!Offset.hasValue())
384+
return SourceLoc();
385+
return getLocForOffset(BufferId, *Offset);
386+
}

lib/Index/Index.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,7 @@ bool IndexSwiftASTWalker::startEntityDecl(ValueDecl *D) {
837837
if (!shouldIndex(D, /*IsRef=*/false))
838838
return false;
839839

840-
SourceLoc Loc = D->getLoc();
840+
SourceLoc Loc = D->getLoc(/*SerializedOK*/false);
841841
if (Loc.isInvalid() && !IsModuleFile)
842842
return false;
843843

@@ -1186,7 +1186,7 @@ bool IndexSwiftASTWalker::reportImplicitConformance(ValueDecl *witness, ValueDec
11861186
if (auto *extD = dyn_cast<ExtensionDecl>(container))
11871187
loc = getLocForExtension(extD);
11881188
else
1189-
loc = container->getLoc();
1189+
loc = container->getLoc(/*SerializedOK*/false);
11901190

11911191
IndexSymbol info;
11921192
if (initIndexSymbol(witness, loc, /*IsRef=*/true, info))
@@ -1208,6 +1208,8 @@ bool IndexSwiftASTWalker::reportImplicitConformance(ValueDecl *witness, ValueDec
12081208
bool IndexSwiftASTWalker::initIndexSymbol(ValueDecl *D, SourceLoc Loc,
12091209
bool IsRef, IndexSymbol &Info) {
12101210
assert(D);
1211+
if (Loc.isValid() && SrcMgr.findBufferContainingLoc(Loc) != BufferID)
1212+
return true;
12111213
if (auto *VD = dyn_cast<VarDecl>(D)) {
12121214
// Always base the symbol information on the canonical VarDecl
12131215
D = VD->getCanonicalVarDecl();
@@ -1266,7 +1268,7 @@ static NominalTypeDecl *getNominalParent(ValueDecl *D) {
12661268

12671269
bool IndexSwiftASTWalker::initFuncDeclIndexSymbol(FuncDecl *D,
12681270
IndexSymbol &Info) {
1269-
if (initIndexSymbol(D, D->getLoc(), /*IsRef=*/false, Info))
1271+
if (initIndexSymbol(D, D->getLoc(/*SerializedOK*/false), /*IsRef=*/false, Info))
12701272
return true;
12711273

12721274
if (isDynamicVarAccessorOrFunc(D, Info.symInfo)) {

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -644,8 +644,10 @@ TypeChecker::overApproximateAvailabilityAtLocation(SourceLoc loc,
644644
// We can assume we are running on at least the minimum deployment target.
645645
auto OverApproximateContext =
646646
AvailabilityContext::forDeploymentTarget(Context);
647-
648-
while (DC && loc.isInvalid()) {
647+
auto isInvalidLoc = [SF](SourceLoc loc) {
648+
return SF ? loc.isInvalid() : true;
649+
};
650+
while (DC && isInvalidLoc(loc)) {
649651
const Decl *D = DC->getInnermostDeclarationDeclContext();
650652
if (!D)
651653
break;

test/SourceKit/CompileNotifications/arg-parsing.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// ARG_PARSE_0: {
44
// ARG_PARSE_0: key.notification: source.notification.compile-will-start
55
// ARG_PARSE_0: key.compileid: [[CID1:".*"]]
6-
// ARG_PARSE_0: key.compilerargs-string: "{{.*}}.swift -no-such-arg"
6+
// ARG_PARSE_0: key.compilerargs-string: "{{.*}}.swift -no-such-arg -Xfrontend -ignore-module-source-info"
77
// ARG_PARSE_0: }
88
// ARG_PARSE_0: {
99
// ARG_PARSE_0: key.notification: source.notification.compile-did-finish
@@ -24,7 +24,7 @@
2424
// ARG_PARSE_1: {
2525
// ARG_PARSE_1: key.notification: source.notification.compile-will-start
2626
// ARG_PARSE_1: key.compileid: [[CID1:".*"]]
27-
// ARG_PARSE_1: key.compilerargs-string: "{{.*}}.swift -no-such-arg"
27+
// ARG_PARSE_1: key.compilerargs-string: "{{.*}}.swift -no-such-arg -Xfrontend -ignore-module-source-info"
2828
// ARG_PARSE_1: }
2929
// ARG_PARSE_1: {
3030
// ARG_PARSE_1: key.notification: source.notification.compile-did-finish

test/lit.cfg

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,10 @@ if test_options:
351351
config.swift_test_options += test_options
352352

353353
config.swift_frontend_test_options = os.environ.get('SWIFT_FRONTEND_TEST_OPTIONS', '')
354+
config.swift_frontend_test_options += ' -ignore-module-source-info'
354355
config.swift_driver_test_options = os.environ.get('SWIFT_DRIVER_TEST_OPTIONS', '')
356+
config.swift_driver_test_options += ' -Xfrontend'
357+
config.swift_driver_test_options += ' -ignore-module-source-info'
355358
config.sil_test_options = os.environ.get('SIL_TEST_OPTIONS', '')
356359

357360
clang_module_cache_path = make_path(config.swift_test_results_dir, "clang-module-cache")
@@ -878,7 +881,7 @@ if run_vendor == 'apple':
878881
config.target_sdk_name = xcrun_sdk_name
879882
config.target_ld = "%s ld -L%r" % (xcrun_prefix, make_path(test_resource_dir, config.target_sdk_name))
880883
config.target_swift_frontend = (
881-
"%s -frontend %s -sdk %r %s %s -ignore-module-source-info" %
884+
"%s -frontend %s -sdk %r %s %s" %
882885
(config.swiftc, target_options, config.variant_sdk,
883886
config.swift_test_options, config.swift_frontend_test_options))
884887
subst_target_swift_frontend_mock_sdk = (

tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,7 @@ static int handleTestInvocation(TestOptions Opts, TestOptions &InitOpts) {
507507
sourcekitd_object_t Req = sourcekitd_request_dictionary_create(nullptr,
508508
nullptr, 0);
509509
ActiveRequest = Opts.Request;
510+
bool ShouldIgnoreSourceInfo = true;
510511
switch (Opts.Request) {
511512
case SourceKitRequest::None:
512513
llvm::errs() << "request is not set\n";
@@ -866,6 +867,7 @@ static int handleTestInvocation(TestOptions Opts, TestOptions &InitOpts) {
866867
sourcekitd_request_dictionary_set_int64(Req, KeyUsingSwiftArgs, true);
867868
sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
868869
RequestEditorOpenHeaderInterface);
870+
ShouldIgnoreSourceInfo = false;
869871
}
870872

871873
sourcekitd_request_dictionary_set_string(Req, KeyName, getInterfaceGenDocumentName().c_str());
@@ -959,6 +961,17 @@ static int handleTestInvocation(TestOptions Opts, TestOptions &InitOpts) {
959961
sourcekitd_object_t Args = sourcekitd_request_array_create(nullptr, 0);
960962
for (auto Arg : Opts.CompilerArgs)
961963
sourcekitd_request_array_set_string(Args, SOURCEKITD_ARRAY_APPEND, Arg);
964+
if (ShouldIgnoreSourceInfo) {
965+
// Ignore .swiftsourceinfo file when testing sourcekitd.
966+
// .swiftsourceinfo for stdlib will be available when sourcekitd is tested,
967+
// which may make some stdlib-depending sourcekitd tests volatile.
968+
// We cannot append the flags when the compiler arguments are for clang
969+
// invocation.
970+
sourcekitd_request_array_set_string(Args, SOURCEKITD_ARRAY_APPEND,
971+
"-Xfrontend");
972+
sourcekitd_request_array_set_string(Args, SOURCEKITD_ARRAY_APPEND,
973+
"-ignore-module-source-info");
974+
}
962975
sourcekitd_request_dictionary_set_value(Req, KeyCompilerArgs, Args);
963976
sourcekitd_request_release(Args);
964977
}

tools/swift-ide-test/swift-ide-test.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1503,7 +1503,7 @@ class AnnotationPrinter : public SourceEntityWalker {
15031503

15041504
void printLoc(SourceLoc Loc, raw_ostream &OS) {
15051505
OS << '@';
1506-
if (Loc.isValid()) {
1506+
if (Loc.isValid() && SM.findBufferContainingLoc(Loc) == BufferID) {
15071507
auto LineCol = SM.getLineAndColumn(Loc, BufferID);
15081508
OS << LineCol.first << ':' << LineCol.second;
15091509
}
@@ -1520,16 +1520,16 @@ class AnnotationPrinter : public SourceEntityWalker {
15201520
OS << 'i';
15211521
if (isa<ConstructorDecl>(D) && Entity.IsRef) {
15221522
OS << "Ctor";
1523-
printLoc(D->getLoc(), OS);
1523+
printLoc(D->getLoc(/*SerializedOK*/false), OS);
15241524
if (Entity.CtorTyRef) {
15251525
OS << '-';
15261526
OS << Decl::getKindName(Entity.CtorTyRef->getKind());
1527-
printLoc(Entity.CtorTyRef->getLoc(), OS);
1527+
printLoc(Entity.CtorTyRef->getLoc(/*SerializedOK*/false), OS);
15281528
}
15291529
} else {
15301530
OS << Decl::getKindName(D->getKind());
15311531
if (Entity.IsRef)
1532-
printLoc(D->getLoc(), OS);
1532+
printLoc(D->getLoc(/*SerializedOK*/false), OS);
15331533
}
15341534

15351535
} else {

0 commit comments

Comments
 (0)