Skip to content

Commit a12a966

Browse files
authored
Merge pull request #41079 from NuriAmari/sema-coupled-diagnostics
2 parents c439a46 + 3762ca1 commit a12a966

25 files changed

+369
-309
lines changed

include/swift/AST/ASTContext.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,9 +1217,6 @@ class ASTContext final {
12171217
InheritedProtocolConformance *
12181218
getInheritedConformance(Type type, ProtocolConformance *inherited);
12191219

1220-
/// Check if \p decl is included in LazyContexts.
1221-
bool isLazyContext(const DeclContext *decl);
1222-
12231220
/// Get the lazy data for the given declaration.
12241221
///
12251222
/// \param lazyLoader If non-null, the lazy loader to use when creating the

include/swift/AST/ClangModuleLoader.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,14 @@ class ClangModuleLoader : public ModuleLoader {
182182
/// Imports a clang decl directly, rather than looking up its name.
183183
virtual Decl *importDeclDirectly(const clang::NamedDecl *decl) = 0;
184184

185-
/// Emits any import diagnostics associated with the provided decl.
186-
virtual void diagnoseDeclDirectly(const clang::NamedDecl *decl) = 0;
185+
/// Emits diagnostics for any declarations named name
186+
/// whose direct declaration context is a TU.
187+
virtual void diagnoseTopLevelValue(const DeclName &name) = 0;
188+
189+
/// Emit diagnostics for declarations named name that are members
190+
/// of the provided baseType.
191+
virtual void diagnoseMemberValue(const DeclName &name,
192+
const Type &baseType) = 0;
187193

188194
/// Instantiate and import class template using given arguments.
189195
///

include/swift/AST/DiagnosticsClangImporter.def

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,20 +107,20 @@ NOTE(macro_not_imported_invalid_numeric_literal, none, "invalid numeric literal"
107107
NOTE(macro_not_imported_unsupported_literal, none, "only numeric and string macro literals supported", ())
108108
NOTE(macro_not_imported_nested_cast, none, "non-null nested casts not supported", ())
109109

110-
ERROR(macro_not_imported_function_like, none, "macro '%0' not imported: function like macros not supported", (StringRef))
111-
ERROR(macro_not_imported_unsupported_structure, none, "macro '%0' not imported: structure not supported", (StringRef))
112-
ERROR(macro_not_imported, none, "macro '%0' not imported", (StringRef))
110+
NOTE(macro_not_imported_function_like, none, "macro '%0' not imported: function like macros not supported", (StringRef))
111+
NOTE(macro_not_imported_unsupported_structure, none, "macro '%0' not imported: structure not supported", (StringRef))
112+
NOTE(macro_not_imported, none, "macro '%0' not imported", (StringRef))
113113

114114
NOTE(return_type_not_imported, none, "return type not imported", ())
115115
NOTE(parameter_type_not_imported, none, "parameter %0 not imported", (const clang::NamedDecl*))
116116
NOTE(incomplete_interface, none, "interface %0 is incomplete", (const clang::NamedDecl*))
117117
NOTE(incomplete_protocol, none, "protocol %0 is incomplete", (const clang::NamedDecl*))
118118
NOTE(unsupported_builtin_type, none, "built-in type '%0' not supported", (StringRef))
119119

120-
WARNING(record_field_not_imported, none, "field %0 not imported", (const clang::NamedDecl*))
121-
WARNING(invoked_func_not_imported, none, "function %0 not imported", (const clang::NamedDecl*))
122-
WARNING(record_method_not_imported, none, "method %0 not imported", (const clang::NamedDecl*))
123-
WARNING(objc_property_not_imported, none, "property %0 not imported", (const clang::NamedDecl*))
120+
NOTE(record_field_not_imported, none, "field %0 not imported", (const clang::NamedDecl*))
121+
NOTE(invoked_func_not_imported, none, "function %0 not imported", (const clang::NamedDecl*))
122+
NOTE(record_method_not_imported, none, "method %0 not imported", (const clang::NamedDecl*))
123+
NOTE(objc_property_not_imported, none, "property %0 not imported", (const clang::NamedDecl*))
124124

125125
NOTE(forward_declared_interface_label, none, "interface %0 forward declared here", (const clang::NamedDecl*))
126126
NOTE(forward_declared_protocol_label, none, "protocol %0 forward declared here", (const clang::NamedDecl*))

include/swift/AST/LazyResolver.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,6 @@ class alignas(void*) LazyMemberLoader {
8585
loadNamedMembers(const IterableDeclContext *IDC, DeclBaseName N,
8686
uint64_t contextData) = 0;
8787

88-
virtual void diagnoseMissingNamedMember(const IterableDeclContext *IDC,
89-
DeclName name) = 0;
90-
9188
/// Populates the given vector with all conformances for \p D.
9289
///
9390
/// The implementation should \em not call setConformances on \p D.

include/swift/AST/NameLookup.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,9 @@ void lookupVisibleMemberDecls(VisibleDeclConsumer &Consumer,
491491

492492
namespace namelookup {
493493

494+
void extractDirectlyReferencedNominalTypes(
495+
Type type, SmallVectorImpl<NominalTypeDecl *> &decls);
496+
494497
/// Once name lookup has gathered a set of results, perform any necessary
495498
/// steps to prune the result set before returning it to the caller.
496499
void pruneLookupResultSet(const DeclContext *dc, NLOptions options,

include/swift/ClangImporter/ClangImporter.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -517,8 +517,13 @@ class ClangImporter final : public ClangModuleLoader {
517517
/// Imports a clang decl directly, rather than looking up it's name.
518518
Decl *importDeclDirectly(const clang::NamedDecl *decl) override;
519519

520-
/// Emits any pending diagnostics associated with the provided decl.
521-
void diagnoseDeclDirectly(const clang::NamedDecl *decl) override;
520+
/// Emits diagnostics for any declarations named name
521+
/// whose direct declaration context is a TU.
522+
void diagnoseTopLevelValue(const DeclName &name) override;
523+
524+
/// Emit diagnostics for declarations named name that are members
525+
/// of the provided baseType.
526+
void diagnoseMemberValue(const DeclName &name, const Type &baseType) override;
522527
};
523528

524529
ImportDecl *createImportDecl(ASTContext &Ctx, DeclContext *DC, ClangNode ClangN,

lib/AST/ASTContext.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2503,10 +2503,6 @@ ASTContext::getInheritedConformance(Type type, ProtocolConformance *inherited) {
25032503
return result;
25042504
}
25052505

2506-
bool ASTContext::isLazyContext(const DeclContext *dc) {
2507-
return getImpl().LazyContexts.count(dc) != 0;
2508-
}
2509-
25102506
LazyContextData *ASTContext::getOrCreateLazyContextData(
25112507
const DeclContext *dc,
25122508
LazyMemberLoader *lazyLoader) {

lib/AST/NameLookup.cpp

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1475,16 +1475,6 @@ DirectLookupRequest::evaluate(Evaluator &evaluator,
14751475
// Look for a declaration with this name.
14761476
auto known = Table.find(name);
14771477
if (known == Table.end()) {
1478-
// Diagnose the missing member if:
1479-
// - The flag enabling ClangImporter diagnostics is passed.
1480-
// - The containing decl is a ClangDecl.
1481-
// - The containing decl (and DeclContext) is lazy.
1482-
if (ctx.LangOpts.EnableExperimentalClangImporterDiagnostics &&
1483-
ctx.isLazyContext(decl) && decl->getDecl()->getClangDecl()) {
1484-
auto ci =
1485-
ctx.getOrCreateLazyIterableContextData(decl, /*lazyLoader=*/nullptr);
1486-
ci->loader->diagnoseMissingNamedMember(decl, name);
1487-
}
14881478
return TinyPtrVector<ValueDecl *>();
14891479
}
14901480

@@ -1601,8 +1591,8 @@ void namelookup::pruneLookupResultSet(const DeclContext *dc, NLOptions options,
16011591

16021592
/// Inspect the given type to determine which nominal type declarations it
16031593
/// directly references, to facilitate name lookup into those types.
1604-
static void extractDirectlyReferencedNominalTypes(
1605-
Type type, SmallVectorImpl<NominalTypeDecl *> &decls) {
1594+
void namelookup::extractDirectlyReferencedNominalTypes(
1595+
Type type, SmallVectorImpl<NominalTypeDecl *> &decls) {
16061596
if (auto nominal = type->getAnyNominal()) {
16071597
decls.push_back(nominal);
16081598
return;
@@ -1674,7 +1664,8 @@ bool DeclContext::lookupQualified(Type type,
16741664

16751665
// Figure out which nominal types we will look into.
16761666
SmallVector<NominalTypeDecl *, 4> nominalTypesToLookInto;
1677-
extractDirectlyReferencedNominalTypes(type, nominalTypesToLookInto);
1667+
namelookup::extractDirectlyReferencedNominalTypes(type,
1668+
nominalTypesToLookInto);
16781669

16791670
return lookupQualified(nominalTypesToLookInto, member, options, decls);
16801671
}

lib/ClangImporter/ClangImporter.cpp

Lines changed: 50 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -3275,11 +3275,6 @@ void ClangModuleUnit::lookupValue(DeclName name, NLKind lookupKind,
32753275
if (auto lookupTable = owner.findLookupTable(clangModule)) {
32763276
// Search it.
32773277
owner.lookupValue(*lookupTable, name, *consumer);
3278-
if (getASTContext().LangOpts.EnableExperimentalClangImporterDiagnostics) {
3279-
if (results.empty()) {
3280-
owner.diagnoseValue(*lookupTable, name);
3281-
}
3282-
}
32833278
}
32843279
}
32853280

@@ -4127,7 +4122,7 @@ void ClangImporter::Implementation::lookupVisibleDecls(
41274122
DeclBaseName name = baseName.toDeclBaseName(SwiftContext);
41284123
if (!lookupValue(table, name, consumer) &&
41294124
SwiftContext.LangOpts.EnableExperimentalEagerClangModuleDiagnostics) {
4130-
diagnoseValue(table, name);
4125+
diagnoseTopLevelValue(name);
41314126
}
41324127
}
41334128
}
@@ -4183,30 +4178,42 @@ void ClangImporter::Implementation::lookupAllObjCMembers(
41834178
}
41844179
}
41854180

4186-
void ClangImporter::Implementation::diagnoseValue(SwiftLookupTable &table,
4187-
DeclName name) {
4188-
auto &clangCtx = getClangASTContext();
4189-
auto clangTU = clangCtx.getTranslationUnitDecl();
4190-
4191-
if (name.isOperator()) {
4192-
for (auto entry : table.lookupMemberOperators(name.getBaseName())) {
4193-
diagnoseTargetDirectly(entry);
4181+
void ClangImporter::Implementation::diagnoseTopLevelValue(
4182+
const DeclName &name) {
4183+
forEachLookupTable([&](SwiftLookupTable &table) -> bool {
4184+
for (const auto &entry :
4185+
table.lookup(name.getBaseName(),
4186+
EffectiveClangContext(
4187+
getClangASTContext().getTranslationUnitDecl()))) {
4188+
diagnoseTargetDirectly(importDiagnosticTargetFromLookupTableEntry(entry));
41944189
}
4195-
}
4190+
return false;
4191+
});
4192+
}
41964193

4197-
for (auto entry : table.lookup(name.getBaseName(), clangTU)) {
4198-
diagnoseTargetDirectly(importDiagnosticTargetFromLookupTableEntry(entry));
4199-
}
4194+
void ClangImporter::Implementation::diagnoseMemberValue(
4195+
const DeclName &name, const clang::DeclContext *container) {
4196+
forEachLookupTable([&](SwiftLookupTable &table) -> bool {
4197+
for (const auto &entry :
4198+
table.lookup(name.getBaseName(), EffectiveClangContext(container))) {
4199+
if (clang::NamedDecl *nd = entry.get<clang::NamedDecl *>()) {
4200+
// We are only interested in members of a particular context,
4201+
// skip other contexts.
4202+
if (nd->getDeclContext() != container)
4203+
continue;
4204+
4205+
diagnoseTargetDirectly(
4206+
importDiagnosticTargetFromLookupTableEntry(entry));
4207+
}
4208+
// If the entry is not a NamedDecl, it is a form of macro, which cannot be
4209+
// a member value.
4210+
}
4211+
return false;
4212+
});
42004213
}
42014214

42024215
void ClangImporter::Implementation::diagnoseTargetDirectly(
42034216
ImportDiagnosticTarget target) {
4204-
if (!(SwiftContext.LangOpts.EnableExperimentalClangImporterDiagnostics ||
4205-
SwiftContext.LangOpts.EnableExperimentalEagerClangModuleDiagnostics) ||
4206-
DiagnosedValues.count(target))
4207-
return;
4208-
4209-
DiagnosedValues.insert(target);
42104217
if (const clang::Decl *decl = target.dyn_cast<const clang::Decl *>()) {
42114218
Walker.TraverseDecl(const_cast<clang::Decl *>(decl));
42124219
} else if (const clang::MacroInfo *macro =
@@ -4363,8 +4370,6 @@ TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
43634370
recordDecl->getClangDecl()) {
43644371
if (auto import = ctx.getClangModuleLoader()->importDeclDirectly(named))
43654372
result.push_back(cast<ValueDecl>(import));
4366-
else if (ctx.LangOpts.EnableExperimentalClangImporterDiagnostics)
4367-
ctx.getClangModuleLoader()->diagnoseDeclDirectly(named);
43684373
}
43694374
}
43704375

@@ -4497,22 +4502,6 @@ ClangImporter::Implementation::loadNamedMembers(
44974502
return Members;
44984503
}
44994504

4500-
void ClangImporter::Implementation::diagnoseMissingNamedMember(
4501-
const IterableDeclContext *IDC, DeclName name) {
4502-
Optional<clang::Module *> containingModule =
4503-
getClangSubmoduleForDecl(IDC->getDecl()->getClangDecl());
4504-
assert(containingModule &&
4505-
"Members should never be loaded from a forward-declared decl");
4506-
auto allResults = evaluateOrDefault(
4507-
SwiftContext.evaluator,
4508-
ClangDirectLookupRequest({const_cast<Decl *>(IDC->getDecl()),
4509-
IDC->getDecl()->getClangDecl(), name}),
4510-
{});
4511-
for (auto entry : allResults) {
4512-
diagnoseTargetDirectly(importDiagnosticTargetFromLookupTableEntry(entry));
4513-
}
4514-
}
4515-
45164505
EffectiveClangContext ClangImporter::Implementation::getEffectiveClangContext(
45174506
const NominalTypeDecl *nominal) {
45184507
// If we have a Clang declaration, look at it to determine the
@@ -4747,6 +4736,23 @@ Decl *ClangImporter::importDeclDirectly(const clang::NamedDecl *decl) {
47474736
return Impl.importDecl(decl, Impl.CurrentVersion);
47484737
}
47494738

4750-
void ClangImporter::diagnoseDeclDirectly(const clang::NamedDecl *decl) {
4751-
Impl.diagnoseTargetDirectly(decl);
4739+
void ClangImporter::diagnoseTopLevelValue(const DeclName &name) {
4740+
Impl.diagnoseTopLevelValue(name);
4741+
}
4742+
4743+
void ClangImporter::diagnoseMemberValue(const DeclName &name,
4744+
const Type &baseType) {
4745+
if (!baseType->getAnyNominal())
4746+
return;
4747+
4748+
SmallVector<NominalTypeDecl *, 4> nominalTypesToLookInto;
4749+
namelookup::extractDirectlyReferencedNominalTypes(baseType,
4750+
nominalTypesToLookInto);
4751+
for (auto containerDecl : nominalTypesToLookInto) {
4752+
const clang::Decl *clangContainerDecl = containerDecl->getClangDecl();
4753+
if (clangContainerDecl && isa<clang::DeclContext>(clangContainerDecl)) {
4754+
Impl.diagnoseMemberValue(name,
4755+
cast<clang::DeclContext>(clangContainerDecl));
4756+
}
4757+
}
47524758
}

lib/ClangImporter/ImporterImpl.h

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -404,11 +404,6 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
404404
std::unordered_set<ImportDiagnostic, ImportDiagnosticHasher>
405405
CollectedDiagnostics;
406406

407-
// ClangNodes for which all import diagnostics have been both collected and
408-
// emitted.
409-
std::unordered_set<ImportDiagnosticTarget, ImportDiagnosticTargetHasher>
410-
DiagnosedValues;
411-
412407
const bool ImportForwardDeclarations;
413408
const bool DisableSwiftBridgeAttr;
414409
const bool BridgingHeaderExplicitlyRequested;
@@ -1455,9 +1450,6 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
14551450
loadNamedMembers(const IterableDeclContext *IDC, DeclBaseName N,
14561451
uint64_t contextData) override;
14571452

1458-
virtual void diagnoseMissingNamedMember(const IterableDeclContext *IDC,
1459-
DeclName name) override;
1460-
14611453
private:
14621454
void
14631455
loadAllMembersOfObjcContainer(Decl *D,
@@ -1600,8 +1592,14 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
16001592
void lookupAllObjCMembers(SwiftLookupTable &table,
16011593
VisibleDeclConsumer &consumer);
16021594

1603-
/// Emit any import diagnostics associated with the given name.
1604-
void diagnoseValue(SwiftLookupTable &table, DeclName name);
1595+
/// Emits diagnostics for any declarations named name
1596+
/// whose direct declaration context is a TU.
1597+
void diagnoseTopLevelValue(const DeclName &name);
1598+
1599+
/// Emit diagnostics for declarations named name that are members
1600+
/// of the provided container.
1601+
void diagnoseMemberValue(const DeclName &name,
1602+
const clang::DeclContext *container);
16051603

16061604
/// Emit any import diagnostics associated with the given Clang node.
16071605
void diagnoseTargetDirectly(ImportDiagnosticTarget target);

lib/Sema/CSDiagnostics.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3626,6 +3626,11 @@ bool MissingMemberFailure::diagnoseAsError() {
36263626
emitDiagnostic(diagnostic, baseType, getName())
36273627
.highlight(getSourceRange())
36283628
.highlight(nameLoc.getSourceRange());
3629+
const auto &ctx = getSolution().getDC()->getASTContext();
3630+
if (ctx.LangOpts.EnableExperimentalClangImporterDiagnostics) {
3631+
ctx.getClangModuleLoader()->diagnoseMemberValue(getName().getFullName(),
3632+
baseType);
3633+
}
36293634
};
36303635

36313636
TypoCorrectionResults corrections(getName(), nameLoc);

lib/Sema/PreCheckExpr.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,10 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
590590
.diagnose(Loc, diag::cannot_find_in_scope, Name,
591591
Name.isOperator())
592592
.highlight(UDRE->getSourceRange());
593+
if (Context.LangOpts.EnableExperimentalClangImporterDiagnostics) {
594+
Context.getClangModuleLoader()->diagnoseTopLevelValue(
595+
Name.getFullName());
596+
}
593597
};
594598

595599
if (!isConfused) {

lib/Serialization/Deserialization.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6402,13 +6402,6 @@ void ModuleFile::loadAllMembers(Decl *container, uint64_t contextData) {
64026402
}
64036403
}
64046404

6405-
void ModuleFile::diagnoseMissingNamedMember(const IterableDeclContext *IDC,
6406-
DeclName name) {
6407-
// TODO: Implement diagnostics for failed member lookups from module files.
6408-
llvm_unreachable(
6409-
"Missing member diangosis is not implemented for module files.");
6410-
}
6411-
64126405
static llvm::Error consumeErrorIfXRefNonLoadedModule(llvm::Error &&error) {
64136406
// Missing module errors are most likely caused by an
64146407
// implementation-only import hiding types and decls.

lib/Serialization/ModuleFile.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -699,9 +699,6 @@ class ModuleFile
699699
virtual void loadAllMembers(Decl *D,
700700
uint64_t contextData) override;
701701

702-
virtual void diagnoseMissingNamedMember(const IterableDeclContext *IDC,
703-
DeclName name) override;
704-
705702
virtual TinyPtrVector<ValueDecl *>
706703
loadNamedMembers(const IterableDeclContext *IDC, DeclBaseName N,
707704
uint64_t contextData) override;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
struct MyStruct {
2+
int _Complex commonName;
3+
};
4+
5+
_Complex int commonName();

test/ClangImporter/Inputs/custom-modules/module.map

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,3 +266,8 @@ module LocalVsFileScope {
266266
header "LocalVsFileScope.h"
267267
export *
268268
}
269+
270+
module CommonName {
271+
header "CommonName.h"
272+
export *
273+
}

0 commit comments

Comments
 (0)