On Fri, Jan 8, 2016 at 1:54 PM, Philippe Canal <pca...@fnal.gov> wrote:

> Hi Richard,
>
> In our use (Persistency of C++ objects, including the (meta)description of
> their data content as well as use the name as key to access the class'
> reflection information at run-time), the 'context' is indeed always the "at
> the end of the translation unit" (or global scope).
> Thus (for us),
>
> > What is the fully-qualified name of `B::t`'s type? Is it `B::TX` or
> `std::tuple<A::X>` or `std::tuple<::A::X>`?
>
> It indeed either `B::TX` or `std::tuple<A::X>` depending on whether the
> typedefs are being desugared or not.
>
> > from within namespace `B`
>
> Within our API there is no way to actually express this (and I can't think
> of a semantic where it would make sense). Thus by construction it is always
> the "end of the translation unit" case.
>
> > The "ideal interface" idea is a good--and very cool--one, but my use
> case doesn't call for it.
>
> This also our situation. In addition, I do think that supporting the
> general case would increase the implementation complexity.  One 'simple'
> adaption is to support also the case with the leading :: (i.e.
> ::std::tuple<::A::X> which would always be safe no matter which context you
> use it).
>

The primary use case for the general "how do I name this thing from *here*"
functionality is automated refactoring tools, where inserting a
fully-qualified name is about the worst (correct) way you can name any
given entity, and isn't even always possible (for instance, if you're
naming an entity from a local scope).

My principal concern here is that we clearly document the design decisions
for these interfaces, so that we know what possible results are / are not
correct. Extending this to support other clients (which want to know how to
name an entity from a specified context) is secondary, and can be postponed
until someone wants to put in the work to make it happen.

