diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaLookup.cpp | 35 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 32 |
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 |