Skip to content

Commit 37bb356

Browse files
authored
Merge pull request #27924 from jrose-apple/attribute-attribution
[ClangImporter] Diagnose bad swift_name attributes better
2 parents 5f3b1da + efa82fc commit 37bb356

15 files changed

+259
-126
lines changed

include/swift/AST/DiagnosticsClangImporter.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ WARNING(unresolvable_clang_decl,none,
8686
"imported declaration '%0' could not be mapped to '%1'",
8787
(StringRef, StringRef))
8888

89+
NOTE(unresolvable_clang_decl_is_a_framework_bug,none,
90+
"please report this issue to the owners of '%0'",
91+
(StringRef))
92+
8993
WARNING(implicit_bridging_header_imported_from_module,none,
9094
"implicit import of bridging header '%0' via module %1 "
9195
"is deprecated and will be removed in a later version of Swift",

lib/ClangImporter/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ add_swift_host_library(swiftClangImporter STATIC
99
ClangAdapter.cpp
1010
ClangDiagnosticConsumer.cpp
1111
ClangImporter.cpp
12+
ClangSourceBufferImporter.cpp
1213
DWARFImporter.cpp
1314
IAMInference.cpp
1415
ImportDecl.cpp

lib/ClangImporter/ClangDiagnosticConsumer.cpp

Lines changed: 14 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "ClangDiagnosticConsumer.h"
14+
#include "ClangSourceBufferImporter.h"
1415
#include "ImporterImpl.h"
1516
#include "swift/AST/ASTContext.h"
1617
#include "swift/AST/DiagnosticEngine.h"
@@ -22,6 +23,7 @@
2223
#include "llvm/ADT/STLExtras.h"
2324

2425
using namespace swift;
26+
using namespace swift::importer;
2527

2628
namespace {
2729
class ClangDiagRenderer final : public clang::DiagnosticNoteRenderer {
@@ -109,81 +111,6 @@ ClangDiagnosticConsumer::ClangDiagnosticConsumer(
109111
: TextDiagnosticPrinter(llvm::errs(), &clangDiagOptions),
110112
ImporterImpl(impl), DumpToStderr(dumpToStderr) {}
111113

112-
static SourceLoc findEndOfLine(SourceManager &SM, SourceLoc loc,
113-
unsigned bufferID) {
114-
CharSourceRange entireBuffer = SM.getRangeForBuffer(bufferID);
115-
CharSourceRange rangeFromLoc{SM, loc, entireBuffer.getEnd()};
116-
StringRef textFromLoc = SM.extractText(rangeFromLoc);
117-
size_t newlineOffset = textFromLoc.find_first_of({"\r\n\0", 3});
118-
if (newlineOffset == StringRef::npos)
119-
return entireBuffer.getEnd();
120-
return loc.getAdvancedLoc(newlineOffset);
121-
}
122-
123-
SourceLoc ClangDiagnosticConsumer::resolveSourceLocation(
124-
const clang::SourceManager &clangSrcMgr,
125-
clang::SourceLocation clangLoc) {
126-
SourceManager &swiftSrcMgr = ImporterImpl.SwiftContext.SourceMgr;
127-
SourceLoc loc;
128-
129-
clangLoc = clangSrcMgr.getFileLoc(clangLoc);
130-
auto decomposedLoc = clangSrcMgr.getDecomposedLoc(clangLoc);
131-
if (decomposedLoc.first.isInvalid())
132-
return loc;
133-
134-
auto buffer = clangSrcMgr.getBuffer(decomposedLoc.first);
135-
unsigned mirrorID;
136-
137-
auto mirrorIter = mirroredBuffers.find(buffer);
138-
if (mirrorIter != mirroredBuffers.end()) {
139-
mirrorID = mirrorIter->second;
140-
} else {
141-
std::unique_ptr<llvm::MemoryBuffer> mirrorBuffer{
142-
llvm::MemoryBuffer::getMemBuffer(buffer->getBuffer(),
143-
buffer->getBufferIdentifier(),
144-
/*RequiresNullTerminator=*/true)
145-
};
146-
mirrorID = swiftSrcMgr.addNewSourceBuffer(std::move(mirrorBuffer));
147-
mirroredBuffers[buffer] = mirrorID;
148-
}
149-
loc = swiftSrcMgr.getLocForOffset(mirrorID, decomposedLoc.second);
150-
151-
auto presumedLoc = clangSrcMgr.getPresumedLoc(clangLoc);
152-
if (!presumedLoc.getFilename())
153-
return loc;
154-
if (presumedLoc.getLine() == 0)
155-
return SourceLoc();
156-
157-
unsigned bufferLineNumber =
158-
clangSrcMgr.getLineNumber(decomposedLoc.first, decomposedLoc.second);
159-
160-
StringRef presumedFile = presumedLoc.getFilename();
161-
SourceLoc startOfLine = loc.getAdvancedLoc(-presumedLoc.getColumn() + 1);
162-
bool isNewVirtualFile =
163-
swiftSrcMgr.openVirtualFile(startOfLine, presumedFile,
164-
presumedLoc.getLine() - bufferLineNumber);
165-
if (isNewVirtualFile) {
166-
SourceLoc endOfLine = findEndOfLine(swiftSrcMgr, loc, mirrorID);
167-
swiftSrcMgr.closeVirtualFile(endOfLine);
168-
}
169-
170-
using SourceManagerRef = llvm::IntrusiveRefCntPtr<const clang::SourceManager>;
171-
auto iter = std::lower_bound(sourceManagersWithDiagnostics.begin(),
172-
sourceManagersWithDiagnostics.end(),
173-
&clangSrcMgr,
174-
[](const SourceManagerRef &inArray,
175-
const clang::SourceManager *toInsert) {
176-
return std::less<const clang::SourceManager *>()(inArray.get(), toInsert);
177-
});
178-
if (iter == sourceManagersWithDiagnostics.end() ||
179-
iter->get() != &clangSrcMgr) {
180-
sourceManagersWithDiagnostics.insert(iter, &clangSrcMgr);
181-
}
182-
183-
return loc;
184-
}
185-
186-
187114
void ClangDiagnosticConsumer::HandleDiagnostic(
188115
clang::DiagnosticsEngine::Level clangDiagLevel,
189116
const clang::Diagnostic &clangDiag) {
@@ -195,13 +122,16 @@ void ClangDiagnosticConsumer::HandleDiagnostic(
195122
}
196123

197124
const ASTContext &ctx = ImporterImpl.SwiftContext;
125+
ClangSourceBufferImporter &bufferImporter =
126+
ImporterImpl.getBufferImporterForDiagnostics();
198127

199128
if (clangDiag.getID() == clang::diag::err_module_not_built &&
200129
CurrentImport && clangDiag.getArgStdStr(0) == CurrentImport->getName()) {
201130
SourceLoc loc = DiagLoc;
202-
if (clangDiag.getLocation().isValid())
203-
loc = resolveSourceLocation(clangDiag.getSourceManager(),
204-
clangDiag.getLocation());
131+
if (clangDiag.getLocation().isValid()) {
132+
loc = bufferImporter.resolveSourceLocation(clangDiag.getSourceManager(),
133+
clangDiag.getLocation());
134+
}
205135

206136
ctx.Diags.diagnose(loc, diag::clang_cannot_build_module,
207137
ctx.LangOpts.EnableObjCInterop,
@@ -216,9 +146,10 @@ void ClangDiagnosticConsumer::HandleDiagnostic(
216146
DiagnosticConsumer::HandleDiagnostic(clangDiagLevel, clangDiag);
217147

218148
// FIXME: Map over source ranges in the diagnostic.
219-
auto emitDiag = [&ctx, this](clang::FullSourceLoc clangNoteLoc,
220-
clang::DiagnosticsEngine::Level clangDiagLevel,
221-
StringRef message) {
149+
auto emitDiag =
150+
[&ctx, &bufferImporter](clang::FullSourceLoc clangNoteLoc,
151+
clang::DiagnosticsEngine::Level clangDiagLevel,
152+
StringRef message) {
222153
decltype(diag::error_from_clang) diagKind;
223154
switch (clangDiagLevel) {
224155
case clang::DiagnosticsEngine::Ignored:
@@ -241,8 +172,8 @@ void ClangDiagnosticConsumer::HandleDiagnostic(
241172

242173
SourceLoc noteLoc;
243174
if (clangNoteLoc.isValid())
244-
noteLoc = resolveSourceLocation(clangNoteLoc.getManager(),
245-
clangNoteLoc);
175+
noteLoc = bufferImporter.resolveSourceLocation(clangNoteLoc.getManager(),
176+
clangNoteLoc);
246177
ctx.Diags.diagnose(noteLoc, diagKind, message);
247178
};
248179

lib/ClangImporter/ClangDiagnosticConsumer.h

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -55,18 +55,6 @@ class ClangDiagnosticConsumer : public clang::TextDiagnosticPrinter {
5555

5656
ClangImporter::Implementation &ImporterImpl;
5757

58-
/// Keeps alive the Clang source managers where diagnostics have been
59-
/// reported.
60-
///
61-
/// This is a bit of a hack, but LLVM's source manager (and by extension
62-
/// Swift's) does not support buffers going away.
63-
//
64-
// This is not using SmallPtrSet or similar because we need the
65-
// IntrusiveRefCntPtr to stay a ref-counting pointer.
66-
SmallVector<llvm::IntrusiveRefCntPtr<const clang::SourceManager>, 4>
67-
sourceManagersWithDiagnostics;
68-
llvm::DenseMap<const llvm::MemoryBuffer *, unsigned> mirroredBuffers;
69-
7058
const clang::IdentifierInfo *CurrentImport = nullptr;
7159
SourceLoc DiagLoc;
7260
const bool DumpToStderr;
@@ -82,12 +70,6 @@ class ClangDiagnosticConsumer : public clang::TextDiagnosticPrinter {
8270
return LoadModuleRAII(*this, name);
8371
}
8472

85-
/// Returns a Swift source location that points into a Clang buffer.
86-
///
87-
/// This will keep the Clang buffer alive as long as this diagnostic consumer.
88-
SourceLoc resolveSourceLocation(const clang::SourceManager &clangSrcMgr,
89-
clang::SourceLocation clangLoc);
90-
9173
void HandleDiagnostic(clang::DiagnosticsEngine::Level diagLevel,
9274
const clang::Diagnostic &info) override;
9375
};

lib/ClangImporter/ClangImporter.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1000,6 +1000,7 @@ ClangImporter::create(ASTContext &ctx, const ClangImporterOptions &importerOpts,
10001000
std::make_shared<SwiftNameLookupExtension>(
10011001
importer->Impl.BridgingHeaderLookupTable,
10021002
importer->Impl.LookupTables, importer->Impl.SwiftContext,
1003+
importer->Impl.getBufferImporterForDiagnostics(),
10031004
importer->Impl.platformAvailability,
10041005
importer->Impl.InferImportAsMember));
10051006

@@ -1330,7 +1331,8 @@ bool ClangImporter::Implementation::importHeader(
13301331
}
13311332

13321333
// Finalize the lookup table, which may fail.
1333-
finalizeLookupTable(*BridgingHeaderLookupTable, getNameImporter());
1334+
finalizeLookupTable(*BridgingHeaderLookupTable, getNameImporter(),
1335+
getBufferImporterForDiagnostics());
13341336

13351337
// FIXME: What do we do if there was already an error?
13361338
if (!hadError && clangDiags.hasErrorOccurred()) {
@@ -1852,6 +1854,7 @@ ClangImporter::Implementation::Implementation(
18521854
IsReadingBridgingPCH(false),
18531855
CurrentVersion(ImportNameVersion::fromOptions(ctx.LangOpts)),
18541856
BridgingHeaderLookupTable(new SwiftLookupTable(nullptr)),
1857+
BuffersForDiagnostics(ctx.SourceMgr),
18551858
platformAvailability(ctx.LangOpts), nameImporter(),
18561859
DWARFImporter(dwarfImporterDelegate) {}
18571860

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
//===--- ClangSourceBufferImporter.cpp - Map Clang buffers to Swift -------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#import "ClangSourceBufferImporter.h"
14+
#import "swift/Basic/SourceManager.h"
15+
#import "clang/Basic/SourceManager.h"
16+
#import "llvm/Support/MemoryBuffer.h"
17+
18+
using namespace swift;
19+
using namespace swift::importer;
20+
21+
static SourceLoc findEndOfLine(SourceManager &SM, SourceLoc loc,
22+
unsigned bufferID) {
23+
CharSourceRange entireBuffer = SM.getRangeForBuffer(bufferID);
24+
CharSourceRange rangeFromLoc{SM, loc, entireBuffer.getEnd()};
25+
StringRef textFromLoc = SM.extractText(rangeFromLoc);
26+
size_t newlineOffset = textFromLoc.find_first_of({"\r\n\0", 3});
27+
if (newlineOffset == StringRef::npos)
28+
return entireBuffer.getEnd();
29+
return loc.getAdvancedLoc(newlineOffset);
30+
}
31+
32+
SourceLoc ClangSourceBufferImporter::resolveSourceLocation(
33+
const clang::SourceManager &clangSrcMgr,
34+
clang::SourceLocation clangLoc) {
35+
SourceLoc loc;
36+
37+
clangLoc = clangSrcMgr.getFileLoc(clangLoc);
38+
auto decomposedLoc = clangSrcMgr.getDecomposedLoc(clangLoc);
39+
if (decomposedLoc.first.isInvalid())
40+
return loc;
41+
42+
auto buffer = clangSrcMgr.getBuffer(decomposedLoc.first);
43+
unsigned mirrorID;
44+
45+
auto mirrorIter = mirroredBuffers.find(buffer);
46+
if (mirrorIter != mirroredBuffers.end()) {
47+
mirrorID = mirrorIter->second;
48+
} else {
49+
std::unique_ptr<llvm::MemoryBuffer> mirrorBuffer{
50+
llvm::MemoryBuffer::getMemBuffer(buffer->getBuffer(),
51+
buffer->getBufferIdentifier(),
52+
/*RequiresNullTerminator=*/true)
53+
};
54+
mirrorID = swiftSourceManager.addNewSourceBuffer(std::move(mirrorBuffer));
55+
mirroredBuffers[buffer] = mirrorID;
56+
}
57+
loc = swiftSourceManager.getLocForOffset(mirrorID, decomposedLoc.second);
58+
59+
auto presumedLoc = clangSrcMgr.getPresumedLoc(clangLoc);
60+
if (!presumedLoc.getFilename())
61+
return loc;
62+
if (presumedLoc.getLine() == 0)
63+
return SourceLoc();
64+
65+
unsigned bufferLineNumber =
66+
clangSrcMgr.getLineNumber(decomposedLoc.first, decomposedLoc.second);
67+
68+
StringRef presumedFile = presumedLoc.getFilename();
69+
SourceLoc startOfLine = loc.getAdvancedLoc(-presumedLoc.getColumn() + 1);
70+
bool isNewVirtualFile = swiftSourceManager.openVirtualFile(
71+
startOfLine, presumedFile, presumedLoc.getLine() - bufferLineNumber);
72+
if (isNewVirtualFile) {
73+
SourceLoc endOfLine = findEndOfLine(swiftSourceManager, loc, mirrorID);
74+
swiftSourceManager.closeVirtualFile(endOfLine);
75+
}
76+
77+
using SourceManagerRef = llvm::IntrusiveRefCntPtr<const clang::SourceManager>;
78+
auto iter = std::lower_bound(sourceManagersWithDiagnostics.begin(),
79+
sourceManagersWithDiagnostics.end(),
80+
&clangSrcMgr,
81+
[](const SourceManagerRef &inArray,
82+
const clang::SourceManager *toInsert) {
83+
return std::less<const clang::SourceManager *>()(inArray.get(), toInsert);
84+
});
85+
if (iter == sourceManagersWithDiagnostics.end() ||
86+
iter->get() != &clangSrcMgr) {
87+
sourceManagersWithDiagnostics.insert(iter, &clangSrcMgr);
88+
}
89+
90+
return loc;
91+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//===--- ClangSourceBufferImporter.h - Map Clang buffers over ---*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_CLANGIMPORTER_CLANGSOURCEBUFFERIMPORTER_H
14+
#define SWIFT_CLANGIMPORTER_CLANGSOURCEBUFFERIMPORTER_H
15+
16+
#include "swift/Basic/LLVM.h"
17+
#include "swift/Basic/SourceLoc.h"
18+
#include "clang/Basic/SourceLocation.h"
19+
#include "llvm/ADT/DenseMap.h"
20+
#include "llvm/ADT/IntrusiveRefCntPtr.h"
21+
#include "llvm/ADT/SmallVector.h"
22+
23+
namespace llvm {
24+
class MemoryBuffer;
25+
}
26+
27+
namespace clang {
28+
class SourceManager;
29+
}
30+
31+
namespace swift {
32+
class SourceManager;
33+
34+
namespace importer {
35+
36+
/// A helper class used to keep alive the Clang source managers where
37+
/// diagnostics have been reported.
38+
///
39+
/// This is a bit of a hack, but LLVM's source manager (and by extension
40+
/// Swift's) does not support buffers going away, so if we want to report
41+
/// diagnostics in them we have to do it this way.
42+
class ClangSourceBufferImporter {
43+
// This is not using SmallPtrSet or similar because we need the
44+
// IntrusiveRefCntPtr to stay a ref-counting pointer.
45+
SmallVector<llvm::IntrusiveRefCntPtr<const clang::SourceManager>, 4>
46+
sourceManagersWithDiagnostics;
47+
llvm::DenseMap<const llvm::MemoryBuffer *, unsigned> mirroredBuffers;
48+
SourceManager &swiftSourceManager;
49+
50+
public:
51+
explicit ClangSourceBufferImporter(SourceManager &sourceMgr)
52+
: swiftSourceManager(sourceMgr) {}
53+
54+
/// Returns a Swift source location that points into a Clang buffer.
55+
///
56+
/// This will keep the Clang buffer alive as long as this object.
57+
SourceLoc resolveSourceLocation(const clang::SourceManager &clangSrcMgr,
58+
clang::SourceLocation clangLoc);
59+
};
60+
61+
} // end namespace importer
62+
} // end namespace swift
63+
64+
#endif

0 commit comments

Comments
 (0)