dblaikie added inline comments.

================
Comment at: clang/bindings/python/clang/cindex.py:1530
+
+    def record_needs_implicit_default_constructor(self):
+        """Returns True if the cursor refers to a C++ record declaration
----------------
aaron.ballman wrote:
> anderslanglands wrote:
> > dblaikie wrote:
> > > aaron.ballman wrote:
> > > > dblaikie wrote:
> > > > > anderslanglands wrote:
> > > > > > dblaikie wrote:
> > > > > > > royjacobson wrote:
> > > > > > > > anderslanglands wrote:
> > > > > > > > > dblaikie wrote:
> > > > > > > > > > aaron.ballman wrote:
> > > > > > > > > > > dblaikie wrote:
> > > > > > > > > > > > anderslanglands wrote:
> > > > > > > > > > > > > dblaikie wrote:
> > > > > > > > > > > > > > aaron.ballman wrote:
> > > > > > > > > > > > > > > royjacobson wrote:
> > > > > > > > > > > > > > > > anderslanglands wrote:
> > > > > > > > > > > > > > > > > royjacobson wrote:
> > > > > > > > > > > > > > > > > > anderslanglands wrote:
> > > > > > > > > > > > > > > > > > > royjacobson wrote:
> > > > > > > > > > > > > > > > > > > > aaron.ballman wrote:
> > > > > > > > > > > > > > > > > > > > > aaron.ballman wrote:
> > > > > > > > > > > > > > > > > > > > > > I don't think we should expose any 
> > > > > > > > > > > > > > > > > > > > > > of the "needs" functions like this 
> > > > > > > > > > > > > > > > > > > > > > -- those are internal 
> > > > > > > > > > > > > > > > > > > > > > implementation details of the class 
> > > > > > > > > > > > > > > > > > > > > > and I don't think we want to 
> > > > > > > > > > > > > > > > > > > > > > calcify that into something we have 
> > > > > > > > > > > > > > > > > > > > > > to support forever. As we add 
> > > > > > > > > > > > > > > > > > > > > > members to a class, we recalculate 
> > > > > > > > > > > > > > > > > > > > > > whether the added member causes us 
> > > > > > > > > > > > > > > > > > > > > > to delete defaulted special members 
> > > > > > > > > > > > > > > > > > > > > > (among other things), and the 
> > > > > > > > > > > > > > > > > > > > > > "needs" functions are basically 
> > > > > > > > > > > > > > > > > > > > > > used when the class is completed to 
> > > > > > > > > > > > > > > > > > > > > > handle lazily created special 
> > > > > > > > > > > > > > > > > > > > > > members. I'm pretty sure that lazy 
> > > > > > > > > > > > > > > > > > > > > > creation is not mandated by the 
> > > > > > > > > > > > > > > > > > > > > > standard, which is why I think the 
> > > > > > > > > > > > > > > > > > > > > > "needs" functions are more of an 
> > > > > > > > > > > > > > > > > > > > > > implementation detail.
> > > > > > > > > > > > > > > > > > > > > CC @erichkeane and @royjacobson as 
> > > > > > > > > > > > > > > > > > > > > folks who have been in this same area 
> > > > > > > > > > > > > > > > > > > > > of the compiler to see if they agree 
> > > > > > > > > > > > > > > > > > > > > or disagree with my assessment there.
> > > > > > > > > > > > > > > > > > > > I think so. The 'needs_*' functions 
> > > > > > > > > > > > > > > > > > > > query `DeclaredSpecialMembers` and I'm 
> > > > > > > > > > > > > > > > > > > > pretty sure it's modified when we add 
> > > > > > > > > > > > > > > > > > > > the implicit definitions in the class 
> > > > > > > > > > > > > > > > > > > > completion code. So this looks a bit 
> > > > > > > > > > > > > > > > > > > > suspicious. Is this API //meant// to be 
> > > > > > > > > > > > > > > > > > > > used with incomplete classes?
> > > > > > > > > > > > > > > > > > > > For complete classes I think looking up 
> > > > > > > > > > > > > > > > > > > > the default/move/copy constructor and 
> > > > > > > > > > > > > > > > > > > > calling `isImplicit()` is the way to do 
> > > > > > > > > > > > > > > > > > > > it.
> > > > > > > > > > > > > > > > > > > > 
> > > > > > > > > > > > > > > > > > > > About the 'is deleted' API - can't the 
> > > > > > > > > > > > > > > > > > > > same be done for those functions as 
> > > > > > > > > > > > > > > > > > > > well so we have a smaller API? 
> > > > > > > > > > > > > > > > > > > > 
> > > > > > > > > > > > > > > > > > > > If this //is// meant to be used with 
> > > > > > > > > > > > > > > > > > > > incomplete classes for efficiency that 
> > > > > > > > > > > > > > > > > > > > would be another thing, I guess.
> > > > > > > > > > > > > > > > > > > > 
> > > > > > > > > > > > > > > > > > > So the intended use case here is I'm 
> > > > > > > > > > > > > > > > > > > using libclang to parse an existing C++ 
> > > > > > > > > > > > > > > > > > > libray's headers and generate a C 
> > > > > > > > > > > > > > > > > > > interface to it. To do that I need to 
> > > > > > > > > > > > > > > > > > > know if I need to generate default 
> > > > > > > > > > > > > > > > > > > constructors etc, which the needs* 
> > > > > > > > > > > > > > > > > > > methods do for me (I believe). The 
> > > > > > > > > > > > > > > > > > > alternative is I have to check manually 
> > > > > > > > > > > > > > > > > > > whether all the constructors/assignment 
> > > > > > > > > > > > > > > > > > > operators exist, then implement the 
> > > > > > > > > > > > > > > > > > > implicit declaration rules myself 
> > > > > > > > > > > > > > > > > > > correctly for each version of the 
> > > > > > > > > > > > > > > > > > > standard, which I'd rather avoid.
> > > > > > > > > > > > > > > > > > > 
> > > > > > > > > > > > > > > > > > > Would putting a note in the doc comment 
> > > > > > > > > > > > > > > > > > > about the behaviour differing when the 
> > > > > > > > > > > > > > > > > > > class is being constructed as originally 
> > > > > > > > > > > > > > > > > > > suggested work for everyone?
> > > > > > > > > > > > > > > > > > Why is the `__is_default_constructible` 
> > > > > > > > > > > > > > > > > > builtin type trait not enough? Do you have 
> > > > > > > > > > > > > > > > > > different behavior for user provided and 
> > > > > > > > > > > > > > > > > > implicit default constructors?
> > > > > > > > > > > > > > > > > > 
> > > > > > > > > > > > > > > > > Can I evaluate that  from libclang somewhow? 
> > > > > > > > > > > > > > > > > I can't modify the C++ libraries I'm 
> > > > > > > > > > > > > > > > > wrapping. 
> > > > > > > > > > > > > > > > > 
> > > > > > > > > > > > > > > > > Basically, given:
> > > > > > > > > > > > > > > > > ```
> > > > > > > > > > > > > > > > > struct Foo { /* ... */ };
> > > > > > > > > > > > > > > > > ```
> > > > > > > > > > > > > > > > > 
> > > > > > > > > > > > > > > > > I want to generate:
> > > > > > > > > > > > > > > > > 
> > > > > > > > > > > > > > > > > ```
> > > > > > > > > > > > > > > > > typedef struct Foo_t;
> > > > > > > > > > > > > > > > > 
> > > > > > > > > > > > > > > > > Foo_t* Foo_ctor();
> > > > > > > > > > > > > > > > > Foo_t* Foo_copy_ctor(Foo_t*);
> > > > > > > > > > > > > > > > > /* etc... */
> > > > > > > > > > > > > > > > > Foo_dtor(Foo_t*);
> > > > > > > > > > > > > > > > > ```
> > > > > > > > > > > > > > > > > 
> > > > > > > > > > > > > > > > > In order to know which ones to generate for 
> > > > > > > > > > > > > > > > > an arbitrary struct that may or may not have 
> > > > > > > > > > > > > > > > > any combination of ctor/assignments defined, 
> > > > > > > > > > > > > > > > > I need to know which ones exist and follow 
> > > > > > > > > > > > > > > > > the implicit generation rules for the ones 
> > > > > > > > > > > > > > > > > that don't. I can do this myself with a whole 
> > > > > > > > > > > > > > > > > bunch of version-dependent logic, but I'd 
> > > > > > > > > > > > > > > > > rather just rely on libclang since it already 
> > > > > > > > > > > > > > > > > knows all this much better than I do.
> > > > > > > > > > > > > > > > I looked a bit, and it seems they aren't, and 
> > > > > > > > > > > > > > > > that generally libclang doesn't really know 
> > > > > > > > > > > > > > > > about Sema, so exporting the type traits is not 
> > > > > > > > > > > > > > > > that easy :/
> > > > > > > > > > > > > > > > 
> > > > > > > > > > > > > > > > I'm not sure what's the best way forward here, 
> > > > > > > > > > > > > > > > but I don't like the idea of exporting those 
> > > > > > > > > > > > > > > > half baked internal API calls when there are 
> > > > > > > > > > > > > > > > actual standardized and implemented type traits 
> > > > > > > > > > > > > > > > that perform the same goal.
> > > > > > > > > > > > > > > CCing folks who may have more historical memory 
> > > > > > > > > > > > > > > of the C APIs and whether they're expected to 
> > > > > > > > > > > > > > > operate on a completed AST or are expected to 
> > > > > > > > > > > > > > > work on an AST as it is under construction. My 
> > > > > > > > > > > > > > > unverified belief is that these APIs are expected 
> > > > > > > > > > > > > > > to work on a completed AST.
> > > > > > > > > > > > > > > 
> > > > > > > > > > > > > > > @echristo @dblaikie @rjmccall @rsmith
> > > > > > > > > > > > > > > 
> > > > > > > > > > > > > > > I'm also not certain of what the best path 
> > > > > > > > > > > > > > > forward is here. I'm not comfortable exposing the 
> > > > > > > > > > > > > > > needs* functions because they really are 
> > > > > > > > > > > > > > > implementation details and I don't want to 
> > > > > > > > > > > > > > > promise we'll support that API forever. But at 
> > > > > > > > > > > > > > > the same time, the use case is reasonably 
> > > > > > > > > > > > > > > compelling on the assumption you need to inspect 
> > > > > > > > > > > > > > > the AST nodes as they're still under construction 
> > > > > > > > > > > > > > > instead of inspecting them once the AST is 
> > > > > > > > > > > > > > > completed. If the AST is fully constructed, then 
> > > > > > > > > > > > > > > we should have already added the AST nodes for 
> > > > > > > > > > > > > > > any special member functions that needed to be 
> > > > > > > > > > > > > > > generated implicitly, so as Roy mentioned, you 
> > > > > > > > > > > > > > > should be able to find the special member 
> > > > > > > > > > > > > > > function you're after and check `isImplicit()` on 
> > > > > > > > > > > > > > > it.
> > > > > > > > > > > > > > Not sure I'm quite following - it doesn't look 
> > > > > > > > > > > > > > (admittedly, sorry, at a somewhat superficial look 
> > > > > > > > > > > > > > at the discussion here) like this is necessarily 
> > > > > > > > > > > > > > about incomplete AST - could parse the header and 
> > > > > > > > > > > > > > stop. That's a complete AST, yeah? And then it 
> > > > > > > > > > > > > > might be OK/reasonable to ask "could this type be 
> > > > > > > > > > > > > > default constructed" (even if the implicit ctor has 
> > > > > > > > > > > > > > been implicitly instantiated/there was no use in 
> > > > > > > > > > > > > > the source code that's been parsed)
> > > > > > > > > > > > > > 
> > > > > > > > > > > > > > Is that correct?
> > > > > > > > > > > > > I am just parsing the headers of a library using 
> > > > > > > > > > > > > `clang_parseTranslationUnit()` then using 
> > > > > > > > > > > > > `clang_visitChildren()` to inspect the AST. Doing 
> > > > > > > > > > > > > this I do NOT see any implicitly generated methods, 
> > > > > > > > > > > > > hence why I need these functions. It sounds like you 
> > > > > > > > > > > > > expect those methods to be in the AST already? Which 
> > > > > > > > > > > > > suggests I'm doing something wrong in my parsing 
> > > > > > > > > > > > > (missing another function call/option or something)?
> > > > > > > > > > > > Ah, no, I wouldn't expect them to be in the AST unless 
> > > > > > > > > > > > there was code that used them in the header.
> > > > > > > > > > > > 
> > > > > > > > > > > > But I'm saying/trying to say is this isn't a "AST nodes 
> > > > > > > > > > > > still under construction" that @aaron.ballman is 
> > > > > > > > > > > > describing, so far as I can see - you can completely 
> > > > > > > > > > > > parse the header, have a complete AST then reasonably 
> > > > > > > > > > > > want to ask "could I default construct an object like 
> > > > > > > > > > > > this" - even if the implicit default ctor hasn't been 
> > > > > > > > > > > > instantiated because none of the parsed code asked that 
> > > > > > > > > > > > question.
> > > > > > > > > > > > 
> > > > > > > > > > > > Not sure what the API to do this should look like, but 
> > > > > > > > > > > > it seems like a pretty reasonable use case.
> > > > > > > > > > > > 
> > > > > > > > > > > > Not sure about whether they cross some threshold where 
> > > > > > > > > > > > they're too complex/nuanced to go in the C API or not - 
> > > > > > > > > > > > maybe that's a question.
> > > > > > > > > > > >> I am just parsing the headers of a library using 
> > > > > > > > > > > >> clang_parseTranslationUnit() then using 
> > > > > > > > > > > >> clang_visitChildren() to inspect the AST. Doing this I 
> > > > > > > > > > > >> do NOT see any implicitly generated methods, hence why 
> > > > > > > > > > > >> I need these functions. It sounds like you expect 
> > > > > > > > > > > >> those methods to be in the AST already? Which suggests 
> > > > > > > > > > > >> I'm doing something wrong in my parsing (missing 
> > > > > > > > > > > >> another function call/option or something)?
> > > > > > > > > > > > Ah, no, I wouldn't expect them to be in the AST unless 
> > > > > > > > > > > > there was code that used them in the header.
> > > > > > > > > > > 
> > > > > > > > > > > That's part of the "this is an implementation detail" I 
> > > > > > > > > > > was talking about. *Today* we don't generate the AST 
> > > > > > > > > > > nodes for those functions unless we have to. Nothing says 
> > > > > > > > > > > we won't find a reason we need to always generate those 
> > > > > > > > > > > AST nodes, which makes the `needs*` functions useless. I 
> > > > > > > > > > > suppose in that situation, the breakage for the C APIs is 
> > > > > > > > > > > mostly that the exposed `needs*` functions start 
> > > > > > > > > > > trivially returning `false` though, so maybe it's not as 
> > > > > > > > > > > bad as it could be...
> > > > > > > > > > > 
> > > > > > > > > > > > But I'm saying/trying to say is this isn't a "AST nodes 
> > > > > > > > > > > > still under construction" that @aaron.ballman is 
> > > > > > > > > > > > describing, so far as I can see - you can completely 
> > > > > > > > > > > > parse the header, have a complete AST then reasonably 
> > > > > > > > > > > > want to ask "could I default construct an object like 
> > > > > > > > > > > > this" - even if the implicit default ctor hasn't been 
> > > > > > > > > > > > instantiated because none of the parsed code asked that 
> > > > > > > > > > > > question.
> > > > > > > > > > > 
> > > > > > > > > > > Yeah, the situation I mentioned earlier was the validity 
> > > > > > > > > > > of the calls when the class has not been fully 
> > > > > > > > > > > constructed in the AST yet. That's not the case here, 
> > > > > > > > > > > which is great.
> > > > > > > > > > > 
> > > > > > > > > > > > Not sure what the API to do this should look like, but 
> > > > > > > > > > > > it seems like a pretty reasonable use case.
> > > > > > > > > > > 
> > > > > > > > > > > Agreed that the use case is reasonable.
> > > > > > > > > > > 
> > > > > > > > > > > > Not sure about whether they cross some threshold where 
> > > > > > > > > > > > they're too complex/nuanced to go in the C API or not - 
> > > > > > > > > > > > maybe that's a question.
> > > > > > > > > > > 
> > > > > > > > > > > Mostly, I think we try to expose APIs that we think we 
> > > > > > > > > > > can support long-term based on what needs folks have. 
> > > > > > > > > > > Given that there's a need here, and the use case seems 
> > > > > > > > > > > reasonable, it seems to be something we should consider 
> > > > > > > > > > > supporting.
> > > > > > > > > > > 
> > > > > > > > > > > I suppose there's another way we could view this need 
> > > > > > > > > > > though -- some folks need those special member functions 
> > > > > > > > > > > even if Clang doesn't think they're necessary to 
> > > > > > > > > > > generate. Not only is this use case one such time, but 
> > > > > > > > > > > running AST matchers over the AST (like in clang-query or 
> > > > > > > > > > > clang-tidy) may also have a similar expectation of 
> > > > > > > > > > > finding all the special members. So maybe what we need is 
> > > > > > > > > > > some flag to tell Clang "force the generation of those 
> > > > > > > > > > > special member functions" so that we don't have to expose 
> > > > > > > > > > > a `needs` function for them (which helps for the C API 
> > > > > > > > > > > users but doesn't help folks like consumers of AST 
> > > > > > > > > > > matchers). (Note, I don't yet know how good or bad of an 
> > > > > > > > > > > idea this is.)
> > > > > > > > > > Yeah - if someone is interested in doing the work, I'd be 
> > > > > > > > > > curious how some equivalent operations work in the AST 
> > > > > > > > > > matchers? I'd assume there's some way to query if something 
> > > > > > > > > > is copy constructible - and maybe that's more likely to be 
> > > > > > > > > > the query the user wants, rather than the "needs" 
> > > > > > > > > > operations?
> > > > > > > > > > 
> > > > > > > > > > (like, if we did add the implicit copy constructors into 
> > > > > > > > > > the AST proactively, I don't think I'd want these queries 
> > > > > > > > > > to return "false" - I think likely the intended query is 
> > > > > > > > > > "is this thing copy constructible" (or similar) less about 
> > > > > > > > > > whether the operation is or isn't present in the AST)
> > > > > > > > > In my case it's "do I need to generate a copy ctor for this 
> > > > > > > > > type?". @aaron.ballman 's suggestion of a way to force the 
> > > > > > > > > implicits to be generated in the AST would work just fine for 
> > > > > > > > > me. 
> > > > > > > > > That's part of the "this is an implementation detail" I was 
> > > > > > > > > talking about. *Today* we don't generate the AST nodes for 
> > > > > > > > > those functions unless we have to. Nothing says we won't find 
> > > > > > > > > a reason we need to always generate those AST nodes, which 
> > > > > > > > > makes the `needs*` functions useless. I suppose in that 
> > > > > > > > > situation, the breakage for the C APIs is mostly that the 
> > > > > > > > > exposed `needs*` functions start trivially returning `false` 
> > > > > > > > > though, so maybe it's not as bad as it could be...
> > > > > > > > > 
> > > > > > > > > ...
> > > > > > > > >
> > > > > > > > > Yeah, the situation I mentioned earlier was the validity of 
> > > > > > > > > the calls when the class has not been fully constructed in 
> > > > > > > > > the AST yet. That's not the case here, which is great.
> > > > > > > > > 
> > > > > > > > 
> > > > > > > > This is not even about future proofing - this is already bad 
> > > > > > > > API. Simply adding
> > > > > > > > 
> > > > > > > > ```
> > > > > > > > void f() {
> > > > > > > >   Test t;
> > > > > > > > }
> > > > > > > > ```
> > > > > > > > 
> > > > > > > > in the test in this PR is changing the printed line from 
> > > > > > > > `ClassDecl=Test:3:7 (Definition) (needs ctor) (needs cctor) 
> > > > > > > > (needs mctor) (needs cassign) (needs massign) (needs dtor) 
> > > > > > > > Extent=[3:1 - 17:2]`
> > > > > > > > to
> > > > > > > > `ClassDecl=Test:3:7 (Definition) (needs cassign) (needs 
> > > > > > > > massign) (needs dtor) Extent=[3:1 - 17:2]`
> > > > > > > > 
> > > > > > > > I don't think making functions in libclang conditional on 
> > > > > > > > whether somewhere in the headers types are actually used or not 
> > > > > > > > is likely to provide value. It's impossible to enforce non-use 
> > > > > > > > of a type if it's definition is available and it's very 
> > > > > > > > unnatural to C++ to rely on it.
> > > > > > > > 
> > > > > > > > I'm now also pessimistic about the possibility of implementing 
> > > > > > > > **correct** versions of those `std::is...` type traits without 
> > > > > > > > Sema. Default constructors might be template functions that are 
> > > > > > > > SFINAE-disabled, for example. This isn't very exotic - the 
> > > > > > > > default constructors of pair, optional, etc.. are all 
> > > > > > > > implemented like this. The other type traits that we'd want to 
> > > > > > > > expose are also pretty similar.
> > > > > > > > 
> > > > > > > > A solution might be useful even if it doesn't handle all cases 
> > > > > > > > correctly, of course. But IMHO in this case an approach with 
> > > > > > > > only AST would be too partial to justify its shortcomings.
> > > > > > > > 
> > > > > > > > In my case it's "do I need to generate a copy ctor for this 
> > > > > > > > type?". @aaron.ballman 's suggestion of a way to force the 
> > > > > > > > implicits to be generated in the AST would work just fine for 
> > > > > > > > me.
> > > > > > > 
> > > > > > > But by "generate" you mean "generate a wrapper for this 
> > > > > > > operation", yeah?
> > > > > > > 
> > > > > > > If you could query the type for "is this type copy 
> > > > > > > constructible", "is this type copy assignable", etc, be adequate 
> > > > > > > for your needs?
> > > > > > > > In my case it's "do I need to generate a copy ctor for this 
> > > > > > > > type?". @aaron.ballman 's suggestion of a way to force the 
> > > > > > > > implicits to be generated in the AST would work just fine for 
> > > > > > > > me.
> > > > > > > 
> > > > > > > But by "generate" you mean "generate a wrapper for this 
> > > > > > > operation", yeah?
> > > > > > > 
> > > > > > > If you could query the type for "is this type copy 
> > > > > > > constructible", "is this type copy assignable", etc, be adequate 
> > > > > > > for your needs?
> > > > > > 
> > > > > > Thinking about it some more, yes I think it probably would. I would 
> > > > > > have to do some minor book-keeping to track whether there was one 
> > > > > > already declared on the class or not, but that's a lot simpler than 
> > > > > > reimplementing the implicit rules. I guess I would need 
> > > > > > `isDefaultConstructible`, `isCopyConstructible`, 
> > > > > > `isMoveConstructible`, `isCopyAssignable`, and `isMoveAssignable`
> > > > > @royjacobson it's also going to be pretty problematic to instantiate 
> > > > > those templates as members too.
> > > > > 
> > > > > The AST is pretty accurately reflective of the compiler's 
> > > > > understanding of the type at the time - adding extra instantiations 
> > > > > isn't necessarily an improvement in fidelity. I'd argue it's a loss 
> > > > > in fidelity because these things weren't instantiated by the original 
> > > > > code.
> > > > > 
> > > > > (types won't be entirely consistent/stable - member function 
> > > > > templates are a great example - you can add code that'll cause new 
> > > > > instantiations, and there's no way to fully enumerate all possible 
> > > > > instantiations. So it's not a goal for a type description to be 
> > > > > stable regardless of the code that uses the type)
> > > > To my thinking, there's a difference between "is this copy 
> > > > constructible" and "does this have a copy constructor (even 
> > > > implicitly)". My understanding of what @anderslanglands is trying to do 
> > > > is to find classes that have a special member function so that the 
> > > > wrapper can expose the same functionality. That's not "is this copy 
> > > > constructible", that's "does this have a copy constructor (even 
> > > > implicitly)."
> > > > 
> > > > The C++ standard specifies when classes get implicit special member 
> > > > functions and our AST does not reflect that accurately unless the class 
> > > > is being used: https://godbolt.org/z/13h3T3dPq. Both have definition 
> > > > data that accurately reflects whether the class could get those special 
> > > > members (and that definition data is an internal implementation 
> > > > detail), but only one of those classes have AST nodes for the special 
> > > > members, which means trying to run an AST matcher query for every class 
> > > > with a constructor gives unexpected results: 
> > > > https://godbolt.org/z/PhMY57anM
> > > Perhaps a simple test: @anderslanglands, if the class had a ctor template 
> > > that could be used for copying the type - would that meet your 
> > > requirements? Would you want to write a wrapper that invoked/instantiated 
> > > that template to perform a copy? Or would you want your wrapper not to 
> > > expose copy construction?
> > > 
> > > If it does, then the property of interest is "is this type copy 
> > > constructible" and not "does this type have a copy constructor", I think?
> > > 
> > > All that said, I don't outright object to the implicit special members 
> > > being eagerly generated if it doesn't cost much compile time/memory 
> > > usage/etc, but I'm certainly a little hesitant. Totally your call, 
> > > @aaron.ballman 
> > @dblaikie what do you mean by "ctor template" in this context?
> > 
> > note: for "copy ctor" here and in what follows, read "all the potentially 
> > implicitly defined functions"
> > 
> > What I'm trying to do is this. I'm essentially transpiling C++ libraries to 
> > C (which are then wrapped in Rust, but it could in theory be any other 
> > language). I do this by iterating over the AST and extracting all the 
> > methods (and all methods from bases), then transforming them into C 
> > equivalents. Thus if a class I'm interested in defines a copy ctor itself, 
> > my regular AST extraction will generate a C version of that and all is 
> > right with the world.
> > 
> > The tricky bit comes when a class *doesnt* define a copy ctor. I then have 
> > to figure out if it's not defined because:
> > 1) The library author didn't bother and is relying on it being implicitly 
> > defined
> > or
> > 2) The class *cannot* have a copy ctor because of the implicit rules
> > 
> > In the case of 1) I currently then need to detect this and generate the C 
> > version of the copy ctor which calls the (implicitly defined) C++ copy ctor 
> > (and of course I'm generating the library that calls this *after* I've 
> > extracted the AST, which means I can't rely on this call to define that 
> > ctor in the AST).
> > 
> > In the case of 2) I need to detect that and then do nothing (and possibly 
> > some other stuff later on if I decide to represent C++ objects as bags of 
> > bytes that I pass around but that's another story).
> > 
> > So there a few ways of achieving what I need:
> > 
> > a) I just implement the implicit rules manually, detect what is and isn't 
> > there and decide whether to create the copy ctor myself. This is what I did 
> > initially, but of course I screwed it up first time which led to me 
> > thinking "surely there's a better way".
> > 
> > b) libclang exposes the `needs*` functions in this patch. I just call those 
> > during extraction to decide what I do and do not need to implement manually 
> > on the C side. Works perfectly for me, but obviously feels wrong to a few 
> > people here.
> > 
> > c) libclang exposes `isCopyConstructible()` etc. This also works for me, 
> > just requires a little more book-keeping my end, i.e. is 
> > `isCopyConstructible()` is true AND the class (or its bases) does not have 
> > an explicit copy constructor, I need to generate one.
> > 
> > d) There's some way to force clang to instantiate all the implicit methods 
> > in the AST. This would make my life very easy, as I wouldn't have to think 
> > about any of this, they'd just be treated like regular methods and 
> > everything would just be extracted without any special handling.
> > 
> > So I'd be fine with anything that's not a) :)
> > All that said, I don't outright object to the implicit special members 
> > being eagerly generated if it doesn't cost much compile time/memory 
> > usage/etc, but I'm certainly a little hesitant. Totally your call, 
> > @aaron.ballman
> 
> Well, I'm hoping we can find a way to avoid doing that in the general case 
> while still giving users a way to opt into that behavior if they need it for 
> the C APIs or AST matching. I think the overhead would be problematic for 
> general compilation (and it would likely impact things like template 
> instantiation depths due to memory overhead pressure), but allowing folks to 
> opt in gives them the power to decide which properties of the compilation are 
> more important to them.
> @dblaikie what do you mean by "ctor template" in this context?

```
struct t1 {
  template<typename T>
  t1(const T&) { ... }
};
```
But actually I got that wrong - the compiler won't consider a template for use 
when copy constructing.

It does for default constructing, though ( https://godbolt.org/z/hax4jhbPY ):
```
#include <iostream>
struct t1 {
  template<typename ...Ts>
  t1(Ts ...args) {
      std::cout << "Called the variadic template ctor\n";
  }
};
int main() {
    t1 v2;
}
static_assert(std::is_default_constructible_v<t1>, "");
```
This type doesn't have a default constructor, but it is default constructible.

So maybe that's a place to ask the question: In this case, which property are 
you interested in? "has a default constructor" or "is default constructible"? 
(would you want to write a wrapper around an instantiation of the ctor template 
taking no args?)

Answering that question might suggest the design for the other implicit 
ctors/operations, even if they don't have quite the same problems.


> Well, I'm hoping we can find a way to avoid doing that in the general case 
> while still giving users a way to opt into that behavior if they need it for 
> the C APIs or AST matching. 

Ah, I was figuring not wanting to diverge/provide toggles if we can help it - 
like unused warnings, opt-in features may go undertested (especially for these 
sort of operations being a bit subtle in some ways). Like we've discussed (at 
least I remember it coming up many years ago) trying to unify more of the 
static analyzer and IRGen to avoid divergence there - adding more divergence 
between static analysis and IRGen/etc seems liable to create more risk of 
bugs/inconsistencies.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D135557/new/

https://reviews.llvm.org/D135557

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to