Skip to content

Commit d09669b

Browse files
authored
Merge pull request swiftlang#12169 from jrose-apple/dance-dance-deduplication
[ClangImporter] Don't add duplicate search paths
2 parents 7778262 + d78d1dc commit d09669b

File tree

9 files changed

+78
-10
lines changed

9 files changed

+78
-10
lines changed

lib/ClangImporter/ClangDiagnosticConsumer.cpp

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "swift/AST/DiagnosticsClangImporter.h"
1818
#include "clang/AST/ASTContext.h"
1919
#include "clang/Frontend/DiagnosticRenderer.h"
20+
#include "clang/Frontend/FrontendDiagnostic.h"
2021
#include "clang/Lex/LexDiagnostic.h"
2122
#include "llvm/ADT/STLExtras.h"
2223

@@ -36,17 +37,37 @@ namespace {
3637
callback(fn) {}
3738

3839
private:
40+
/// Is this a diagnostic that doesn't do the user any good to show if it
41+
/// is located in one of Swift's synthetic buffers? If so, returns true to
42+
/// suppress it.
43+
static bool shouldSuppressDiagInSwiftBuffers(clang::DiagOrStoredDiag info) {
44+
if (info.isNull())
45+
return false;
46+
47+
unsigned ID;
48+
if (auto *activeDiag = info.dyn_cast<const clang::Diagnostic *>())
49+
ID = activeDiag->getID();
50+
else
51+
ID = info.get<const clang::StoredDiagnostic *>()->getID();
52+
return ID == clang::diag::note_module_import_here ||
53+
ID == clang::diag::err_module_not_built;
54+
}
55+
56+
/// Returns true if \p loc is inside one of Swift's synthetic buffers.
57+
static bool isInSwiftBuffers(clang::FullSourceLoc loc) {
58+
StringRef bufName = StringRef(loc.getManager().getBufferName(loc));
59+
return bufName == ClangImporter::Implementation::moduleImportBufferName ||
60+
bufName == ClangImporter::Implementation::bridgingHeaderBufferName;
61+
}
62+
3963
void emitDiagnosticMessage(clang::FullSourceLoc Loc,
4064
clang::PresumedLoc PLoc,
4165
clang::DiagnosticsEngine::Level Level,
4266
StringRef Message,
4367
ArrayRef<clang::CharSourceRange> Ranges,
4468
clang::DiagOrStoredDiag Info) override {
45-
StringRef bufName = StringRef(Loc.getManager().getBufferName(Loc));
46-
if (bufName == ClangImporter::Implementation::moduleImportBufferName ||
47-
bufName == ClangImporter::Implementation::bridgingHeaderBufferName) {
69+
if (shouldSuppressDiagInSwiftBuffers(Info) && isInSwiftBuffers(Loc))
4870
return;
49-
}
5071
callback(Loc, Level, Message);
5172
}
5273

@@ -61,8 +82,9 @@ namespace {
6182

6283
void emitNote(clang::FullSourceLoc Loc, StringRef Message) override {
6384
// We get invalid note locations when trying to describe where a module
64-
// is imported and the actual location is in Swift.
65-
if (Loc.isInvalid())
85+
// is imported and the actual location is in Swift. We also want to ignore
86+
// things like "in module X imported from <swift-imported-modules>".
87+
if (Loc.isInvalid() || isInSwiftBuffers(Loc))
6688
return;
6789
emitDiagnosticMessage(Loc, {}, clang::DiagnosticsEngine::Note, Message,
6890
{}, {});
@@ -227,6 +249,7 @@ void ClangDiagnosticConsumer::HandleDiagnostic(
227249
clang::FullSourceLoc clangDiagLoc(clangDiag.getLocation(),
228250
clangDiag.getSourceManager());
229251
renderer.emitDiagnostic(clangDiagLoc, clangDiagLevel, message,
230-
clangDiag.getRanges(), clangDiag.getFixItHints());
252+
clangDiag.getRanges(), clangDiag.getFixItHints(),
253+
&clangDiag);
231254
}
232255
}

lib/ClangImporter/ClangImporter.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,9 +1064,21 @@ bool ClangImporter::addSearchPath(StringRef newSearchPath, bool isFramework,
10641064
return true;
10651065

10661066
auto &headerSearchInfo = Impl.getClangPreprocessor().getHeaderSearchInfo();
1067-
headerSearchInfo.AddSearchPath({entry, isSystem ?
1068-
clang::SrcMgr::C_System :
1069-
clang::SrcMgr::C_User, isFramework},
1067+
auto exists = std::any_of(headerSearchInfo.search_dir_begin(),
1068+
headerSearchInfo.search_dir_end(),
1069+
[&](const clang::DirectoryLookup &lookup) -> bool {
1070+
if (isFramework)
1071+
return lookup.getFrameworkDir() == entry;
1072+
return lookup.getDir() == entry;
1073+
});
1074+
if (exists) {
1075+
// Don't bother adding a search path that's already there. Clang would have
1076+
// removed it via deduplication at the time the search path info gets built.
1077+
return false;
1078+
}
1079+
1080+
auto kind = isSystem ? clang::SrcMgr::C_System : clang::SrcMgr::C_User;
1081+
headerSearchInfo.AddSearchPath({entry, kind, isFramework},
10701082
/*isAngled=*/true);
10711083

10721084
// In addition to changing the current preprocessor directly, we still need
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#warning "Test.h found in override"
2+
3+
extern int TestFrameworkFromOverride;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
framework module Test {
2+
umbrella header "Test.h"
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#warning "TestUser found in override"
2+
3+
@import Test;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
framework module TestUser {
2+
umbrella header "TestUser.h"
3+
export *
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#warning "Test.h found in SDK"
2+
3+
extern int TestFrameworkFromSDK;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
framework module Test {
2+
umbrella header "Test.h"
3+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %target-swift-frontend -F %S/Inputs/explicit-system-framework-path/sdkroot/Library/Frameworks -F %S/Inputs/explicit-system-framework-path/override -typecheck -sdk %S/Inputs/explicit-system-framework-path/sdkroot %s 2>&1 | %FileCheck %s
2+
3+
// Make sure we're matching Clang's behavior on this.
4+
// RUN: echo '@import TestUser;' | %clang -F %S/Inputs/explicit-system-framework-path/sdkroot/Library/Frameworks -F %S/Inputs/explicit-system-framework-path/override -isysroot %S/Inputs/explicit-system-framework-path/sdkroot -x objective-c -fmodules -fsyntax-only - 2>&1 | %FileCheck %s
5+
6+
// This only works with framework search paths because normal include paths
7+
// will pop up a "redefinition of module 'X'" error. Only Apple platforms have
8+
// default framework search paths, so just limit this to macOS.
9+
// REQUIRES: OS=macosx
10+
11+
import TestUser
12+
13+
// CHECK: TestUser found in override
14+
// CHECK: Test.h found in override

0 commit comments

Comments
 (0)