[cfe-dev] local submodule visibility, namespaces and Decl::getOwningModule()

Adrian Prantl via cfe-dev cfe-dev at lists.llvm.org
Tue Oct 23 17:29:33 PDT 2018

> On Oct 23, 2018, at 5:10 PM, Richard Smith <richard at metafoo.co.uk> wrote:
> On Mon, 15 Oct 2018 at 10:13, Adrian Prantl via cfe-dev <cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org>> wrote:
> I'm trying to fix a bug in the -gmodules debug info that appears when debugging Clang with local submodule visibility enabled. In my reduced testcase, I have a module A, defining a template "AlignedCharArray<unsigned, unsigned>", and two templates "SmallVector" and "Optional" that use it. In module B, I'm instantiating an Optional that instantiates an AlignedCharArray<4, 16>. In module C, I'm instantiating a SmallVector that also instantiates an AlignedCharArray<4, 16>.
> The -gmodules debug info format saves space by forward-declaring types that are defined in an already-imported module and specify which module they came from. To point to the module of the definition CGDebugInfo::getParentModuleOrNull(const Decl *D) uses Decl::getOwningModule(). This mechanism works as expected, but only if the TemplateDecl is not inside a namespace.
> When compiling the attached testcase with -U WITH_NAMESPACE, the owning module for the ClassTemplateSpecializationDecl (of AlignedCharArray<4, 16>) in module B is C. (B imports C, so the C specialization is instantiated first).
> When compiling the attached testcase with -D WITH_NAMESPACE, the owning module for the ClassTemplateSpecializationDecl (of AlignedCharArray<4, 16>) in module B is A. (A is where the TemplateDecl that is being specialized comes from).
> I'm sure that this discrepancy must be because a namespace can be spread out over many modules.
> Sort of. In practice, what's happening is this:
> When we create a declaration, we inherit its owning module from its lexical parent by default. And we ensure that the lexical parent of the TU declaration corresponds to the module we're currently "in". When a declaration is injected into a lexical declaration context from a different module, such as happens when adding a template specialization to an imported template, that default behavior will pick up the current module at global scope, but will pick up the owning module of the enclosing namespace declaration at namespace scope, which will be the owning module of whichever declaration of the template we picked. Now, this usually doesn't matter, because a template specialization doesn't really *have* a meaningful notion of "owning module". For visibility purposes, the specialization should be visible wherever the corresponding template is visible, and for linkage purposes, it should be considered owned by the same module as the template pattern. So in some sense the bug is in the global-scope case: we should always treat the specialization as being owned by module A.
> I think there's a chance that you're asking the wrong question -- perhaps you should be trying to determine whether the declaration in question is imported from a module *file*, not what its semantic owning module is. (As an example, suppose we're tracking module ownership but not using PCM files. If we textually enter a modular header of some other module, I think you want to *not* treat declarations in that header as being owned by a module for the purpose of -gmodules, because there is no reason to think there's separate debug information for that header.) You can figure that out by calling Decl::isFromASTFile(), and if you want to know *which* AST file the declaration comes from (because you know that some AST files have debug information and some don't), you can use ASTReader::getOwningModuleFile to find out.

Thanks for the pointer! That interface sounds promising; I will try to expose it as a

   virtual ASTSourceDescriptor getOwningModuleFile(Decl *);

in ExternalASTSource and see if that gets me further.

-- adrian

> I can "fix" my issue by always emitting full debug info definitions for template specializations inside of namespaces. But I'm also really curious whether the behavior I'm experiencing is indicative of a general bug/shortcoming of the LSV implementation that we might be interested in fixing. The owning module of each declaration is set to the owning module of its DeclContext and namespaces seem to interfere with this mechanism. 
> thanks,
> Adrian
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org>
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev <http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20181023/8d492a27/attachment.html>

More information about the cfe-dev mailing list