Hi all,
I am wondering if there is a way to remove existing explicit class template specialization declaration? I cannot remove it like Decl->getDeclContext()->removeDecl(Decl)..
I know that in ClassTemplateDecl there is addSpecialization() and no removeSpecialization(). Is it complex to implement removeSpecialization()?
Cheers,
Vassil
It is *extremely* complex to remove a specialization, since you would have to walk the entire AST to determine if anything in the AST references the specialization.
- Doug
Hi,
Yes, but in my case I know that nothing depends on the specific specialization (I inject one artificially, analyze the output, get what I need and I want to remove it). If I try to remove it like with DeclContext I end up with assert. It is not possible to remove it simply from the Scope (like I do with the when I create implicit function for the failed sema lookups (Sema::ImplicitlyDefineFunction()))
Cheers,
Vassil
Hi,
Yes, but in my case I know that nothing depends on the specific specialization (I inject one artificially, analyze the output, get what I need and I want to remove it).
Injecting a specialization can cause a cascade of instantiations, some of which can refer back to that specialization. For example, you could end up instantiating a static data member of some other class template specialization that refers to a member of the specialization you injected.
If I try to remove it like with DeclContext I end up with assert. It is not possible to remove it simply from the Scope (like I do with the when I create implicit function for the failed sema lookups (Sema::ImplicitlyDefineFunction()))
The Clang AST does not offer removal of nodes because it is extremely complicated to undo the effects of the addition of a node.
- Doug
Hi,
Yes, but in my case I know that nothing depends on the specific specialization (I inject one artificially, analyze the output, get what I need and I want to remove it).Injecting a specialization can cause a cascade of instantiations, some of which can refer back to that specialization. For example, you could end up instantiating a static data member of some other class template specialization that refers to a member of the specialization you injected.
I agree, but as I said nothing depends on the injected templated class and its explicit specialization in my case.
If I try to remove it like with DeclContext I end up with assert. It is not possible to remove it simply from the Scope (like I do with the when I create implicit function for the failed sema lookups (Sema::ImplicitlyDefineFunction()))
The Clang AST does not offer removal of nodes because it is extremely complicated to undo the effects of the addition of a node.
Yes I agree that dependency analysis upon c++ semantic tree is far away from trivial. However, there is one thing that I don't get isn't there clang::DeclContext::removeDecl(clang::Decl), which is public interface that removes decls from given DeclContext? I think you use it for shadow declarations in one place... (I am writing by hard but: Shadow->getDeclContext()->removeDecl(Shadow))
I am curious do you plan to implement removing arbitrary nodes from the AST at some point? One can argue that if someone wants to delete a node it should be possible, but it's his responsibility to preserve semantics.
Or it'd be great if a node is removed and the AST to transform itself into semantically valid new AST.
Hi,
Yes, but in my case I know that nothing depends on the specific specialization (I inject one artificially, analyze the output, get what I need and I want to remove it).Injecting a specialization can cause a cascade of instantiations, some of which can refer back to that specialization. For example, you could end up instantiating a static data member of some other class template specialization that refers to a member of the specialization you injected.
I agree, but as I said nothing depends on the injected templated class and its explicit specialization in my case.
Then you have defined what goes into that class template in a *very* narrow way, that doesn't permit it to trigger any other instantiations that might capture or reproduce the specialization. That basically means that it doesn't interact with any of the other code in the translation unit that you don't control, e.g., it doesn't call a function that might be a function template.
If I try to remove it like with DeclContext I end up with assert. It is not possible to remove it simply from the Scope (like I do with the when I create implicit function for the failed sema lookups (Sema::ImplicitlyDefineFunction()))
The Clang AST does not offer removal of nodes because it is extremely complicated to undo the effects of the addition of a node.
Yes I agree that dependency analysis upon c++ semantic tree is far away from trivial. However, there is one thing that I don't get isn't there clang::DeclContext::removeDecl(clang::Decl), which is public interface that removes decls from given DeclContext? I think you use it for shadow declarations in one place... (I am writing by hard but: Shadow->getDeclContext()->removeDecl(Shadow))
Frankly, I'd rather that DeclContext::removeDecl() go away. It's meant to support a very narrow use case with using declarations, and Sema handle things correctly, but it's really messy.
I am curious do you plan to implement removing arbitrary nodes from the AST at some point?
We have no plans to do implement this.
- Doug
Hi,
Hi,
Yes, but in my case I know that nothing depends on the specific specialization (I inject one artificially, analyze the output, get what I need and I want to remove it).Injecting a specialization can cause a cascade of instantiations, some of which can refer back to that specialization. For example, you could end up instantiating a static data member of some other class template specialization that refers to a member of the specialization you injected.
I agree, but as I said nothing depends on the injected templated class and its explicit specialization in my case.
Then you have defined what goes into that class template in a *very* narrow way, that doesn't permit it to trigger any other instantiations that might capture or reproduce the specialization. That basically means that it doesn't interact with any of the other code in the translation unit that you don't control, e.g., it doesn't call a function that might be a function template.
Yes that is correct. As a matter of fact we use it to get the QualType from clang. Suppose that we need to get the clang type of a given type (let's say clang::DeclContext). The idea we had is constructing a string: template <typename T> class dummy{}; template <> class dummy<clang::DeclContext*>{}; After that we compile to get the TopLevelDeclaration of that and we ask what is the type of the explicit template specialization parameter. This is much easier than constructing fake Token, Identifier, DeclarationName, DeclarationSpec, etc. and perform the lookup...
So after we get the QualType of the specialization parameter will be much better to remove these things, because they are redundant.
It works just fine now because we are using unique class names every time, but I'd like to have something more clear... Then we can move the templated class declaration into the interpreter's runtime universe and create only specialization, when it is needed.
If I try to remove it like with DeclContext I end up with assert. It is not possible to remove it simply from the Scope (like I do with the when I create implicit function for the failed sema lookups (Sema::ImplicitlyDefineFunction()))
The Clang AST does not offer removal of nodes because it is extremely complicated to undo the effects of the addition of a node.
Yes I agree that dependency analysis upon c++ semantic tree is far away from trivial. However, there is one thing that I don't get isn't there clang::DeclContext::removeDecl(clang::Decl), which is public interface that removes decls from given DeclContext? I think you use it for shadow declarations in one place... (I am writing by hard but: Shadow->getDeclContext()->removeDecl(Shadow))
Frankly, I'd rather that DeclContext::removeDecl() go away. It's meant to support a very narrow use case with using declarations, and Sema handle things correctly, but it's really messy.
Yes I have to admit it is a bit misleading :). Is this valid for Scope::RemoveDecl(), as well? Is there any overlap between the Scope::RemoveDecl and DeclContext::removeDecl and what is the difference?
Cheers,
Vassil