diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/Decl.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaCXXScopeSpec.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLookup.cpp | 354 | ||||
-rw-r--r-- | clang/lib/Sema/SemaModule.cpp | 15 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 71 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 67 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 20 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterDecl.cpp | 18 |
10 files changed, 131 insertions, 430 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 5e51012..94f5d5c 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -588,7 +588,6 @@ static bool isExportedFromModuleInterfaceUnit(const NamedDecl *D) { // FIXME: Handle isModulePrivate. switch (D->getModuleOwnershipKind()) { case Decl::ModuleOwnershipKind::Unowned: - case Decl::ModuleOwnershipKind::ReachableWhenImported: case Decl::ModuleOwnershipKind::ModulePrivate: return false; case Decl::ModuleOwnershipKind::Visible: diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index 3f8fedda..97783eb 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -121,7 +121,7 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, // entering the context, and that can't happen in a SFINAE context. assert(!isSFINAEContext() && "partial specialization scope specifier in SFINAE context?"); - if (!hasReachableDefinition(PartialSpec)) + if (!hasVisibleDeclaration(PartialSpec)) diagnoseMissingImport(SS.getLastQualifierNameLoc(), PartialSpec, MissingImportKind::PartialSpecialization, /*Recover*/true); @@ -243,8 +243,8 @@ bool Sema::RequireCompleteEnumDecl(EnumDecl *EnumD, SourceLocation L, if (EnumD->isCompleteDefinition()) { // If we know about the definition but it is not visible, complain. NamedDecl *SuggestedDef = nullptr; - if (!hasReachableDefinition(EnumD, &SuggestedDef, - /*OnlyNeedComplete*/ false)) { + if (!hasVisibleDefinition(EnumD, &SuggestedDef, + /*OnlyNeedComplete*/false)) { // If the user is going to see an error here, recover by making the // definition visible. bool TreatAsComplete = !isSFINAEContext(); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 7ed338d..99dfebd 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -16310,12 +16310,7 @@ Decl *Sema::ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc, if (getLangOpts().CPlusPlusModules && isCurrentModulePurview()) { Module *GlobalModule = PushGlobalModuleFragment(ExternLoc, /*IsImplicit=*/true); - /// According to [module.reach]p3.2, - /// The declaration in global module fragment is reachable if it is not - /// discarded. And the discarded declaration should be deleted. So it - /// doesn't matter mark the declaration in global module fragment as - /// reachable here. - D->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ReachableWhenImported); + D->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ModulePrivate); D->setLocalOwningModule(GlobalModule); } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 40fb60c..ce7706a 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -17943,7 +17943,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, if (NeedDefinition && (Func->getTemplateSpecializationKind() != TSK_Undeclared || Func->getMemberSpecializationInfo())) - checkSpecializationReachability(Loc, Func); + checkSpecializationVisibility(Loc, Func); if (getLangOpts().CUDA) CheckCUDACall(Loc, Func); diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 47c7a61..9f2e1ea 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -1607,17 +1607,16 @@ bool Sema::hasMergedDefinitionInCurrentModule(NamedDecl *Def) { return false; } -template <typename ParmDecl> +template<typename ParmDecl> static bool -hasAcceptableDefaultArgument(Sema &S, const ParmDecl *D, - llvm::SmallVectorImpl<Module *> *Modules, - Sema::AcceptableKind Kind) { +hasVisibleDefaultArgument(Sema &S, const ParmDecl *D, + llvm::SmallVectorImpl<Module *> *Modules) { if (!D->hasDefaultArgument()) return false; while (D) { auto &DefaultArg = D->getDefaultArgStorage(); - if (!DefaultArg.isInherited() && S.isAcceptable(D, Kind)) + if (!DefaultArg.isInherited() && S.isVisible(D)) return true; if (!DefaultArg.isInherited() && Modules) { @@ -1631,36 +1630,20 @@ hasAcceptableDefaultArgument(Sema &S, const ParmDecl *D, return false; } -bool Sema::hasAcceptableDefaultArgument( - const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules, - Sema::AcceptableKind Kind) { - if (auto *P = dyn_cast<TemplateTypeParmDecl>(D)) - return ::hasAcceptableDefaultArgument(*this, P, Modules, Kind); - - if (auto *P = dyn_cast<NonTypeTemplateParmDecl>(D)) - return ::hasAcceptableDefaultArgument(*this, P, Modules, Kind); - - return ::hasAcceptableDefaultArgument( - *this, cast<TemplateTemplateParmDecl>(D), Modules, Kind); -} - bool Sema::hasVisibleDefaultArgument(const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules) { - return hasAcceptableDefaultArgument(D, Modules, - Sema::AcceptableKind::Visible); -} - -bool Sema::hasReachableDefaultArgument( - const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules) { - return hasAcceptableDefaultArgument(D, Modules, - Sema::AcceptableKind::Reachable); + if (auto *P = dyn_cast<TemplateTypeParmDecl>(D)) + return ::hasVisibleDefaultArgument(*this, P, Modules); + if (auto *P = dyn_cast<NonTypeTemplateParmDecl>(D)) + return ::hasVisibleDefaultArgument(*this, P, Modules); + return ::hasVisibleDefaultArgument(*this, cast<TemplateTemplateParmDecl>(D), + Modules); } -template <typename Filter> -static bool -hasAcceptableDeclarationImpl(Sema &S, const NamedDecl *D, - llvm::SmallVectorImpl<Module *> *Modules, Filter F, - Sema::AcceptableKind Kind) { +template<typename Filter> +static bool hasVisibleDeclarationImpl(Sema &S, const NamedDecl *D, + llvm::SmallVectorImpl<Module *> *Modules, + Filter F) { bool HasFilteredRedecls = false; for (auto *Redecl : D->redecls()) { @@ -1668,7 +1651,7 @@ hasAcceptableDeclarationImpl(Sema &S, const NamedDecl *D, if (!F(R)) continue; - if (S.isAcceptable(R, Kind)) + if (S.isVisible(R)) return true; HasFilteredRedecls = true; @@ -1684,115 +1667,74 @@ hasAcceptableDeclarationImpl(Sema &S, const NamedDecl *D, return true; } -static bool -hasAcceptableExplicitSpecialization(Sema &S, const NamedDecl *D, - llvm::SmallVectorImpl<Module *> *Modules, - Sema::AcceptableKind Kind) { - return hasAcceptableDeclarationImpl( - S, D, Modules, - [](const NamedDecl *D) { - if (auto *RD = dyn_cast<CXXRecordDecl>(D)) - return RD->getTemplateSpecializationKind() == - TSK_ExplicitSpecialization; - if (auto *FD = dyn_cast<FunctionDecl>(D)) - return FD->getTemplateSpecializationKind() == - TSK_ExplicitSpecialization; - if (auto *VD = dyn_cast<VarDecl>(D)) - return VD->getTemplateSpecializationKind() == - TSK_ExplicitSpecialization; - llvm_unreachable("unknown explicit specialization kind"); - }, - Kind); -} - bool Sema::hasVisibleExplicitSpecialization( const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules) { - return ::hasAcceptableExplicitSpecialization(*this, D, Modules, - Sema::AcceptableKind::Visible); + return hasVisibleDeclarationImpl(*this, D, Modules, [](const NamedDecl *D) { + if (auto *RD = dyn_cast<CXXRecordDecl>(D)) + return RD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization; + if (auto *FD = dyn_cast<FunctionDecl>(D)) + return FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization; + if (auto *VD = dyn_cast<VarDecl>(D)) + return VD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization; + llvm_unreachable("unknown explicit specialization kind"); + }); } -bool Sema::hasReachableExplicitSpecialization( +bool Sema::hasVisibleMemberSpecialization( const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules) { - return ::hasAcceptableExplicitSpecialization(*this, D, Modules, - Sema::AcceptableKind::Reachable); -} - -static bool -hasAcceptableMemberSpecialization(Sema &S, const NamedDecl *D, - llvm::SmallVectorImpl<Module *> *Modules, - Sema::AcceptableKind Kind) { assert(isa<CXXRecordDecl>(D->getDeclContext()) && "not a member specialization"); - return hasAcceptableDeclarationImpl( - S, D, Modules, - [](const NamedDecl *D) { - // If the specialization is declared at namespace scope, then it's a - // member specialization declaration. If it's lexically inside the class - // definition then it was instantiated. - // - // FIXME: This is a hack. There should be a better way to determine - // this. - // FIXME: What about MS-style explicit specializations declared within a - // class definition? - return D->getLexicalDeclContext()->isFileContext(); - }, - Kind); -} - -bool Sema::hasVisibleMemberSpecialization( - const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules) { - return hasAcceptableMemberSpecialization(*this, D, Modules, - Sema::AcceptableKind::Visible); -} - -bool Sema::hasReachableMemberSpecialization( - const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules) { - return hasAcceptableMemberSpecialization(*this, D, Modules, - Sema::AcceptableKind::Reachable); + return hasVisibleDeclarationImpl(*this, D, Modules, [](const NamedDecl *D) { + // If the specialization is declared at namespace scope, then it's a member + // specialization declaration. If it's lexically inside the class + // definition then it was instantiated. + // + // FIXME: This is a hack. There should be a better way to determine this. + // FIXME: What about MS-style explicit specializations declared within a + // class definition? + return D->getLexicalDeclContext()->isFileContext(); + }); } -/// Determine whether a declaration is acceptable to name lookup. +/// Determine whether a declaration is visible to name lookup. /// -/// This routine determines whether the declaration D is acceptable in the -/// current lookup context, taking into account the current template -/// instantiation stack. During template instantiation, a declaration is -/// acceptable if it is acceptable from a module containing any entity on the -/// template instantiation path (by instantiating a template, you allow it to -/// see the declarations that your module can see, including those later on in -/// your module). -bool LookupResult::isAcceptableSlow(Sema &SemaRef, NamedDecl *D, - Sema::AcceptableKind Kind) { +/// This routine determines whether the declaration D is visible in the current +/// lookup context, taking into account the current template instantiation +/// stack. During template instantiation, a declaration is visible if it is +/// visible from a module containing any entity on the template instantiation +/// path (by instantiating a template, you allow it to see the declarations that +/// your module can see, including those later on in your module). +bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) { assert(!D->isUnconditionallyVisible() && "should not call this: not in slow case"); Module *DeclModule = SemaRef.getOwningModule(D); assert(DeclModule && "hidden decl has no owning module"); - // If the owning module is visible, the decl is acceptable. - if (SemaRef.isModuleVisible(DeclModule, - D->isInvisibleOutsideTheOwningModule())) + if (SemaRef.isModuleVisible(DeclModule, D->isModulePrivate())) + // If the owning module is visible, the decl is visible. return true; // Determine whether a decl context is a file context for the purpose of - // visibility/reachability. This looks through some (export and linkage spec) - // transparent contexts, but not others (enums). + // visibility. This looks through some (export and linkage spec) transparent + // contexts, but not others (enums). auto IsEffectivelyFileContext = [](const DeclContext *DC) { return DC->isFileContext() || isa<LinkageSpecDecl>(DC) || isa<ExportDecl>(DC); }; // If this declaration is not at namespace scope - // then it is acceptable if its lexical parent has a acceptable definition. + // then it is visible if its lexical parent has a visible definition. DeclContext *DC = D->getLexicalDeclContext(); if (DC && !IsEffectivelyFileContext(DC)) { // For a parameter, check whether our current template declaration's - // lexical context is acceptable, not whether there's some other acceptable + // lexical context is visible, not whether there's some other visible // definition of it, because parameters aren't "within" the definition. // - // In C++ we need to check for a acceptable definition due to ODR merging, + // In C++ we need to check for a visible definition due to ODR merging, // and in C we must not because each declaration of a function gets its own // set of declarations for tags in prototype scope. - bool AcceptableWithinParent; + bool VisibleWithinParent; if (D->isTemplateParameter()) { bool SearchDefinitions = true; if (const auto *DCD = dyn_cast<Decl>(DC)) { @@ -1803,63 +1745,41 @@ bool LookupResult::isAcceptableSlow(Sema &SemaRef, NamedDecl *D, } } if (SearchDefinitions) - AcceptableWithinParent = - SemaRef.hasAcceptableDefinition(cast<NamedDecl>(DC), Kind); + VisibleWithinParent = SemaRef.hasVisibleDefinition(cast<NamedDecl>(DC)); else - AcceptableWithinParent = - isAcceptable(SemaRef, cast<NamedDecl>(DC), Kind); + VisibleWithinParent = isVisible(SemaRef, cast<NamedDecl>(DC)); } else if (isa<ParmVarDecl>(D) || (isa<FunctionDecl>(DC) && !SemaRef.getLangOpts().CPlusPlus)) - AcceptableWithinParent = isAcceptable(SemaRef, cast<NamedDecl>(DC), Kind); + VisibleWithinParent = isVisible(SemaRef, cast<NamedDecl>(DC)); else if (D->isModulePrivate()) { - // A module-private declaration is only acceptable if an enclosing lexical + // A module-private declaration is only visible if an enclosing lexical // parent was merged with another definition in the current module. - AcceptableWithinParent = false; + VisibleWithinParent = false; do { if (SemaRef.hasMergedDefinitionInCurrentModule(cast<NamedDecl>(DC))) { - AcceptableWithinParent = true; + VisibleWithinParent = true; break; } DC = DC->getLexicalParent(); } while (!IsEffectivelyFileContext(DC)); } else { - AcceptableWithinParent = - SemaRef.hasAcceptableDefinition(cast<NamedDecl>(DC), Kind); + VisibleWithinParent = SemaRef.hasVisibleDefinition(cast<NamedDecl>(DC)); } - if (AcceptableWithinParent && SemaRef.CodeSynthesisContexts.empty() && - Kind == Sema::AcceptableKind::Visible && + if (VisibleWithinParent && SemaRef.CodeSynthesisContexts.empty() && // FIXME: Do something better in this case. !SemaRef.getLangOpts().ModulesLocalVisibility) { // Cache the fact that this declaration is implicitly visible because // its parent has a visible definition. D->setVisibleDespiteOwningModule(); } - return AcceptableWithinParent; + return VisibleWithinParent; } - if (Kind == Sema::AcceptableKind::Visible) - return false; - - assert(Kind == Sema::AcceptableKind::Reachable && - "Additional Sema::AcceptableKind?"); - return isReachableSlow(SemaRef, D); + return false; } bool Sema::isModuleVisible(const Module *M, bool ModulePrivate) { - // [module.global.frag]p2: - // A global-module-fragment specifies the contents of the global module - // fragment for a module unit. The global module fragment can be used to - // provide declarations that are attached to the global module and usable - // within the module unit. - // - // Global module fragment is special. Global Module fragment is only usable - // within the module unit it got defined [module.global.frag]p2. So here we - // check if the Module is the global module fragment in current translation - // unit. - if (M->isGlobalModule() && M != this->GlobalModuleFragment) - return false; - // The module might be ordinarily visible. For a module-private query, that // means it is part of the current module. if (ModulePrivate && isUsableModule(M)) @@ -1892,74 +1812,8 @@ bool Sema::isModuleVisible(const Module *M, bool ModulePrivate) { }); } -// FIXME: Return false directly if we don't have an interface dependency on the -// translation unit containing D. -bool LookupResult::isReachableSlow(Sema &SemaRef, NamedDecl *D) { - assert(!isVisible(SemaRef, D) && "Shouldn't call the slow case.\n"); - - Module *DeclModule = SemaRef.getOwningModule(D); - assert(DeclModule && "hidden decl has no owning module"); - - // Entities in module map modules are reachable only if they're visible. - if (DeclModule->isModuleMapModule()) - return false; - - // If D comes from a module and SemaRef doesn't own a module, it implies D - // comes from another TU. In case SemaRef owns a module, we could judge if D - // comes from another TU by comparing the module unit. - // - // FIXME: It would look better if we have direct method to judge whether D is - // in another TU. - if (SemaRef.getCurrentModule() && - SemaRef.getCurrentModule()->getTopLevelModule() == - DeclModule->getTopLevelModule()) - return true; - - // [module.reach]/p3: - // A declaration D is reachable from a point P if: - // ... - // - D is not discarded ([module.global.frag]), appears in a translation unit - // that is reachable from P, and does not appear within a private module - // fragment. - // - // A declaration that's discarded in the GMF should be module-private. - if (D->isModulePrivate()) - return false; - - // [module.reach]/p1 - // A translation unit U is necessarily reachable from a point P if U is a - // module interface unit on which the translation unit containing P has an - // interface dependency, or the translation unit containing P imports U, in - // either case prior to P ([module.import]). - // - // [module.import]/p10 - // A translation unit has an interface dependency on a translation unit U if - // it contains a declaration (possibly a module-declaration) that imports U - // or if it has an interface dependency on a translation unit that has an - // interface dependency on U. - // - // So we could conclude the module unit U is necessarily reachable if: - // (1) The module unit U is module interface unit. - // (2) The current unit has an interface dependency on the module unit U. - // - // Here we only check for the first condition. Since we couldn't see - // DeclModule if it isn't (transitively) imported. - if (DeclModule->getTopLevelModule()->isModuleInterfaceUnit()) - return true; - - // [module.reach]/p2 - // Additional translation units on - // which the point within the program has an interface dependency may be - // considered reachable, but it is unspecified which are and under what - // circumstances. - // - // The decision here is to treat all additional tranditional units as - // unreachable. - return false; -} - -bool Sema::isAcceptableSlow(const NamedDecl *D, Sema::AcceptableKind Kind) { - return LookupResult::isAcceptable(*this, const_cast<NamedDecl *>(D), Kind); +bool Sema::isVisibleSlow(const NamedDecl *D) { + return LookupResult::isVisible(*this, const_cast<NamedDecl*>(D)); } bool Sema::shouldLinkPossiblyHiddenDecl(LookupResult &R, const NamedDecl *New) { @@ -2008,7 +1862,7 @@ bool Sema::shouldLinkPossiblyHiddenDecl(LookupResult &R, const NamedDecl *New) { /// and visible. If no declaration of D is visible, returns null. static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D, unsigned IDNS) { - assert(!LookupResult::isAvailableForLookup(SemaRef, D) && "not in slow case"); + assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case"); for (auto RD : D->redecls()) { // Don't bother with extra checks if we already know this one isn't visible. @@ -2020,7 +1874,7 @@ static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D, // visible in the same scope as D. This needs to be done much more // carefully. if (ND->isInIdentifierNamespace(IDNS) && - LookupResult::isAvailableForLookup(SemaRef, ND)) + LookupResult::isVisible(SemaRef, ND)) return ND; } @@ -2030,17 +1884,8 @@ static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D, bool Sema::hasVisibleDeclarationSlow(const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules) { assert(!isVisible(D) && "not in slow case"); - return hasAcceptableDeclarationImpl( - *this, D, Modules, [](const NamedDecl *) { return true; }, - Sema::AcceptableKind::Visible); -} - -bool Sema::hasReachableDeclarationSlow( - const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules) { - assert(!isReachable(D) && "not in slow case"); - return hasAcceptableDeclarationImpl( - *this, D, Modules, [](const NamedDecl *) { return true; }, - Sema::AcceptableKind::Reachable); + return hasVisibleDeclarationImpl(*this, D, Modules, + [](const NamedDecl *) { return true; }); } NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const { @@ -2065,60 +1910,6 @@ NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const { return findAcceptableDecl(getSema(), D, IDNS); } -bool LookupResult::isVisible(Sema &SemaRef, NamedDecl *D) { - // If this declaration is already visible, return it directly. - if (D->isUnconditionallyVisible()) - return true; - - // During template instantiation, we can refer to hidden declarations, if - // they were visible in any module along the path of instantiation. - return isAcceptableSlow(SemaRef, D, Sema::AcceptableKind::Visible); -} - -bool LookupResult::isReachable(Sema &SemaRef, NamedDecl *D) { - if (D->isUnconditionallyVisible()) - return true; - - return isAcceptableSlow(SemaRef, D, Sema::AcceptableKind::Reachable); -} - -bool LookupResult::isAvailableForLookup(Sema &SemaRef, NamedDecl *ND) { - // We should check the visibility at the callsite already. - if (isVisible(SemaRef, ND)) - return true; - - auto *DC = ND->getDeclContext(); - // If ND is not visible and it is at namespace scope, it shouldn't be found - // by name lookup. - if (DC->isFileContext()) - return false; - - // [module.interface]p7 - // 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. - if (auto *TD = dyn_cast<TagDecl>(DC)) - return SemaRef.hasReachableDefinition(TD); - - return false; -} - /// Perform unqualified name lookup starting from a given /// scope. /// @@ -3850,16 +3641,7 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc, } } else if (D->getFriendObjectKind()) { auto *RD = cast<CXXRecordDecl>(D->getLexicalDeclContext()); - // [basic.lookup.argdep]p4: - // Argument-dependent lookup finds all declarations of functions and - // function templates that - // - ... - // - are declared as a friend ([class.friend]) of any class with a - // reachable definition in the set of associated entities, - // - // FIXME: If there's a merged definition of D that is reachable, then - // the friend declaration should be considered. - if (AssociatedClasses.count(RD) && isReachable(D)) { + if (AssociatedClasses.count(RD) && isVisible(D)) { Visible = true; break; } diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp index 3aa124d..b0e7d30 100644 --- a/clang/lib/Sema/SemaModule.cpp +++ b/clang/lib/Sema/SemaModule.cpp @@ -90,14 +90,7 @@ Sema::ActOnGlobalModuleFragmentDecl(SourceLocation ModuleLoc) { // All declarations created from now on are owned by the global module. auto *TU = Context.getTranslationUnitDecl(); - // [module.global.frag]p2 - // A global-module-fragment specifies the contents of the global module - // fragment for a module unit. The global module fragment can be used to - // provide declarations that are attached to the global module and usable - // within the module unit. - // - // So the declations in the global module shouldn't be visible by default. - TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ReachableWhenImported); + TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::Visible); TU->setLocalOwningModule(GlobalModule); // FIXME: Consider creating an explicit representation of this declaration. @@ -332,12 +325,10 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc, VisibleModules.setVisible(Mod, ModuleLoc); // From now on, we have an owning module for all declarations we see. - // In C++20 modules, those declaration would be reachable when imported - // unless explicitily exported. - // Otherwise, those declarations are module-private unless explicitly + // However, those declarations are module-private unless explicitly // exported. auto *TU = Context.getTranslationUnitDecl(); - TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ReachableWhenImported); + TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ModulePrivate); TU->setLocalOwningModule(Mod); // We are in the module purview, but before any other (non import) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index dbfe616..250dbcd 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -799,9 +799,8 @@ bool Sema::DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation, if (PatternDef && !IsEntityBeingDefined) { NamedDecl *SuggestedDef = nullptr; - if (!hasReachableDefinition(const_cast<NamedDecl *>(PatternDef), - &SuggestedDef, - /*OnlyNeedComplete*/ false)) { + if (!hasVisibleDefinition(const_cast<NamedDecl*>(PatternDef), &SuggestedDef, + /*OnlyNeedComplete*/false)) { // If we're allowed to diagnose this and recover, do so. bool Recover = Complain && !isSFINAEContext(); if (Complain) @@ -5256,7 +5255,7 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, HasDefaultArg = false; if (TemplateTypeParmDecl *TypeParm = dyn_cast<TemplateTypeParmDecl>(Param)) { - if (!hasReachableDefaultArgument(TypeParm)) + if (!hasVisibleDefaultArgument(TypeParm)) return TemplateArgumentLoc(); HasDefaultArg = true; @@ -5273,7 +5272,7 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, if (NonTypeTemplateParmDecl *NonTypeParm = dyn_cast<NonTypeTemplateParmDecl>(Param)) { - if (!hasReachableDefaultArgument(NonTypeParm)) + if (!hasVisibleDefaultArgument(NonTypeParm)) return TemplateArgumentLoc(); HasDefaultArg = true; @@ -5291,7 +5290,7 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, TemplateTemplateParmDecl *TempTempParm = cast<TemplateTemplateParmDecl>(Param); - if (!hasReachableDefaultArgument(TempTempParm)) + if (!hasVisibleDefaultArgument(TempTempParm)) return TemplateArgumentLoc(); HasDefaultArg = true; @@ -5629,10 +5628,10 @@ static bool diagnoseMissingArgument(Sema &S, SourceLocation Loc, ->getTemplateParameters() ->getParam(D->getIndex())); - // If there's a default argument that's not reachable, diagnose that we're + // If there's a default argument that's not visible, diagnose that we're // missing a module import. llvm::SmallVector<Module*, 8> Modules; - if (D->hasDefaultArgument() && !S.hasReachableDefaultArgument(D, &Modules)) { + if (D->hasDefaultArgument() && !S.hasVisibleDefaultArgument(D, &Modules)) { S.diagnoseMissingImport(Loc, cast<NamedDecl>(TD), D->getDefaultArgumentLoc(), Modules, Sema::MissingImportKind::DefaultArgument, @@ -5815,7 +5814,7 @@ bool Sema::CheckTemplateArgumentList( // (when the template parameter was part of a nested template) into // the default argument. if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) { - if (!hasReachableDefaultArgument(TTP)) + if (!hasVisibleDefaultArgument(TTP)) return diagnoseMissingArgument(*this, TemplateLoc, Template, TTP, NewArgs); @@ -5832,7 +5831,7 @@ bool Sema::CheckTemplateArgumentList( ArgType); } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { - if (!hasReachableDefaultArgument(NTTP)) + if (!hasVisibleDefaultArgument(NTTP)) return diagnoseMissingArgument(*this, TemplateLoc, Template, NTTP, NewArgs); @@ -5850,7 +5849,7 @@ bool Sema::CheckTemplateArgumentList( TemplateTemplateParmDecl *TempParm = cast<TemplateTemplateParmDecl>(*Param); - if (!hasReachableDefaultArgument(TempParm)) + if (!hasVisibleDefaultArgument(TempParm)) return diagnoseMissingArgument(*this, TemplateLoc, Template, TempParm, NewArgs); @@ -11007,12 +11006,10 @@ class ExplicitSpecializationVisibilityChecker { Sema &S; SourceLocation Loc; llvm::SmallVector<Module *, 8> Modules; - Sema::AcceptableKind Kind; public: - ExplicitSpecializationVisibilityChecker(Sema &S, SourceLocation Loc, - Sema::AcceptableKind Kind) - : S(S), Loc(Loc), Kind(Kind) {} + ExplicitSpecializationVisibilityChecker(Sema &S, SourceLocation Loc) + : S(S), Loc(Loc) {} void check(NamedDecl *ND) { if (auto *FD = dyn_cast<FunctionDecl>(ND)) @@ -11040,23 +11037,6 @@ private: S.diagnoseMissingImport(Loc, D, D->getLocation(), Modules, Kind, Recover); } - bool CheckMemberSpecialization(const NamedDecl *D) { - return Kind == Sema::AcceptableKind::Visible - ? S.hasVisibleMemberSpecialization(D) - : S.hasReachableMemberSpecialization(D); - } - - bool CheckExplicitSpecialization(const NamedDecl *D) { - return Kind == Sema::AcceptableKind::Visible - ? S.hasVisibleExplicitSpecialization(D) - : S.hasReachableExplicitSpecialization(D); - } - - bool CheckDeclaration(const NamedDecl *D) { - return Kind == Sema::AcceptableKind::Visible ? S.hasVisibleDeclaration(D) - : S.hasReachableDeclaration(D); - } - // Check a specific declaration. There are three problematic cases: // // 1) The declaration is an explicit specialization of a template @@ -11073,9 +11053,10 @@ private: void checkImpl(SpecDecl *Spec) { bool IsHiddenExplicitSpecialization = false; if (Spec->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { - IsHiddenExplicitSpecialization = Spec->getMemberSpecializationInfo() - ? !CheckMemberSpecialization(Spec) - : !CheckExplicitSpecialization(Spec); + IsHiddenExplicitSpecialization = + Spec->getMemberSpecializationInfo() + ? !S.hasVisibleMemberSpecialization(Spec, &Modules) + : !S.hasVisibleExplicitSpecialization(Spec, &Modules); } else { checkInstantiated(Spec); } @@ -11099,7 +11080,7 @@ private: checkTemplate(TD); else if (auto *TD = From.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) { - if (!CheckDeclaration(TD)) + if (!S.hasVisibleDeclaration(TD)) diagnose(TD, true); checkTemplate(TD); } @@ -11115,7 +11096,7 @@ private: checkTemplate(TD); else if (auto *TD = From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) { - if (!CheckDeclaration(TD)) + if (!S.hasVisibleDeclaration(TD)) diagnose(TD, true); checkTemplate(TD); } @@ -11126,7 +11107,7 @@ private: template<typename TemplDecl> void checkTemplate(TemplDecl *TD) { if (TD->isMemberSpecialization()) { - if (!CheckMemberSpecialization(TD)) + if (!S.hasVisibleMemberSpecialization(TD, &Modules)) diagnose(TD->getMostRecentDecl(), false); } } @@ -11137,17 +11118,5 @@ void Sema::checkSpecializationVisibility(SourceLocation Loc, NamedDecl *Spec) { if (!getLangOpts().Modules) return; - ExplicitSpecializationVisibilityChecker(*this, Loc, - Sema::AcceptableKind::Visible) - .check(Spec); -} - -void Sema::checkSpecializationReachability(SourceLocation Loc, - NamedDecl *Spec) { - if (!getLangOpts().CPlusPlusModules) - return checkSpecializationVisibility(Loc, Spec); - - ExplicitSpecializationVisibilityChecker(*this, Loc, - Sema::AcceptableKind::Reachable) - .check(Spec); + ExplicitSpecializationVisibilityChecker(*this, Loc).check(Spec); } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 3edce94..0015d6a 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -8642,8 +8642,17 @@ bool Sema::hasStructuralCompatLayout(Decl *D, Decl *Suggested) { return Ctx.IsEquivalent(D, Suggested); } -bool Sema::hasAcceptableDefinition(NamedDecl *D, NamedDecl **Suggested, - AcceptableKind Kind, bool OnlyNeedComplete) { +/// Determine whether there is any declaration of \p D that was ever a +/// definition (perhaps before module merging) and is currently visible. +/// \param D The definition of the entity. +/// \param Suggested Filled in with the declaration that should be made visible +/// in order to provide a definition of this entity. +/// \param OnlyNeedComplete If \c true, we only need the type to be complete, +/// not defined. This only matters for enums with a fixed underlying +/// type, since in all other cases, a type is complete if and only if it +/// is defined. +bool Sema::hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested, + bool OnlyNeedComplete) { // Easy case: if we don't have modules, all declarations are visible. if (!getLangOpts().Modules && !getLangOpts().ModulesLocalVisibility) return true; @@ -8687,14 +8696,13 @@ bool Sema::hasAcceptableDefinition(NamedDecl *D, NamedDecl **Suggested, VD = Pattern; D = VD->getDefinition(); } - assert(D && "missing definition for pattern of instantiated definition"); *Suggested = D; - auto DefinitionIsAcceptable = [&] { + auto DefinitionIsVisible = [&] { // The (primary) definition might be in a visible module. - if (isAcceptable(D, Kind)) + if (isVisible(D)) return true; // A visible module might have a merged definition instead. @@ -8712,51 +8720,19 @@ bool Sema::hasAcceptableDefinition(NamedDecl *D, NamedDecl **Suggested, return false; }; - if (DefinitionIsAcceptable()) + if (DefinitionIsVisible()) return true; // The external source may have additional definitions of this entity that are // visible, so complete the redeclaration chain now and ask again. if (auto *Source = Context.getExternalSource()) { Source->CompleteRedeclChain(D); - return DefinitionIsAcceptable(); + return DefinitionIsVisible(); } return false; } -/// Determine whether there is any declaration of \p D that was ever a -/// definition (perhaps before module merging) and is currently visible. -/// \param D The definition of the entity. -/// \param Suggested Filled in with the declaration that should be made visible -/// in order to provide a definition of this entity. -/// \param OnlyNeedComplete If \c true, we only need the type to be complete, -/// not defined. This only matters for enums with a fixed underlying -/// type, since in all other cases, a type is complete if and only if it -/// is defined. -bool Sema::hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested, - bool OnlyNeedComplete) { - return hasAcceptableDefinition(D, Suggested, Sema::AcceptableKind::Visible, - OnlyNeedComplete); -} - -/// Determine whether there is any declaration of \p D that was ever a -/// definition (perhaps before module merging) and is currently -/// reachable. -/// \param D The definition of the entity. -/// \param Suggested Filled in with the declaration that should be made -/// reachable -/// in order to provide a definition of this entity. -/// \param OnlyNeedComplete If \c true, we only need the type to be complete, -/// not defined. This only matters for enums with a fixed underlying -/// type, since in all other cases, a type is complete if and only if it -/// is defined. -bool Sema::hasReachableDefinition(NamedDecl *D, NamedDecl **Suggested, - bool OnlyNeedComplete) { - return hasAcceptableDefinition(D, Suggested, Sema::AcceptableKind::Reachable, - OnlyNeedComplete); -} - /// Locks in the inheritance model for the given class and all of its bases. static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) { RD = RD->getMostRecentNonInjectedDecl(); @@ -8826,19 +8802,20 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, // Check that any necessary explicit specializations are visible. For an // enum, we just need the declaration, so don't check this. if (Def && !isa<EnumDecl>(Def)) - checkSpecializationReachability(Loc, Def); + checkSpecializationVisibility(Loc, Def); // If we have a complete type, we're done. if (!Incomplete) { - NamedDecl *Suggested = nullptr; + // If we know about the definition but it is not visible, complain. + NamedDecl *SuggestedDef = nullptr; if (Def && - !hasReachableDefinition(Def, &Suggested, /*OnlyNeedComplete=*/true)) { + !hasVisibleDefinition(Def, &SuggestedDef, /*OnlyNeedComplete*/true)) { // If the user is going to see an error here, recover by making the // definition visible. bool TreatAsComplete = Diagnoser && !isSFINAEContext(); - if (Diagnoser && Suggested) - diagnoseMissingImport(Loc, Suggested, MissingImportKind::Definition, - /*Recover*/ TreatAsComplete); + if (Diagnoser && SuggestedDef) + diagnoseMissingImport(Loc, SuggestedDef, MissingImportKind::Definition, + /*Recover*/TreatAsComplete); return !TreatAsComplete; } else if (Def && !TemplateInstCallbacks.empty()) { CodeSynthesisContext TempInst; diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index b4506da..ae29855 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -605,27 +605,15 @@ void ASTDeclReader::VisitDecl(Decl *D) { D->setTopLevelDeclInObjCContainer(Record.readInt()); D->setAccess((AccessSpecifier)Record.readInt()); D->FromASTFile = true; - auto ModuleOwnership = (Decl::ModuleOwnershipKind)Record.readInt(); - bool ModulePrivate = - (ModuleOwnership == Decl::ModuleOwnershipKind::ModulePrivate); + bool ModulePrivate = Record.readInt(); // Determine whether this declaration is part of a (sub)module. If so, it // may not yet be visible. if (unsigned SubmoduleID = readSubmoduleID()) { - - switch (ModuleOwnership) { - case Decl::ModuleOwnershipKind::Visible: - ModuleOwnership = Decl::ModuleOwnershipKind::VisibleWhenImported; - break; - case Decl::ModuleOwnershipKind::Unowned: - case Decl::ModuleOwnershipKind::VisibleWhenImported: - case Decl::ModuleOwnershipKind::ReachableWhenImported: - case Decl::ModuleOwnershipKind::ModulePrivate: - break; - } - - D->setModuleOwnershipKind(ModuleOwnership); // Store the owning submodule ID in the declaration. + D->setModuleOwnershipKind( + ModulePrivate ? Decl::ModuleOwnershipKind::ModulePrivate + : Decl::ModuleOwnershipKind::VisibleWhenImported); D->setOwningModuleID(SubmoduleID); if (ModulePrivate) { diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 01f692c..3666d5a 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -311,7 +311,7 @@ void ASTDeclWriter::VisitDecl(Decl *D) { Record.push_back(D->isReferenced()); Record.push_back(D->isTopLevelDeclInObjCContainer()); Record.push_back(D->getAccess()); - Record.push_back((uint64_t)D->getModuleOwnershipKind()); + Record.push_back(D->isModulePrivate()); Record.push_back(Writer.getSubmoduleID(D->getOwningModule())); // If this declaration injected a name into a context different from its @@ -1928,7 +1928,7 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // isReferenced Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // AccessSpecifier - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // ModuleOwnershipKind + Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier @@ -1961,7 +1961,7 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // isReferenced Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // AccessSpecifier - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // ModuleOwnershipKind + Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier @@ -1999,7 +1999,7 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // isReferenced Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // ModuleOwnershipKind + Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier @@ -2049,7 +2049,7 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // isReferenced Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // ModuleOwnershipKind + Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier @@ -2111,7 +2111,7 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // isReferenced Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // ModuleOwnershipKind + Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier @@ -2159,7 +2159,7 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isReferenced Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // C++ AccessSpecifier - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // ModuleOwnershipKind + Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier @@ -2188,7 +2188,7 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // isReferenced Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // ModuleOwnershipKind + Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier @@ -2240,7 +2240,7 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Referenced Abv->Add(BitCodeAbbrevOp(0)); // InObjCContainer Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Access - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // ModuleOwnershipKind + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ModulePrivate Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl Abv->Add(BitCodeAbbrevOp(DeclarationName::Identifier)); // NameKind |