aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Sema/SemaLookup.cpp35
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp32
2 files changed, 50 insertions, 17 deletions
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 5ad9dd8..aa7191d 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -1565,6 +1565,21 @@ void Sema::makeMergedDefinitionVisible(NamedDecl *ND) {
if (auto *TD = dyn_cast<TemplateDecl>(ND))
for (auto *Param : *TD->getTemplateParameters())
makeMergedDefinitionVisible(Param);
+
+ // If we import a named module which contains a header, and then we include a
+ // header which contains a definition of enums, we will skip parsing the enums
+ // in the current TU. But we need to ensure the visibility of the enum
+ // contants, since they are able to be found with the parents of their
+ // parents.
+ if (auto *ED = dyn_cast<EnumDecl>(ND);
+ ED && ED->isFromGlobalModule() && !ED->isScoped()) {
+ for (auto *ECD : ED->enumerators()) {
+ ECD->setVisibleDespiteOwningModule();
+ DeclContext *RedeclCtx = ED->getDeclContext()->getRedeclContext();
+ if (RedeclCtx->lookup(ECD->getDeclName()).empty())
+ RedeclCtx->makeDeclVisibleInContext(ECD);
+ }
+ }
}
/// Find the module in which the given declaration was defined.
@@ -2185,22 +2200,10 @@ bool LookupResult::isAvailableForLookup(Sema &SemaRef, NamedDecl *ND) {
// Class and enumeration member names can be found by name lookup in any
// context in which a definition of the type is reachable.
//
- // FIXME: The current implementation didn't consider about scope. For example,
- // ```
- // // m.cppm
- // export module m;
- // enum E1 { e1 };
- // // Use.cpp
- // import m;
- // void test() {
- // auto a = E1::e1; // Error as expected.
- // auto b = e1; // Should be error. namespace-scope name e1 is not visible
- // }
- // ```
- // For the above example, the current implementation would emit error for `a`
- // correctly. However, the implementation wouldn't diagnose about `b` now.
- // Since we only check the reachability for the parent only.
- // See clang/test/CXX/module/module.interface/p7.cpp for example.
+ // NOTE: The above wording may be problematic. See
+ // https://github.com/llvm/llvm-project/issues/131058 But it is much complext
+ // to adjust it in Sema's lookup process. Now we hacked it in ASTWriter. See
+ // the comments in ASTDeclContextNameLookupTrait::getLookupVisibility.
if (auto *TD = dyn_cast<TagDecl>(DC))
return SemaRef.hasReachableDefinition(TD);
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index af7229d..c6487c5 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -4331,9 +4331,36 @@ private:
return LookupVisibility::ModuleLocalVisible;
if (isTULocalInNamedModules(D))
return LookupVisibility::TULocal;
+
+ // A trick to handle enum constants. The enum constants is special since
+ // they can be found directly without their parent context. This makes it
+ // tricky to decide if an EnumConstantDecl is visible or not by their own
+ // visibilities. E.g., for a class member, we can assume it is visible if
+ // the user get its parent somehow. But for an enum constant, the users may
+ // access if without its parent context. Although we can fix the problem in
+ // Sema lookup process, it might be too complex, we just make a trick here.
+ // Note that we only removes enum constant from the lookup table from its
+ // parent of parent. We DON'T remove the enum constant from its parent. So
+ // we don't need to care about merging problems here.
+ if (auto *ECD = dyn_cast<EnumConstantDecl>(D);
+ ECD && DC.isFileContext() && ECD->getOwningModule() &&
+ ECD->getTopLevelOwningNamedModule()->isNamedModule()) {
+ if (llvm::all_of(
+ DC.noload_lookup(
+ cast<EnumDecl>(ECD->getDeclContext())->getDeclName()),
+ [](auto *Found) {
+ return Found->isInvisibleOutsideTheOwningModule();
+ }))
+ return ECD->isFromExplicitGlobalModule() ||
+ ECD->isInAnonymousNamespace()
+ ? LookupVisibility::TULocal
+ : LookupVisibility::ModuleLocalVisible;
+ }
+
return LookupVisibility::GenerallyVisibile;
}
+ DeclContext &DC;
ModuleLevelDeclsMapTy ModuleLocalDeclsMap;
TULocalDeclsMapTy TULocalDeclsMap;
@@ -4341,6 +4368,9 @@ public:
using ASTDeclContextNameTrivialLookupTrait::
ASTDeclContextNameTrivialLookupTrait;
+ ASTDeclContextNameLookupTrait(ASTWriter &Writer, DeclContext &DC)
+ : ASTDeclContextNameTrivialLookupTrait(Writer), DC(DC) {}
+
template <typename Coll> data_type getData(const Coll &Decls) {
unsigned Start = DeclIDs.size();
for (NamedDecl *D : Decls) {
@@ -4612,7 +4642,7 @@ void ASTWriter::GenerateNameLookupTable(
MultiOnDiskHashTableGenerator<reader::ASTDeclContextNameLookupTrait,
ASTDeclContextNameLookupTrait>
Generator;
- ASTDeclContextNameLookupTrait Trait(*this);
+ ASTDeclContextNameLookupTrait Trait(*this, *DC);
// The first step is to collect the declaration names which we need to
// serialize into the name lookup table, and to collect them in a stable