<html>
<head></head>
<body>
<p>Hi,</p>
<p>Well, I'm going to rewind and try to give as much information of the problem as possible to clarify it to everyone.</p>
<p>My intention is the next: I want to retrieve the default constructor of a class (not trivial if possible) and then to delete it so that the compiler provides one. For this purpose, I need to verify that the class that default constructor belongs to, doesn't have any other constructors (with at least another constructor, the compiler doesn't provide the default constructor).</p>
<p>So, I created the next matcher:</p>
<p>DeclarationMatcher DefaultConstructorMatcher =<br /> recordDecl(<br /> unless(hasMethod(constructorDecl(<br /> allOf(hasAnyParameter(anything()), unless(isImplicit()))))),<br /> hasMethod(constructorDecl(isDefinition(), parameterCountIs(0),<br /> anyOf(hasAnyConstructorInitializer(isWritten()), has(compoundStmt(has(stmt()))))).bind("default_constructor"))<br /> ).bind("class_default_constructor");</p>
<p>The first part helps me to discard classes with a constructor different from the default constructor and the second part gives me the default constructor I'm looking for. </p>
<p>(Note: I put "unless(isImplicit())" to avoid other implicit constructors provides by the compiler)</p>
<p>Then, I can do:</p>
<p> if (Result.Nodes.getNodeAs<clang::CXXRecordDecl>("class_default_constructor"))<br /> const CXXConstructorDecl *FS = Result.Nodes.getNodeAs<clang::CXXConstructorDecl>("default_constructor");</p>
<p>The problem now is:</p>
<p>- Case 1:<br/>
class E{<br /> public:<br /> E(){int a = 3;}; <br /> int e;<br />};</p>
<p>Constructor E() is retrieved.</p>
<p>- Case 2: <br/>
class E{<br /> public:<br /> E(); <br /> int e;<br />};</p>
<p>E::E(){<br /> int a = 3;<br />}</p>
<p>Constructor E() is not retrieved. I think the problem is that there are two CXXConstructors in the AST, I suppose one for the declaration and the other for the definition:</p>
<p><CXXConstructor ptr="0xc7de070" name="E" prototype="true"><br /> <FunctionProtoType ptr="0xc7de040" canonical="0xc7de040"><br /> <BuiltinType ptr="0xc7ddc30" canonical="0xc7ddc30"/><br /> <parameters/><br /> </FunctionProtoType><br /> </CXXConstructor></p>
<p>....</p>
<p><CXXConstructor used="1" ptr="0xc7de270" name="E" previous="0xc7de070" prototype="true"><br /> <FunctionProtoType ptr="0xc7de040" canonical="0xc7de040"><br /> <BuiltinType ptr="0xc7ddc30" canonical="0xc7ddc30"/><br /> <parameters/><br /> </FunctionProtoType><br /> <Stmt><br />CompoundStmt 0xc7de378 <./ABC.h:8:7, line:10:1><br />`-DeclStmt 0xc7de368 <line:9:2, col:11><br /> `-VarDecl 0xc7de320 <col:2, col:10> a 'int'<br /> `-IntegerLiteral 0xc7de350 <col:10> 'int' 3<br /><br /> </Stmt><br /> </CXXConstructor></p>
<br/>
<p>With all this information everyone could test that this is true. Now, responding your message:</p>
<blockquote class="replyBlock" style="border-left: 2px solid #000083; margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><div>> <em>Did you mean "clang::Redeclarable< decl_type >" class?</em></div><div><em><br /></em></div><div>Yes.<em><br /></em></div></blockquote><p>I've been looking for a solution with this, but I definitively have no idea what can I do with it.</p>
<blockquote class="replyBlock" style="border-left: 2px solid #000083; margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><div>> <em>I think your suggestion might be useful to me, so that the second declaration is not taken into account</em></div><div><em><br /></em></div><div>Yes, that is the idea.<em><br /></em></div></blockquote><p>Yes, but I need this only for the first part of the matcher, not for the second part as I need to determine whether the constructor is trivial or not.</p>
<blockquote class="replyBlock" style="border-left: 2px solid #000083; margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><div>> <em>the matcher you are suggesting is previous to this or is included in the same matcher I'm trying to build?</em></div><div><em><br /></em></div><p>I don't understand what you mean.</p>
</blockquote><p>What I was asking was whether I needed to change my matcher "DefaultConstructorMatcher" to do what you proposed or I had to create a new one to act before my matcher.</p>
<p>Thanks for your concern,</p>
<p>Pedro.</p>
<br/>
<br/>
<div><em>El dia 10 jun 2013 00:50, Gábor Kozár <kozargabor@gmail.com> escribió:</em></div><blockquote class="replyBlock" style="border-left: 2px solid #000083; margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><div dir="ltr"><div>Hi,</div><div>I reread your previous e-mail, and I do not know why your matcher is not working as intended in the example - I cannot find any problems with it. Did you try filtering out the methods that have been declared before, to see whether the E(); line or the E::E() line causes the matcher to fail?</div><div>> <em>Did you mean "clang::Redeclarable< decl_type >" class?</em></div><div><em><br /></em></div><div>Yes.<em><br /></em></div><div>> <em>I think your suggestion might be useful to me, so that the second declaration is not taken into account</em></div><div><em><br /></em></div><div>Yes, that is the idea.<em><br /></em></div><div>> <em>but I can't still understand why the matcher is doing that if the second declaration doesn't fit that matcher's conditions.</em></div><div><em><br /></em></div><div>Me neither, it appears that we're missing something.<em><br /></em></div><div>> <em>the matcher you are suggesting is previous to this or is included in the same matcher I'm trying to build?</em></div><div><em><br /></em></div><div>I don't understand what you mean.<em><br /></em></div><div>Gabor</div></div><div class="gmail_extra"><br /><br /><div class="gmail_quote">2013/5/31 Pedro Delgado Perez <span dir="ltr"><<a href="mailto:pedro.delgado@uca.es" target="_blank">pedro.delgado@uca.es</a>></span><br /><blockquote class="gmail_quote" style="margin: 0 0 0 .8ex; border-left: 1px #ccc solid; padding-left: 1ex;"><div><p>Did you mean "clang::Redeclarable< decl_type >" class? I think your suggestion might be useful to me, so that the second declaration is not taken into account, but I can't still understand why the matcher is doing that if the second declaration doesn't fit that matcher's conditions.</p>
<p>I will look into this, but the matcher you are suggesting is previous to this or is included in the same matcher I'm trying to build?</p>
<p>Thanks,</p>
<p>Pedro.</p>
<div><em>El dia 30 may 2013 21:36, Gábor Kozár <<a href="mailto:kozargabor@gmail.com" target="_blank">kozargabor@gmail.com</a>> escribió:</em></div><div><div class="h5"><blockquote style="border-left: 2px solid #000083; margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><div dir="ltr"><div>Well, try filtering out declarations that are not first declarations - it looks to me that would solve your issue.</div><div>I think you'll need to create a new matcher for this. In fact, this might be useful to implement generally and contribute to Clang. I believe there is a base class for redeclarable AST nodes, but can't remember the exact name - you should use that for your matcher.</div></div><div class="gmail_extra"><br /><br /><div class="gmail_quote">2013/5/30 Pedro Delgado Perez <span dir="ltr"><<a href="mailto:pedro.delgado@uca.es" target="_blank">pedro.delgado@uca.es</a>></span><br /><blockquote class="gmail_quote" style="margin: 0 0 0 .8ex; border-left: 1px #ccc solid; padding-left: 1ex;"><div><p>Hi,</p>
<div><blockquote style="border-left: 2px solid #000083; margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><p>Default, copy, and move constructors are provided implicitly (under various conditions - obviously if you have members that aren't default, copy, or move constructible, you might not/cannot get all of those) </p>
</blockquote></div><p>Ok, but this keeps giving me trouble. I've used the isImplicit() matcher to avoid those implicit constructors, but it isn't working how I need yet.</p>
<p>recordDecl(<br /> unless(hasMethod(constructorDecl(<br /> allOf(hasAnyParameter(anything()), unless(isImplicit()))</p>
<p>I know I shouldn't use the -ast-dump-xml option, but look at this. If I have a class like this:</p>
<p>class E{<br /> public:<br /> E(){int a = 3;}; <br /> int e;<br />};</p>
<p>This is the dump of the constructor:</p>
<p><CXXConstructor used="1" ptr="0xd7d8070" name="E" prototype="true"><br /> <FunctionProtoType ptr="0xd7d8040" canonical="0xd7d8040"><br /> <BuiltinType ptr="0xd7d7c30" canonical="0xd7d7c30"/><br /> <parameters/><br /> </FunctionProtoType><br /> <Stmt><br />CompoundStmt 0xd7d81a8 <./ABC.h:4:6, col:17><br />`-DeclStmt 0xd7d8198 <col:7, col:16><br /> `-VarDecl 0xd7d8150 <col:7, col:15> a 'int'<br /> `-IntegerLiteral 0xd7d8180 <col:15> 'int' 3<br /><br /> </Stmt><br /> </CXXConstructor></p>
<p>And this case is working fine. But when the class is this other way:</p>
<p>class E{<br /> public:<br /> E(); <br /> int e;<br />};</p>
<p>E::E(){<br /> int a = 3;<br />}</p>
<p>The dump creates two CXXConstructors, I suppose one for the declaration and the other for the definition:</p>
<p><CXXConstructor ptr="0xc7de070" name="E" prototype="true"><br /> <FunctionProtoType ptr="0xc7de040" canonical="0xc7de040"><br /> <BuiltinType ptr="0xc7ddc30" canonical="0xc7ddc30"/><br /> <parameters/><br /> </FunctionProtoType><br /> </CXXConstructor></p>
<p>....</p>
<p><CXXConstructor used="1" ptr="0xc7de270" name="E" previous="0xc7de070" prototype="true"><br /> <FunctionProtoType ptr="0xc7de040" canonical="0xc7de040"><br /> <BuiltinType ptr="0xc7ddc30" canonical="0xc7ddc30"/><br /> <parameters/><br /> </FunctionProtoType><br /> <Stmt><br />CompoundStmt 0xc7de378 <./ABC.h:8:7, line:10:1><br />`-DeclStmt 0xc7de368 <line:9:2, col:11><br /> `-VarDecl 0xc7de320 <col:2, col:10> a 'int'<br /> `-IntegerLiteral 0xc7de350 <col:10> 'int' 3<br /><br /> </Stmt><br /> </CXXConstructor></p>
<br/>
<p>And this is the case my matcher is not retrieving the class E. I don't know if clang it's considering that first CxxConstructor as implicit... The only difference I can see is the "used" attribute. I've tried creating a simple matcher to use the isUsed() method of Decl class:</p>
<p>namespace clang{ <br /> namespace ast_matchers{ <br /> AST_MATCHER(Decl, isUsed) <br /> { <br /> return Node.isUsed(); <br /> } <br /> } <br />}</p>
<p>but, this is having no influence.</p>
<p>Maybe, I'm ignoring something.</p>
<p>Thanks,</p>
<p>Pedro.</p>
<br/>
<br/>
<br/>
<div><em>El dia 28 may 2013 18:18, David Blaikie <<a href="mailto:dblaikie@gmail.com" target="_blank">dblaikie@gmail.com</a>> escribió:</em></div><div><div><blockquote style="border-left: 2px solid #000083; margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><div dir="ltr"><br /><div class="gmail_extra"><br /><br /></div></div></blockquote><div dir="ltr"><div class="gmail_extra"><blockquote style="border-left: 2px solid #000083; margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><div class="gmail_quote">On Tue, May 28, 2013 at 2:07 AM, Pedro Delgado Perez <span dir="ltr"><<a href="mailto:pedro.delgado@uca.es" target="_blank">pedro.delgado@uca.es</a>></span> wrote:<br /><div><div><p>That seems like an approach that works. I don't know that there's a different common property. Why's the default constructor different from the copy constructor here?</p>
</div><p>First of all, sorry but I made a mistake in the example:</p>
<br/>
<br/>
<div>class A{<br />1. A(){...}<br />2. A(int a){...}</div><p>3. <strong>A(const A& a){... ...}</strong><br />};</p>
<br/>
<p>What I mean is that I need to find if there is at least one constructor that explicitly overloads the default constructor so that if I delete the default constructor the compiler won't provide the default constructor. So, my question was totally erroneous as the copy constructor does overload the default constructor if provided, but I don't want to take it into account if it wasn't explicitly provided.</p>
<p>A better question is: which are the kind of constructors that the compiler provides if no constructors are explicitly supplied? Only the default and the copy constructor (in some situations)?</p>
</div><div>Default, copy, and move constructors are provided implicitly (under various conditions - obviously if you have members that aren't default, copy, or move constructible, you might not/cannot get all of those) </div><div><p>If "unless(allOf(... ...))" is the best solution, could someone enumerate the kind of constructors I must to indicate in that matcher?</p>
<div><p>I'd suggest to not use ast-dump-xml any more. It's basically deprecated, and hopefully it'll be removed soon. -ast-dump gives you all the information (and more).</p>
</div><p>Ok, I didn't know it.</p>
<div><p>... you can see that one is the default constructor and the other one is the copy constructor. If you just put "G g;" into the code instead of the second class, you'll also see that a simple use of G already triggers the copy constructor to appear. Others are probably better able to explain exactly when a copy constructor is created.</p>
</div><p>Further information will be well received.</p>
<p>Regards,</p>
<p>Pedro.</p>
<div><em>El dia 27 may 2013 12:24, Manuel Klimek <<a href="mailto:klimek@google.com" target="_blank">klimek@google.com</a>> escribió:</em></div><div><div><div dir="ltr">Hi Pedro,<div>first, please always send those mails also to cfe-dev. There are people who are much more knowledgable about the AST on that list, and you'll often get better answers faster that way :)</div><div class="gmail_extra">On Mon, May 27, 2013 at 10:00 AM, Pedro Delgado Perez <span dir="ltr"><<a href="mailto:pedro.delgado@uca.es" target="_blank">pedro.delgado@uca.es</a>></span> wrote:<br /><div class="gmail_quote"><div><p>Sorry Manuel, but I prefer to ask you all the things I don't know before you reply me:</p>
<p>How do I know that a CXXConstructorDecl is a "simple" constructor of a class. I mean, I want to find all the constructors in a class, but not the copy, the move or things like this constructors. I'm not able to find this in the documentation. To clarify this, I'm going to put an example:</p>
<p>class A{<br />1. A(){...}<br />2. A(int a){...}<br />3. A(const &a){... ...}<br />};</p>
<p>I want to look only for 1 and 2 and not for 3 when I ask:<br />recordDecl(hasMethod(constructDecl(...)));</p>
<p>What can I do? Do I have to write "unless(allOf(isCopyConstructor(), isMoveConstructor()...))" for each type of existing constructors?</p>
</div><div>That seems like an approach that works. I don't know that there's a different common property. Why's the default constructor different from the copy constructor here?</div><div> </div><div><p>Thanks,</p>
<p>Pedro.</p>
<br/>
<br/>
<br/>
<p>Hi Manuel,</p>
<p>I would like to ask you something about the AST built by Clang if you don't mind. I've just have a look at your video of introduction to Clang AST (By the way, nice tutorial!) and I think that you may have an answer for my trouble.</p>
<p>Look, I was trying to look for classes that had only the default constructor through ASTMatchers. Well, I tested my matcher with the next classes:</p>
<p>class G{<br />public:<br /> G():a(1){}<br /> int a;<br /> virtual int ma(int arg);<br />};</p>
<p>class L: <strong>public G</strong>{<br /> public:<br /> L(){v = 1;}<br /> int b;<br /> int h;<br /> virtual int ma(int arg);<br /> private:<br /> int v;<br /> int f();<br />};</p>
<p>My matcher only retrieved the class 'L' and not the 'G'. I was wondering what would be the problem when I had a look to the ast-dump-xml option:</p>
</div><div>I'd suggest to not use ast-dump-xml any more. It's basically deprecated, and hopefully it'll be removed soon. -ast-dump gives you all the information (and more).</div><div><p> <CXXRecord ptr="0xd695f30" name="G" typeptr="0xd695f80"><br /> <CXXRecord ptr="0xd695fd0" name="G" typeptr="0xd695f80"/><br /> <AccessSpec ptr="0xd696020" access="public"/><br /> <strong><CXXConstructor</strong> used="1" ptr="0xd696080" name="G" prototype="true"><br /> <FunctionProtoType ptr="0xd696050" canonical="0xd696050"><br /> <BuiltinType ptr="0xd695c40" canonical="0xd695c40"/><br /> <parameters/><br /> </FunctionProtoType><br /> <Stmt><br />CompoundStmt 0xd696450 <tst.cpp:7:10, col:11><br /> </Stmt><br /> </CXXConstructor></p>
<p>....</p>
<p><strong><CXXConstructor</strong> ptr="0xd6aefc0" name="G" prototype="true" inline="true"><br /> <FunctionProtoType ptr="0xd6af050" canonical="0xd6af030" exception_spec="unevaluated"><br /> <BuiltinType ptr="0xd695c40" canonical="0xd695c40"/><br /> <parameters><br /> <LValueReferenceType ptr="0xd696240" canonical="0xd696240"><br /> <QualType const="true"><br /> <RecordType ptr="0xd695f80" canonical="0xd695f80"><br /> <CXXRecord ref="0xd695f30"/><br /> </RecordType><br /> </QualType><br /> </LValueReferenceType><br /> </parameters><br /> </FunctionProtoType><br /> <ParmVar ptr="0xd6af070" name="" initstyle="c"><br /> <LValueReferenceType ptr="0xd696240" canonical="0xd696240"><br /> <QualType const="true"><br /> <RecordType ptr="0xd695f80" canonical="0xd695f80"><br /> <CXXRecord ref="0xd695f30"/><br /> </RecordType><br /> </QualType><br /> </LValueReferenceType><br /> </ParmVar><br /> </CXXConstructor><br /> </CXXRecord></p>
<br/>
<p>Why class 'G' has two constructors? If I change the test program in order that class 'L' doesn't inherits from class 'G', this doesn't happen (class 'G' only has one constructor in the ast-dump-xml) Could you lend me a hand?</p>
</div><div>If you look at -ast-dump:</div><div><div>$ clang -cc1 -ast-dump t4.cc</div><div><snip></div><div>|-CXXRecordDecl 0x37faf80 <t4.cc:1:1, line:6:1> class G</div><div><snip></div><div>| |-CXXConstructorDecl 0x37fb1c0 <line:3:3, col:15> G 'void (void)'</div><div>| | |-CXXCtorInitializer Field 0x37fb290 'a' 'int'</div><div>| | | |-IntegerLiteral 0x382d018 <col:11> 'int' 1</div><div>| | `-CompoundStmt 0x382d0a0 <col:14, col:15></div><div><snip></div><div>| `-CXXConstructorDecl 0x382da70 <col:7> G 'void (const class G &)' inline</div><div>| `-ParmVarDecl 0x382f820 <col:7> 'const class G &'</div><div><snip></div><div>... you can see that one is the default constructor and the other one is the copy constructor. If you just put "G g;" into the code instead of the second class, you'll also see that a simple use of G already triggers the copy constructor to appear. Others are probably better able to explain exactly when a copy constructor is created.</div><div>cheers,</div><div>/Manuel</div></div></div></div></div></div></div></div><br/>
<p>_______________________________________________<br />cfe-dev mailing list<br /><a href="mailto:cfe-dev@cs.uiuc.edu" target="_blank">cfe-dev@cs.uiuc.edu</a></p>
</div></blockquote></div></div><blockquote style="border-left: 2px solid #000083; margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><p><a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev</a></p>
</blockquote></div></div></div><br/>
<p>_______________________________________________<br />cfe-dev mailing list<br /><a href="mailto:cfe-dev@cs.uiuc.edu" target="_blank">cfe-dev@cs.uiuc.edu</a></p>
</blockquote></div></div><p><a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev</a></p>
</blockquote></div></div></div></blockquote></div><br/>
</div></blockquote>
</body>
</html>