[PATCH] D15861: Support fully-qualified names for all QualTypes
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Mon Jan 4 16:07:15 PST 2016
rsmith added inline comments.
================
Comment at: include/clang/Tooling/Core/QualTypeNames.h:32
@@ +31,3 @@
+namespace TypeName {
+///\brief Convert the type into one with fully qualified template
+/// arguments.
----------------
Please ensure there's a space between each `/// ` and the content.
================
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:
> 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.
================
Comment at: include/clang/Tooling/Core/QualTypeNames.h:37
@@ +36,3 @@
+///\param[in] Ctx - the ASTContext to be used.
+clang::QualType getFullyQualifiedType(clang::QualType QT,
+ const clang::ASTContext &Ctx);
----------------
Remove the `clang::`s; you're already in namespace `clang`.
================
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);
+
----------------
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?
================
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();
----------------
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.
http://reviews.llvm.org/D15861
More information about the cfe-commits
mailing list