Cheers,
> Philippe.
>
>
>
>
> -------- Forwarded Message -------- Subject: Re: [PATCH] D15861: Support
> fully-qualified names for all QualTypes Date: Fri, 8 Jan 2016 19:50:16
> +0000 From: Sterling Augustine via cfe-commits
> <cfe-commits@lists.llvm.org><cfe-commits@lists.llvm.org>
> <cfe-commits@lists.llvm.org> Reply-To:
> reviews+d15861+public+e412d660379b2...@reviews.llvm.org, Sterling
> Augustine <saugust...@google.com> <saugust...@google.com> To:
> saugust...@google.com, rich...@metafoo.co.uk CC:
> cfe-commits@lists.llvm.org
>
>
> saugustine added a comment.
>
> Thanks for the reviews. Please take another look when you get a chance.
>
>
> ================
> Comment at: include/clang/Tooling/Core/QualTypeNames.h:32-33
> @@ +31,4 @@
> +namespace TypeName {
> +///\brief Convert the type into one with fully qualified template
> +/// arguments.
> +///\param[in] QT - the type for which the fully qualified type will be
> ----------------
> rsmith wrote:
> > rsmith wrote:
> > > Please ensure there's a space between each `/// ` and the content.
> > What do you mean by "fully qualified template arguments" here? Let me give 
> > you some examples:
> >
> >     namespace A {
> >       struct X {};
> >     }
> >     using A::X;
> >     namespace B {
> >       using std::tuple;
> >       typedef typle<X> TX;
> >       TX t;
> >       struct A { typedef int X; };
> >     }
> >
> > What is the fully-qualified name of `B::t`'s type? Is it `B::TX` or 
> > `std::tuple<A::X>` or `std::tuple<::A::X>`? Note that if you want to 
> > redeclare `t` from within namespace `B`, `std::tuple<A::X>` will name the 
> > wrong type.
> >
> >
> > Why does this only affect template arguments? Its name suggests it should 
> > affect the type as a whole (for instance, in the above case it should 
> > produce `std::tuple<...>`, not `tuple<...>`).
> >
> >
> > Generally, I think this interface needs to specify where the produced names 
> > can be used as a name for the specified type, otherwise I don't see how it 
> > can ever be reliable. For instance:
> >
> > > "Generates a name for a type that can be used to name the same type if 
> > > used at the end of the current translation unit." (eg, `B::TX` or 
> > > `std::tuple<X>`)
> >
> > or:
> >
> > > "Generates a maximally-explicit name for a type that can be used in any 
> > > context where all the relevant components have been declared. In such a 
> > > context, this name will either name the intended type or produce an 
> > > ambiguity error." (eg, `::std::tuple<::A::X>`)
> >
> > You should also specify what happens when it's not possible to generate 
> > such a name. For instance, given:
> >
> >     void f() {
> >       struct X {} x;
> >     }
> >
> > ... there's no way to name the type of `x` from outside `f` (which makes 
> > certain refactoring operations impossible unless you also move the 
> > definition of `struct X`).
> >
> >
> > I think the ideal interface here would allow you to specify a location 
> > where you wish to insert the name, and would produce a "best possible" name 
> > for that type for that location, avoiding adding explicit qualification / 
> > desugaring wherever possible, but the interface should at least take the 
> > context-sensitivity of names into account.
> My use case is to take a function signature, and communicate to a developer 
> one way to declare the variables they need to call the function.
>
> It does expand entire qualtypes, not just template parameters. (I've updated 
> that description.)
>
> Given the use case, "at the end of the translation unit" is the closest 
> description of where these names would be valid, with the exception that this 
> code avoids relying on any "using" declaration. "using foo::bar; void bat(bar 
> b);", this code would describe foo's parameter as type foo::bar, rather than 
> plain "bar", even though plain "bar" would work at the end of the translation 
> unit.
>
> I have updated the file header's comment to reflect all this, and added a 
> couple of test cases to prove to myself that it does what I have documented. 
> Along the way I have found a couple of places to explicitly mark where one 
> would do things differently if one wanted to change this behavior.
>
> The "ideal interface" idea is a good--and very cool--one, but my use case 
> doesn't call for it.
>
> ================
> Comment at: include/clang/Tooling/Core/QualTypeNames.h:49-79
> @@ +48,33 @@
> +
> +///\brief Create a NestedNameSpecifier for Namesp and its enclosing
> +/// scopes.
> +///
> +///\param[in] Ctx - the AST Context to be used.
> +///\param[in] Namesp - the NamespaceDecl for which a NestedNameSpecifier
> +/// is requested.
> +clang::NestedNameSpecifier *createNestedNameSpecifier(
> +    const clang::ASTContext &Ctx, const clang::NamespaceDecl *Namesp);
> +
> +///\brief Create a NestedNameSpecifier for TagDecl and its enclosing
> +/// scopes.
> +///
> +///\param[in] Ctx - the AST Context to be used.
> +///\param[in] TD - the TagDecl for which a NestedNameSpecifier is
> +/// requested.
> +///\param[in] FullyQualify - Convert all template arguments into fully
> +/// qualified names.
> +clang::NestedNameSpecifier *createNestedNameSpecifier(
> +    const clang::ASTContext &Ctx, const clang::TagDecl *TD, bool 
> FullyQualify);
> +
> +///\brief Create a NestedNameSpecifier for TypedefDecl and its enclosing
> +/// scopes.
> +///
> +///\param[in] Ctx - the AST Context to be used.
> +///\param[in] TD - the TypedefDecl for which a NestedNameSpecifier is
> +/// requested.
> +///\param[in] FullyQualify - Convert all template arguments (of possible
> +/// parent scopes) into fully qualified names.
> +clang::NestedNameSpecifier *createNestedNameSpecifier(
> +    const clang::ASTContext &Ctx, const clang::TypedefNameDecl *TD,
> +    bool FullyQualify);
> +
> ----------------
> rsmith wrote:
> > Is it useful to expose the intermediary functionality to generate 
> > fully-qualified `QualType`s and `NestedNameSpecifier`s rather than only 
> > exposing functionality to generate `string`s? What are the intended uses of 
> > these functions?
> I believe the Cling project (from which this code is adapted) uses all those 
> functions internally. So I expect at least one client for those functions.
>
> Let me know if you think hiding this interface is still the right thing.
>
> ================
> Comment at: lib/Tooling/Core/QualTypeNames.cpp:341-343
> @@ +340,5 @@
> +          llvm::dyn_cast<ElaboratedType>(QT.getTypePtr())) {
> +    // Intentionally, we do not care about the other compononent of
> +    // the elaborated type (the keyword) as part of the name
> +    // normalization is to remove it.
> +    Prefix = ETypeInput->getQualifier();
> ----------------
> rsmith wrote:
> > This will not work in C, or if the type name is normally shadowed by a 
> > variable or function. You sometimes need to keep the keyword.
> I've rewritten this code a bit, and this problem is solved near the end of 
> this function. (This section itself is now mostly gone.)
>
> http://reviews.llvm.org/D15861
>
>
>
> _______________________________________________
> cfe-commits mailing 
> listcfe-comm...@lists.llvm.orghttp://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
>
>
>
>
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to