[clang] 476a497 - Add clang_CXXMethod_isCopyAssignmentOperator to libclang

2022-10-26 Thread Luca Di Sera via cfe-commits

Author: Luca Di Sera
Date: 2022-10-27T06:55:11+02:00
New Revision: 476a497f729a408ba436f75fc50a41254ce65bc8

URL: 
https://github.com/llvm/llvm-project/commit/476a497f729a408ba436f75fc50a41254ce65bc8
DIFF: 
https://github.com/llvm/llvm-project/commit/476a497f729a408ba436f75fc50a41254ce65bc8.diff

LOG: Add clang_CXXMethod_isCopyAssignmentOperator to libclang

The new method is a wrapper of `CXXMethodDecl::isCopyAssignmentOperator` and
can be used to recognized copy-assignment operators in libclang.

An export for the method, together with its documentation, was added to
"clang/include/clang-c/Index.h" with an implementation provided in
"clang/tools/libclang/CIndex.cpp". The implementation was based on
similar `clang_CXXMethod.*` implementations, following the same
structure but calling `CXXMethodDecl::isCopyAssignmentOperator` for its
main logic.

The new symbol was further added to "clang/tools/libclang/libclang.map"
to be exported, under the LLVM16 tag.

"clang/tools/c-index-test/c-index-test.c" was modified to print a
specific tag, "(copy-assignment operator)", for cursors that are
recognized by `clang_CXXMethod_isCopyAssignmentOperator`.
A new regression test file,
"clang/test/Index/copy-assignment-operator.cpp", was added to ensure
that the correct constructs were recognized or not by the new function.

The "clang/test/Index/get-cursor.cpp" regression test file was updated
as it was affected by the new "(copy-assignment operator)" tag.

A binding for the new function was added to libclang's python's
bindings, in "clang/bindings/python/clang/cindex.py", adding a new
method for `Cursor`, `is_copy_assignment_operator_method`.

The current release note, `clang/docs/ReleaseNotes.rst`, was modified to
report the new addition under the "libclang" section.

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D136604

Added: 
clang/test/Index/copy-assignment-operator.cpp

Modified: 
clang/bindings/python/clang/cindex.py
clang/docs/ReleaseNotes.rst
clang/include/clang-c/Index.h
clang/test/Index/get-cursor.cpp
clang/tools/c-index-test/c-index-test.c
clang/tools/libclang/CIndex.cpp
clang/tools/libclang/libclang.map

Removed: 




diff  --git a/clang/bindings/python/clang/cindex.py 
b/clang/bindings/python/clang/cindex.py
index a8fe6e3e7ed56..99dcbb341dfe1 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -1479,6 +1479,31 @@ def is_deleted_method(self):
 """
 return conf.lib.clang_CXXMethod_isDeleted(self)
 
+def is_copy_assignment_operator_method(self):
+"""Returnrs True if the cursor refers to a copy-assignment operator.
+
+A copy-assignment operator `X::operator=` is a non-static,
+non-template member function of _class_ `X` with exactly one
+parameter of type `X`, `X&`, `const X&`, `volatile X&` or `const
+volatile X&`.
+
+
+That is, for example, the `operator=` in:
+
+   class Foo {
+   bool operator=(const volatile Foo&);
+   };
+
+Is a copy-assignment operator, while the `operator=` in:
+
+   class Bar {
+   bool operator=(const int&);
+   };
+
+Is not.
+"""
+return conf.lib.clang_CXXMethod_isCopyAssignmentOperator(self)
+
 def is_mutable_field(self):
 """Returns True if the cursor refers to a C++ field that is declared
 'mutable'.
@@ -3436,6 +3461,10 @@ def cursor(self):
[Cursor],
bool),
 
+  ("clang_CXXMethod_isCopyAssignmentOperator",
+   [Cursor],
+   bool),
+
   ("clang_CXXMethod_isPureVirtual",
[Cursor],
bool),

diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index cb438b596c90c..d73e58acbccd1 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -673,8 +673,11 @@ libclang
   the behavior of ``QualType::getNonReferenceType`` for ``CXType``.
 - Introduced the new function ``clang_CXXMethod_isDeleted``, which queries
   whether the method is declared ``= delete``.
-- ``clang_Cursor_getNumTemplateArguments``, 
``clang_Cursor_getTemplateArgumentKind``,
-  ``clang_Cursor_getTemplateArgumentType``, 
``clang_Cursor_getTemplateArgumentValue`` and
+- Introduced the new function ``clang_CXXMethod_isCopyAssignmentOperator``,
+  which identifies whether a method cursor is a copy-assignment
+  operator.
+- ``clang_Cursor_getNumTemplateArguments``, 
``clang_Cursor_getTemplateArgumentKind``, 
+  ``clang_Cursor_getTemplateArgumentType``, 
``clang_Cursor_getTemplateArgumentValue`` and 
   ``clang_Cursor_getTemplateArgumentUnsignedValue`` now work on struct, class,
   and partial template specialization cursors in addition to function cursors.
 

diff  --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index 4e6fe060f2518..2cd2d499ab53d 100644
--- a/clang/include/clang-c/Index.h
+

[clang] 5c67cf0 - Add clang_CXXMethod_isMoveAssignmentOperator to libclang

2022-11-14 Thread Luca Di Sera via cfe-commits

Author: Luca Di Sera
Date: 2022-11-14T15:21:36+01:00
New Revision: 5c67cf0a7fdc00c9b9c55578b770e768f5618bed

URL: 
https://github.com/llvm/llvm-project/commit/5c67cf0a7fdc00c9b9c55578b770e768f5618bed
DIFF: 
https://github.com/llvm/llvm-project/commit/5c67cf0a7fdc00c9b9c55578b770e768f5618bed.diff

LOG: Add clang_CXXMethod_isMoveAssignmentOperator to libclang

The new method is a wrapper of `CXXMethodDecl::isMoveAssignmentOperator` and
can be used to recognized move-assignment operators in libclang.

An export for the function, together with its documentation, was added to
"clang/include/clang-c/Index.h" with an implementation provided in
"clang/tools/libclang/CIndex.cpp". The implementation was based on
similar `clang_CXXMethod.*` implementations, following the same
structure but calling `CXXMethodDecl::isMoveAssignmentOperator` for its
main logic.

The new symbol was further added to "clang/tools/libclang/libclang.map"
to be exported, under the LLVM16 tag.

"clang/tools/c-index-test/c-index-test.c" was modified to print a
specific tag, "(move-assignment operator)", for cursors that are
recognized by `clang_CXXMethod_isMoveAssignmentOperator`.
A new regression test file,
"clang/test/Index/move-assignment-operator.cpp", was added to ensure
whether the correct constructs were recognized or not by the new function.

The "clang/test/Index/get-cursor.cpp" regression test file was updated
as it was affected by the new "(move-assignment operator)" tag.

A binding for the new function was added to libclang's python's
bindings, in "clang/bindings/python/clang/cindex.py", adding a new
method for `Cursor`, `is_move_assignment_operator_method`.
An accompanying test was added to
`clang/bindings/python/tests/cindex/test_cursor.py`, testing the new
function with the same methodology as the corresponding libclang test.

The current release note, `clang/docs/ReleaseNotes.rst`, was modified to
report the new addition under the "libclang" section.

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D137246

Added: 
clang/test/Index/move-assignment-operator.cpp

Modified: 
clang/bindings/python/clang/cindex.py
clang/bindings/python/tests/cindex/test_cursor.py
clang/docs/ReleaseNotes.rst
clang/include/clang-c/Index.h
clang/test/Index/get-cursor.cpp
clang/tools/c-index-test/c-index-test.c
clang/tools/libclang/CIndex.cpp
clang/tools/libclang/libclang.map

Removed: 




diff  --git a/clang/bindings/python/clang/cindex.py 
b/clang/bindings/python/clang/cindex.py
index 99dcbb341dfe..2e32ce2ba6d0 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -1504,6 +1504,31 @@ class Bar {
 """
 return conf.lib.clang_CXXMethod_isCopyAssignmentOperator(self)
 
+def is_move_assignment_operator_method(self):
+"""Returnrs True if the cursor refers to a move-assignment operator.
+
+A move-assignment operator `X::operator=` is a non-static,
+non-template member function of _class_ `X` with exactly one
+parameter of type `X&&`, `const X&&`, `volatile X&&` or `const
+volatile X&&`.
+
+
+That is, for example, the `operator=` in:
+
+   class Foo {
+   bool operator=(const volatile Foo&&);
+   };
+
+Is a move-assignment operator, while the `operator=` in:
+
+   class Bar {
+   bool operator=(const int&&);
+   };
+
+Is not.
+"""
+return conf.lib.clang_CXXMethod_isMoveAssignmentOperator(self)
+
 def is_mutable_field(self):
 """Returns True if the cursor refers to a C++ field that is declared
 'mutable'.
@@ -3465,6 +3490,10 @@ def cursor(self):
[Cursor],
bool),
 
+  ("clang_CXXMethod_isMoveAssignmentOperator",
+   [Cursor],
+   bool),
+
   ("clang_CXXMethod_isPureVirtual",
[Cursor],
bool),

diff  --git a/clang/bindings/python/tests/cindex/test_cursor.py 
b/clang/bindings/python/tests/cindex/test_cursor.py
index ef875e972474..198352080c69 100644
--- a/clang/bindings/python/tests/cindex/test_cursor.py
+++ b/clang/bindings/python/tests/cindex/test_cursor.py
@@ -219,6 +219,64 @@ def test_is_default_method(self):
 self.assertTrue(xc.is_default_method())
 self.assertFalse(yc.is_default_method())
 
+def test_is_move_assignment_operator_method(self):
+"""Ensure Cursor.is_move_assignment_operator_method works."""
+source_with_move_assignment_operators = """
+struct Foo {
+   // Those are move-assignment operators
+   bool operator=(const Foo&&);
+   bool operator=(Foo&&);
+   bool operator=(volatile Foo&&);
+   bool operator=(const volatile Foo&&);
+
+// Positive-check that the recognition works for templated classes too
+template 
+class Bar {
+bool operator=(const Bar&&)

[clang] 0a51bc7 - Add clang_CXXMethod_isExplicit to libclang

2023-01-27 Thread Luca Di Sera via cfe-commits

Author: Luca Di Sera
Date: 2023-01-27T13:23:41+01:00
New Revision: 0a51bc731bcc2c27e4fe97957a83642d93d989be

URL: 
https://github.com/llvm/llvm-project/commit/0a51bc731bcc2c27e4fe97957a83642d93d989be
DIFF: 
https://github.com/llvm/llvm-project/commit/0a51bc731bcc2c27e4fe97957a83642d93d989be.diff

LOG: Add clang_CXXMethod_isExplicit to libclang

The new method is a wrapper of `CXXConstructorDecl::isExplicit` and
`CXXConversionDecl::isExplicit`, allowing the user to recognize whether
the declaration pointed to by a cursor was marked with the explicit
specifier.

An export for the function, together with its documentation, was added
to "clang/include/clang-c/Index.h" with an implementation provided in
"clang/tools/libclang/CIndex.cpp".

The implementation is based on similar `clang_CXXMethod`
implementations, returning a falsy unsigned value when the cursor is not
a declaration, is not a declaration for a constructor or conversion
function or is not a relevant declaration that was marked with the
`explicit` specifier.

The new symbol was added to "clang/tools/libclang/libclang.map" to be
exported, under the LLVM16 tag.

"clang/tools/c-index-test/c-index-test.c" was modified to print a
specific tag, "(explicit)", for cursors that are recognized by
`clang_CXXMethod_isExplicit`.

Two new regression files, "explicit-constructor.cpp" and
"explicit-conversion-function.cpp", were added to "clang/test/Index", to
ensure that the behavior of the new function is correct for constructors
and conversion functions, respectively.

The "get-cursor.cpp", "index-file.cpp" and
"recursive-cxx-member-calls.cpp" regression files in "clang/test/Index"
were updated as they were affected by the new "(explicit)" tag.

A binding for the new function was added to libclang's python's
bindings, in "clang/bindings/python/clang/cindex.py", as the
"is_explicit_method" method under `Cursor`.

An accompanying test was added to
"clang/bindings/python/tests/cindex/test_cursor.py", mimicking the
regression tests for the C side.

The current release note for Clang, "clang/docs/ReleaseNotes.rst" was
modified to report the new addition under the "libclang" section.

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D140756

Added: 
clang/test/Index/explicit-constructor.cpp
clang/test/Index/explicit-conversion-function.cpp

Modified: 
clang/bindings/python/clang/cindex.py
clang/bindings/python/tests/cindex/test_cursor.py
clang/include/clang-c/Index.h
clang/test/Index/get-cursor.cpp
clang/test/Index/index-file.cpp
clang/test/Index/recursive-cxx-member-calls.cpp
clang/tools/c-index-test/c-index-test.c
clang/tools/libclang/CIndex.cpp
clang/tools/libclang/libclang.map

Removed: 




diff  --git a/clang/bindings/python/clang/cindex.py 
b/clang/bindings/python/clang/cindex.py
index 2e32ce2ba6d06..5d13b7bff1498 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -1529,6 +1529,51 @@ class Bar {
 """
 return conf.lib.clang_CXXMethod_isMoveAssignmentOperator(self)
 
+def is_explicit_method(self):
+"""Determines if a C++ constructor or conversion function is
+explicit, returning 1 if such is the case and 0 otherwise.
+
+Constructors or conversion functions are declared explicit through
+the use of the explicit specifier.
+
+For example, the following constructor and conversion function are
+not explicit as they lack the explicit specifier:
+
+class Foo {
+Foo();
+operator int();
+};
+
+While the following constructor and conversion function are
+explicit as they are declared with the explicit specifier.
+
+class Foo {
+explicit Foo();
+explicit operator int();
+};
+
+This method will return 0 when given a cursor pointing to one of
+the former declarations and it will return 1 for a cursor pointing
+to the latter declarations.
+
+The explicit specifier allows the user to specify a
+conditional compile-time expression whose value decides
+whether the marked element is explicit or not.
+
+For example:
+
+constexpr bool foo(int i) { return i % 2 == 0; }
+
+class Foo {
+ explicit(foo(1)) Foo();
+ explicit(foo(2)) operator int();
+}
+
+This method will return 0 for the constructor and 1 for
+the conversion function.
+"""
+return conf.lib.clang_CXXMethod_isExplicit(self)
+
 def is_mutable_field(self):
 """Returns True if the cursor refers to a C++ field that is declared
 'mutable'.
@@ -3494,6 +3539,10 @@ def cursor(self):
[Cursor],
bool),
 
+  ("clang_CXXMethod_isExplicit",
+   [Cursor],
+   bool),

[clang] ddbe140 - Add clang_CXXMethod_isExplicit to libclang

2023-01-23 Thread Luca Di Sera via cfe-commits

Author: Luca Di Sera
Date: 2023-01-23T11:30:38+01:00
New Revision: ddbe14084da7f31d4b4b53e13d9f868d759f3673

URL: 
https://github.com/llvm/llvm-project/commit/ddbe14084da7f31d4b4b53e13d9f868d759f3673
DIFF: 
https://github.com/llvm/llvm-project/commit/ddbe14084da7f31d4b4b53e13d9f868d759f3673.diff

LOG: Add clang_CXXMethod_isExplicit to libclang

The new method is a wrapper of `CXXConstructorDecl::isExplicit` and
`CXXConversionDecl::isExplicit`, allowing the user to recognize whether
the declaration pointed to by a cursor was marked with the explicit
specifier.

An export for the function, together with its documentation, was added
to "clang/include/clang-c/Index.h" with an implementation provided in
"clang/tools/libclang/CIndex.cpp".

The implementation is based on similar `clang_CXXMethod`
implementations, returning a falsy unsigned value when the cursor is not
a declaration, is not a declaration for a constructor or conversion
function or is not a relevant declaration that was marked with the
`explicit` specifier.

The new symbol was added to "clang/tools/libclang/libclang.map" to be
exported, under the LLVM16 tag.

"clang/tools/c-index-test/c-index-test.c" was modified to print a
specific tag, "(explicit)", for cursors that are recognized by
`clang_CXXMethod_isExplicit`.

Two new regression files, "explicit-constructor.cpp" and
"explicit-conversion-function.cpp", were added to "clang/test/Index", to
ensure that the behavior of the new function is correct for constructors
and conversion functions, respectively.

The "get-cursor.cpp", "index-file.cpp" and
"recursive-cxx-member-calls.cpp" regression files in "clang/test/Index"
were updated as they were affected by the new "(explicit)" tag.

A binding for the new function was added to libclang's python's
bindings, in "clang/bindings/python/clang/cindex.py", as the
"is_explicit_method" method under `Cursor`.

An accompanying test was added to
"clang/bindings/python/tests/cindex/test_cursor.py", mimicking the
regression tests for the C side.

The current release note for Clang, "clang/docs/ReleaseNotes.rst" was
modified to report the new addition under the "libclang" section.

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D140756

Added: 
clang/test/Index/explicit-constructor.cpp
clang/test/Index/explicit-conversion-function.cpp

Modified: 
clang/bindings/python/clang/cindex.py
clang/bindings/python/tests/cindex/test_cursor.py
clang/docs/ReleaseNotes.rst
clang/include/clang-c/Index.h
clang/test/Index/get-cursor.cpp
clang/test/Index/index-file.cpp
clang/test/Index/recursive-cxx-member-calls.cpp
clang/tools/c-index-test/c-index-test.c
clang/tools/libclang/CIndex.cpp
clang/tools/libclang/libclang.map

Removed: 




diff  --git a/clang/bindings/python/clang/cindex.py 
b/clang/bindings/python/clang/cindex.py
index 2e32ce2ba6d06..217873f2d3aaf 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -1529,6 +1529,51 @@ class Bar {
 """
 return conf.lib.clang_CXXMethod_isMoveAssignmentOperator(self)
 
+def is_explicit_method(self):
+"""Determines if a C++ constructor or conversion function is
+explicit, returning 1 if such is the case and 0 otherwise.
+
+Constructors or conversion functions are declared explicit through
+the use of the explicit specifier.
+
+For example, the following constructor and conversion function are
+not explicit as they lack the explicit specifier:
+
+class Foo {
+Foo();
+operator int();
+};
+
+While the following constructor and conversion function are
+explicit as they are declared with the explicit specifier.
+
+class Foo {
+explicit Foo();
+explicit operator int();
+};
+
+This method will return 0 when given a cursor pointing to one of
+the former declarations and it will return 1 for a cursor pointing
+to the latter declarations.
+
+The explicit specifier allows the user to specify a
+conditional compile-time expression whose value decides
+whether the marked element is explicit or not.
+
+For example:
+
+constexpr bool foo(int i) { return 1 % 2 == 0; }
+
+class Foo {
+ explicit(foo(1)) Foo();
+ explicit(foo(2)) operator int();
+}
+
+This method will return 0 for the constructor and 1 for
+the conversion function.
+"""
+return conf.lib.clang_CXXMethod_isExplicit(self)
+
 def is_mutable_field(self):
 """Returns True if the cursor refers to a C++ field that is declared
 'mutable'.
@@ -3494,6 +3539,10 @@ def cursor(self):
[Cursor],
bool),
 
+  ("clang_CXXMethod_isExp

[clang] 1af7164 - Revert "Add clang_CXXMethod_isExplicit to libclang"

2023-01-23 Thread Luca Di Sera via cfe-commits

Author: Luca Di Sera
Date: 2023-01-23T12:55:34+01:00
New Revision: 1af716499d6bc29afd9ff2903200890df774859f

URL: 
https://github.com/llvm/llvm-project/commit/1af716499d6bc29afd9ff2903200890df774859f
DIFF: 
https://github.com/llvm/llvm-project/commit/1af716499d6bc29afd9ff2903200890df774859f.diff

LOG: Revert "Add clang_CXXMethod_isExplicit to libclang"

This is currently failing the build due to some test errors.

This reverts commit ddbe14084da7f31d4b4b53e13d9f868d759f3673.

Added: 


Modified: 
clang/bindings/python/clang/cindex.py
clang/bindings/python/tests/cindex/test_cursor.py
clang/docs/ReleaseNotes.rst
clang/include/clang-c/Index.h
clang/test/Index/get-cursor.cpp
clang/test/Index/index-file.cpp
clang/test/Index/recursive-cxx-member-calls.cpp
clang/tools/c-index-test/c-index-test.c
clang/tools/libclang/CIndex.cpp
clang/tools/libclang/libclang.map

Removed: 
clang/test/Index/explicit-constructor.cpp
clang/test/Index/explicit-conversion-function.cpp



diff  --git a/clang/bindings/python/clang/cindex.py 
b/clang/bindings/python/clang/cindex.py
index 217873f2d3aaf..2e32ce2ba6d06 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -1529,51 +1529,6 @@ class Bar {
 """
 return conf.lib.clang_CXXMethod_isMoveAssignmentOperator(self)
 
-def is_explicit_method(self):
-"""Determines if a C++ constructor or conversion function is
-explicit, returning 1 if such is the case and 0 otherwise.
-
-Constructors or conversion functions are declared explicit through
-the use of the explicit specifier.
-
-For example, the following constructor and conversion function are
-not explicit as they lack the explicit specifier:
-
-class Foo {
-Foo();
-operator int();
-};
-
-While the following constructor and conversion function are
-explicit as they are declared with the explicit specifier.
-
-class Foo {
-explicit Foo();
-explicit operator int();
-};
-
-This method will return 0 when given a cursor pointing to one of
-the former declarations and it will return 1 for a cursor pointing
-to the latter declarations.
-
-The explicit specifier allows the user to specify a
-conditional compile-time expression whose value decides
-whether the marked element is explicit or not.
-
-For example:
-
-constexpr bool foo(int i) { return 1 % 2 == 0; }
-
-class Foo {
- explicit(foo(1)) Foo();
- explicit(foo(2)) operator int();
-}
-
-This method will return 0 for the constructor and 1 for
-the conversion function.
-"""
-return conf.lib.clang_CXXMethod_isExplicit(self)
-
 def is_mutable_field(self):
 """Returns True if the cursor refers to a C++ field that is declared
 'mutable'.
@@ -3539,10 +3494,6 @@ def cursor(self):
[Cursor],
bool),
 
-  ("clang_CXXMethod_isExplicit",
-   [Cursor],
-   bool),
-
   ("clang_CXXMethod_isPureVirtual",
[Cursor],
bool),

diff  --git a/clang/bindings/python/tests/cindex/test_cursor.py 
b/clang/bindings/python/tests/cindex/test_cursor.py
index 74f7445cbc3ef..198352080c69f 100644
--- a/clang/bindings/python/tests/cindex/test_cursor.py
+++ b/clang/bindings/python/tests/cindex/test_cursor.py
@@ -277,57 +277,6 @@ class Bar {
 for cursor in non_move_assignment_operators_cursors
 ]))
 
-def test_is_explicit_method(self):
-"""Ensure Cursor.is_explicit_method works."""
-source_with_explicit_methods = """
-struct Foo {
-   // Those are explicit
-   explicit Foo(double);
-   explicit(true) Foo(char);
-   explicit operator double();
-   explicit(true) operator char();
-};
-"""
-source_without_explicit_methods = """
-struct Foo {
-// Those are not explicit
-Foo(int);
-explicit(false) Foo(float);
-operator int();
-explicit(false) operator float();
-};
-"""
-tu_with_explicit_methods = get_tu(
-source_with_explicit_methods, lang="cpp"
-)
-tu_without_explicit_methods = get_tu(
-source_without_explicit_methods, lang="cpp"
-)
-
-explicit_methods_cursors = [
-*get_cursors(tu_with_explicit_methods, "Foo")[1:],
-get_cursor(tu_with_explicit_methods, "operator double"),
-get_cursor(tu_with_explicit_methods, "operator char"),
-]
-
-non_explicit_methods_cursors = [
-*get_cursors(tu_without_explicit_methods, "Foo")[1:],
-get_cursor(tu_without_explicit_me

[clang] Qualify non-dependent types of a class template with the class declar… (PR #67566)

2023-09-27 Thread Luca Di sera via cfe-commits

https://github.com/diseraluca created 
https://github.com/llvm/llvm-project/pull/67566

…ation

When
`clang::TypeName::getFullyQualifiedType`/`clang::TypeName::getFullyQualifiedName`
 encounter a non-dependent type/type alias that is defined under a templated 
class/struct, it qualifies the type/type alias under a specialization of the 
templated class, if any was declared.

That is, in:

```
template
class Foo {
using Bar = T;
}

using Baz = Foo;
```

Usages of `Foo::Bar` will be qualified as `Foo::Bar`.

When the `using Baz = Foo;` line is removed, as there are would be no 
specialization encountered in the translation unit, usages of `Foo::Bar` would 
instead be qualified as `Foo::Bar`.

When multiple specializations are present, the one that is chosen is the first 
one that is encountered; due to the current implementation of the behavior and 
the fact that iterating the specialization of a `ClassTemplateDecl` respects 
the order in which the specializations were stored in.

That is, if we were to add a reference to some other specialization in the 
above example, so that it would be parsed before the current `using Baz = 
Foo;`, say:

```
template
class Foo {
using Bar = T;
}

using Bat = Foo;
using Baz = Foo;
```

Then usages of `Foo::Bar` would be qualified as `Foo::Bar` instead of 
`Foo::Bar`.

Should the same declaration be added, instead, after the `using Baz = 
Foo;` line, then the qualification would remain consistent with our 
previous version.

To provide a more consistent behavior, that avoids changing the output when 
relatively unrelated declarations are present in the translation unit,
`clang::TypeName::getFullyQualifiedType`/`clang::TypeName::getFullyQualifiedName`
 will now qualify such types using the original templated declaration instead 
of one of the specializations.

>From 34b4e7939c88627ce433c96cdcc5e54d71ada94d Mon Sep 17 00:00:00 2001
From: Luca Di Sera 
Date: Wed, 27 Sep 2023 15:20:22 +0200
Subject: [PATCH] Qualify non-dependent types of a class template with the
 class declaration

When
`clang::TypeName::getFullyQualifiedType`/`clang::TypeName::getFullyQualifiedName`
encounter a non-dependent type/type alias that is defined under a templated
class/struct, it qualifies the type/type alias under a specialization of
the templated class, if any was declared.

That is, in:

```
template
class Foo {
using Bar = T;
}

using Baz = Foo;
```

Usages of `Foo::Bar` will be qualified as `Foo::Bar`.

When the `using Baz = Foo;` line is removed, as there are would be no
specialization encountered in the translation unit, usages of
`Foo::Bar` would instead be qualified as `Foo::Bar`.

When multiple specializations are present, the one that is chosen is the
first one that is encountered; due to the current implementation of the
behavior and the fact that iterating the specialization of a
`ClassTemplateDecl` respects the order in which the specializations were
stored in.

That is, if we were to add a reference to some other specialization in
the above example, so that it would be parsed before the current `using
Baz = Foo;`, say:

```
template
class Foo {
using Bar = T;
}

using Bat = Foo;
using Baz = Foo;
```

Then usages of `Foo::Bar` would be qualified as `Foo::Bar`
instead of `Foo::Bar`.

Should the same declaration be added, instead, after the `using Baz =
Foo;` line, then the qualification would remain consistent with our
previous version.

To provide a more consistent behavior, that avoids changing the output
when relatively unrelated declarations are present in the translation
unit,
`clang::TypeName::getFullyQualifiedType`/`clang::TypeName::getFullyQualifiedName`
will now qualify such types using the original templated declaration
instead of one of the specializations.
---
 clang/lib/AST/QualTypeNames.cpp   | 21 -
 clang/unittests/Tooling/QualTypeNamesTest.cpp | 83 +--
 2 files changed, 40 insertions(+), 64 deletions(-)

diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp
index 7557336f0aafa88..32fba2ab887d27c 100644
--- a/clang/lib/AST/QualTypeNames.cpp
+++ b/clang/lib/AST/QualTypeNames.cpp
@@ -272,27 +272,6 @@ static NestedNameSpecifier 
*createNestedNameSpecifierForScopeOf(
   const auto *Outer = dyn_cast_or_null(DC);
   const auto *OuterNS = dyn_cast_or_null(DC);
   if (Outer && !(OuterNS && OuterNS->isAnonymousNamespace())) {
-if (const auto *CxxDecl = dyn_cast(DC)) {
-  if (ClassTemplateDecl *ClassTempl =
-  CxxDecl->getDescribedClassTemplate()) {
-// We are in the case of a type(def) that was declared in a
-// class template but is *not* type dependent.  In clang, it
-// gets attached to the class template declaration rather than
-// any specific class template instantiation.  This result in
-// 'odd' fully qualified typename:
-//
-//vector<_Tp,_Alloc>::size_type
-//
-// Make the situation is 'useable' but loo

[clang] Qualify non-dependent types of a class template with the class declar… (PR #67566)

2023-09-27 Thread Luca Di sera via cfe-commits

diseraluca wrote:

This might be a breaking change, so I'm not sure if it will be
possible to merge it, but I would like to give some context on where
the change is coming from.

I'm trying (in my position as an employee of The Qt Company), to
migrate our documentation generation tool, QDoc, which depends on both
of Clang's C and C++ APIs, and similarly our CI systems, to support
LLVM 16 and 17 to catch up with the current releases.

Due to a bug fix that happened between 15 and 16, our product behaves
differently on the two versions, and we are using
`clang::TypeName::getFullyQualifiedType`/`clang::TypeName::getFullyQualifiedName`
to stabilize the software behavior on pre-16 and post-16 LLVM
releases, which is the suggested migration path
( https://github.com/llvm/llvm-project/issues/61810 ,
https://github.com/llvm/llvm-project/issues/58040 ).

Using those functions has been generally working for us, but the
behavior that I'm changing in this patch has been a blocker.

As a documentation generation tool we generally require a certain
consistency between generations of different version of the same
codebase, unless something in the code changed so that it justifies
the changes in the documentation itself.

Due to Qt's codebase being quite convoluted, we don't really have too
much control about the order that certain specializations will be
encountered in, albeit we could do some trick to try and control that
from QDoc.

Nonetheless, we are generally required to have the output be stable
when the documented code is not meaningfully changed between release
sets of our documentation.

Having the produced output change because of the first encountered
specialization changing in the codebase is not feasible, as it break
this desiderable property of a documentation set and may break our
regression-testing suite that is enforced in CI.

Furthermore, the chosen specialization may produce incorrect
information, which we cannot show to the end user of the documentation
set.

For example, we currently have `QFuture` define a `const_iterator`
alias that is later used as the argument or return type of some of our
documented callables.

Due to the way the current codebase is set up, the chosen
specialization is `QFuture` so that, for example,
`QFuture::constBegin()` would be shown to the user as returning a
`QFuture::const_iterator`.
Nonetheless, `QFuture` is the only specialization that cannot
have a `const_iterator` and, as a consequence, doesn't have a
`constBegin` method in the first place.

It is obviously impossible to have this change in 16/17.
My current plan is to maintain our own implementation of
`clang::TypeName::getFullyQualifiedType`/`clang::TypeName::getFullyQualifiedName`,
but would prefer to be able to converge back when we can consider 18
the minimum version needed for QDoc, quite far in the future.

I further generally think that a more stable output is a preferred
property for this type of computations considering the possible
usages, such that the lack of the current behavior is either a better
default or a non-meaningful change in many expected usages.


https://github.com/llvm/llvm-project/pull/67566
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Qualify non-dependent types of a class template with the class declar… (PR #67566)

2023-09-27 Thread Luca Di sera via cfe-commits

https://github.com/diseraluca updated 
https://github.com/llvm/llvm-project/pull/67566

>From 34b4e7939c88627ce433c96cdcc5e54d71ada94d Mon Sep 17 00:00:00 2001
From: Luca Di Sera 
Date: Wed, 27 Sep 2023 15:20:22 +0200
Subject: [PATCH 1/2] Qualify non-dependent types of a class template with the
 class declaration

When
`clang::TypeName::getFullyQualifiedType`/`clang::TypeName::getFullyQualifiedName`
encounter a non-dependent type/type alias that is defined under a templated
class/struct, it qualifies the type/type alias under a specialization of
the templated class, if any was declared.

That is, in:

```
template
class Foo {
using Bar = T;
}

using Baz = Foo;
```

Usages of `Foo::Bar` will be qualified as `Foo::Bar`.

When the `using Baz = Foo;` line is removed, as there are would be no
specialization encountered in the translation unit, usages of
`Foo::Bar` would instead be qualified as `Foo::Bar`.

When multiple specializations are present, the one that is chosen is the
first one that is encountered; due to the current implementation of the
behavior and the fact that iterating the specialization of a
`ClassTemplateDecl` respects the order in which the specializations were
stored in.

That is, if we were to add a reference to some other specialization in
the above example, so that it would be parsed before the current `using
Baz = Foo;`, say:

```
template
class Foo {
using Bar = T;
}

using Bat = Foo;
using Baz = Foo;
```

Then usages of `Foo::Bar` would be qualified as `Foo::Bar`
instead of `Foo::Bar`.

Should the same declaration be added, instead, after the `using Baz =
Foo;` line, then the qualification would remain consistent with our
previous version.

To provide a more consistent behavior, that avoids changing the output
when relatively unrelated declarations are present in the translation
unit,
`clang::TypeName::getFullyQualifiedType`/`clang::TypeName::getFullyQualifiedName`
will now qualify such types using the original templated declaration
instead of one of the specializations.
---
 clang/lib/AST/QualTypeNames.cpp   | 21 -
 clang/unittests/Tooling/QualTypeNamesTest.cpp | 83 +--
 2 files changed, 40 insertions(+), 64 deletions(-)

diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp
index 7557336f0aafa88..32fba2ab887d27c 100644
--- a/clang/lib/AST/QualTypeNames.cpp
+++ b/clang/lib/AST/QualTypeNames.cpp
@@ -272,27 +272,6 @@ static NestedNameSpecifier 
*createNestedNameSpecifierForScopeOf(
   const auto *Outer = dyn_cast_or_null(DC);
   const auto *OuterNS = dyn_cast_or_null(DC);
   if (Outer && !(OuterNS && OuterNS->isAnonymousNamespace())) {
-if (const auto *CxxDecl = dyn_cast(DC)) {
-  if (ClassTemplateDecl *ClassTempl =
-  CxxDecl->getDescribedClassTemplate()) {
-// We are in the case of a type(def) that was declared in a
-// class template but is *not* type dependent.  In clang, it
-// gets attached to the class template declaration rather than
-// any specific class template instantiation.  This result in
-// 'odd' fully qualified typename:
-//
-//vector<_Tp,_Alloc>::size_type
-//
-// Make the situation is 'useable' but looking a bit odd by
-// picking a random instance as the declaring context.
-if (ClassTempl->spec_begin() != ClassTempl->spec_end()) {
-  Decl = *(ClassTempl->spec_begin());
-  Outer = dyn_cast(Decl);
-  OuterNS = dyn_cast(Decl);
-}
-  }
-}
-
 if (OuterNS) {
   return createNestedNameSpecifier(Ctx, OuterNS, WithGlobalNsPrefix);
 } else if (const auto *TD = dyn_cast(Outer)) {
diff --git a/clang/unittests/Tooling/QualTypeNamesTest.cpp 
b/clang/unittests/Tooling/QualTypeNamesTest.cpp
index 686d189cf69eb2f..18286f9e74921dd 100644
--- a/clang/unittests/Tooling/QualTypeNamesTest.cpp
+++ b/clang/unittests/Tooling/QualTypeNamesTest.cpp
@@ -85,7 +85,7 @@ TEST(QualTypeNameTest, Simple) {
   // Namespace alias
   Visitor.ExpectedQualTypeNames["CheckL"] = "A::B::C::MyInt";
   Visitor.ExpectedQualTypeNames["non_dependent_type_var"] =
-  "Foo::non_dependent_type";
+  "Foo::non_dependent_type";
   Visitor.ExpectedQualTypeNames["AnEnumVar"] = "EnumScopeClass::AnEnum";
   Visitor.ExpectedQualTypeNames["AliasTypeVal"] = "A::B::C::InnerAlias";
   Visitor.ExpectedQualTypeNames["AliasInnerTypeVal"] =
@@ -175,20 +175,19 @@ TEST(QualTypeNameTest, Simple) {
 TEST(QualTypeNameTest, Complex) {
   TypeNameVisitor Complex;
   Complex.ExpectedQualTypeNames["CheckTX"] = "B::TX";
-  Complex.runOver(
-  "namespace A {"
-  "  struct X {};"
-  "}"
-  "using A::X;"
-  "namespace fake_std {"
-  "  template class tuple {};"
-  "}"
-  "namespace B {"
-  "  using fake_std::tuple;"
-  "  typedef tuple TX;"
-  "  TX CheckTX;"
-  "  struct A { typedef int X; };"
-  "}");
+  Complex.runOver("namespace A {"
+  "  s

[clang] Qualify non-dependent types of a class template with the class declar… (PR #67566)

2023-09-27 Thread Luca Di sera via cfe-commits

https://github.com/diseraluca updated 
https://github.com/llvm/llvm-project/pull/67566

>From d19d716609034465bf6be814a322f26c1ea619c9 Mon Sep 17 00:00:00 2001
From: Luca Di Sera 
Date: Wed, 27 Sep 2023 15:20:22 +0200
Subject: [PATCH] Qualify non-dependent types of a class template with its
 declaration

When
`clang::TypeName::getFullyQualifiedType`/`clang::TypeName::getFullyQualifiedName`
encounter a non-dependent type/type alias that is defined under a templated
class/struct, it qualifies the type/type alias under a specialization of
the templated class, if any was declared.

That is, in:

```
template
class Foo {
using Bar = T;
}

using Baz = Foo;
```

Usages of `Foo::Bar` will be qualified as `Foo::Bar`.

When the `using Baz = Foo;` line is removed, as there are would be no
specialization encountered in the translation unit, usages of
`Foo::Bar` would instead be qualified as `Foo::Bar`.

When multiple specializations are present, the one that is chosen is the
first one that is encountered; due to the current implementation of the
behavior and the fact that iterating the specialization of a
`ClassTemplateDecl` respects the order in which the specializations were
stored in.

That is, if we were to add a reference to some other specialization in
the above example, so that it would be parsed before the current `using
Baz = Foo;`, say:

```
template
class Foo {
using Bar = T;
}

using Bat = Foo;
using Baz = Foo;
```

Then usages of `Foo::Bar` would be qualified as `Foo::Bar`
instead of `Foo::Bar`.

Should the same declaration be added, instead, after the `using Baz =
Foo;` line, then the qualification would remain consistent with our
previous version.

To provide a more consistent behavior, that avoids changing the output
when relatively unrelated declarations are present in the translation
unit,
`clang::TypeName::getFullyQualifiedType`/`clang::TypeName::getFullyQualifiedName`
will now qualify such types using the original templated declaration
instead of one of the specializations.
---
 clang/lib/AST/QualTypeNames.cpp   | 49 ---
 clang/unittests/Tooling/QualTypeNamesTest.cpp | 83 +--
 2 files changed, 54 insertions(+), 78 deletions(-)

diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp
index 7557336f0aafa88..6ed5c9c3b2dee24 100644
--- a/clang/lib/AST/QualTypeNames.cpp
+++ b/clang/lib/AST/QualTypeNames.cpp
@@ -272,43 +272,22 @@ static NestedNameSpecifier 
*createNestedNameSpecifierForScopeOf(
   const auto *Outer = dyn_cast_or_null(DC);
   const auto *OuterNS = dyn_cast_or_null(DC);
   if (Outer && !(OuterNS && OuterNS->isAnonymousNamespace())) {
-if (const auto *CxxDecl = dyn_cast(DC)) {
-  if (ClassTemplateDecl *ClassTempl =
-  CxxDecl->getDescribedClassTemplate()) {
-// We are in the case of a type(def) that was declared in a
-// class template but is *not* type dependent.  In clang, it
-// gets attached to the class template declaration rather than
-// any specific class template instantiation.  This result in
-// 'odd' fully qualified typename:
-//
-//vector<_Tp,_Alloc>::size_type
-//
-// Make the situation is 'useable' but looking a bit odd by
-// picking a random instance as the declaring context.
-if (ClassTempl->spec_begin() != ClassTempl->spec_end()) {
-  Decl = *(ClassTempl->spec_begin());
-  Outer = dyn_cast(Decl);
-  OuterNS = dyn_cast(Decl);
-}
+  if (OuterNS) {
+return createNestedNameSpecifier(Ctx, OuterNS, WithGlobalNsPrefix);
+  } else if (const auto *TD = dyn_cast(Outer)) {
+return createNestedNameSpecifier(Ctx, TD, FullyQualified,
+ WithGlobalNsPrefix);
+  } else if (isa(Outer)) {
+// Context is the TU. Nothing needs to be done.
+return nullptr;
+  } else {
+// Decl's context was neither the TU, a namespace, nor a
+// TagDecl, which means it is a type local to a scope, and not
+// accessible at the end of the TU.
+return nullptr;
   }
-}
-
-if (OuterNS) {
-  return createNestedNameSpecifier(Ctx, OuterNS, WithGlobalNsPrefix);
-} else if (const auto *TD = dyn_cast(Outer)) {
-  return createNestedNameSpecifier(
-  Ctx, TD, FullyQualified, WithGlobalNsPrefix);
-} else if (isa(Outer)) {
-  // Context is the TU. Nothing needs to be done.
-  return nullptr;
-} else {
-  // Decl's context was neither the TU, a namespace, nor a
-  // TagDecl, which means it is a type local to a scope, and not
-  // accessible at the end of the TU.
-  return nullptr;
-}
   } else if (WithGlobalNsPrefix && DC->isTranslationUnit()) {
-return NestedNameSpecifier::GlobalSpecifier(Ctx);
+  return NestedNameSpecifier::GlobalSpecifier(Ctx);
   }
   return nullptr;
 }
diff --git a/clang/unittests/Tooling/QualTypeName

[clang] Qualify non-dependent types of a class template with its declaration (PR #67566)

2023-09-27 Thread Luca Di sera via cfe-commits

https://github.com/diseraluca edited 
https://github.com/llvm/llvm-project/pull/67566
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Qualify non-dependent types of a class template with its declaration (PR #67566)

2023-09-27 Thread Luca Di sera via cfe-commits

https://github.com/diseraluca edited 
https://github.com/llvm/llvm-project/pull/67566
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Qualify non-dependent types of a class template with its declaration (PR #67566)

2023-09-27 Thread Luca Di sera via cfe-commits

diseraluca wrote:

Run clang-format on the patch.

I made a bit of a mess as I haven't used the PR model in a very long time. 
Hopefully this is correct.

https://github.com/llvm/llvm-project/pull/67566
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Qualify non-dependent types of a class template with its declaration (PR #67566)

2023-09-29 Thread Luca Di sera via cfe-commits

diseraluca wrote:

> @diseraluca, thanks for the thorough description. The point of these routines 
> is to produce code that compiles. I am not sure if we change `Foo::Bar` 
> with `Foo::Bar` it will compile.
> 
> > Due to the way the current codebase is set up, the chosen specialization is 
> > `QFuture` so that, for example, `QFuture::constBegin()` would be 
> > shown to the user as returning a `QFuture::const_iterator`. 
> > Nonetheless, `QFuture` is the only specialization that cannot have a 
> > `const_iterator` and, as a consequence, doesn't have a `constBegin` method 
> > in the first place.
> 
> I suspect that `QFuture` is an explicit specialization. The intent of 
> the code was to pick up an implicit specialization which follows much more 
> closely the template pattern. Would selecting the first non-explicit 
> instantiation fix your usecase?

Thank you for your answer @vgvassilev.

I gave it a quick try, and we would still end up with the same result in our 
codebase. But, generally, this would not probably be feasible for us as a 
solution.

Since that is the case, and we have somewhat conflicting requirements, I think 
the best path would be for me to indefinitely maintain a custom implementation 
of `getFullyQualified*`, leaving upstream as is.

I would thus suggest to close this without merging.

https://github.com/llvm/llvm-project/pull/67566
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Qualify non-dependent types of a class template with its declaration (PR #67566)

2023-09-29 Thread Luca Di sera via cfe-commits

diseraluca wrote:

> > I gave it a quick try, and we would still end up with the same result in 
> > our codebase. But, generally, this would not probably be feasible for us as 
> > a solution.
> 
> do you have an idea why? Can you show the diff of the changes you made? Is 
> the void specialization not explicit?

I did a quick test with this:

```
diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp
index 26aaa96a1dc6..8b882eda83bb 100644
--- a/clang/lib/AST/QualTypeNames.cpp
+++ b/clang/lib/AST/QualTypeNames.cpp
@@ -287,8 +287,13 @@ static NestedNameSpecifier 
*createNestedNameSpecifierForScopeOf(
 //
 // Make the situation is 'useable' but looking a bit odd by
 // picking a random instance as the declaring context.
-if (ClassTempl->spec_begin() != ClassTempl->spec_end()) {
-  Decl = *(ClassTempl->spec_begin());
+auto specialization_iterator = std::find_if(
+ClassTempl->spec_begin(), ClassTempl->spec_end(), [](auto a) {
+  return !a->isExplicitInstantiationOrSpecialization();
+});
+
+if (specialization_iterator != ClassTempl->spec_end()) {
+  Decl = *specialization_iterator;
   Outer = dyn_cast(Decl);
   OuterNS = dyn_cast(Decl);
 }
```

Do please let me know if this is incorrect or if I misunderstood your proposal.

We do have explicit references to the void specialization in the codebase so it 
would explain the previous choice. But I'm not aware of why it would be chosen 
as a non-explicit one too.

I can try to debug that on Monday if that can be useful. Albeit it might take 
some time.

https://github.com/llvm/llvm-project/pull/67566
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Qualify non-dependent types of a class template with its declaration (PR #67566)

2023-09-30 Thread Luca Di sera via cfe-commits

diseraluca wrote:

> > > > I gave it a quick try, and we would still end up with the same result 
> > > > in our codebase. But, generally, this would not probably be feasible 
> > > > for us as a solution.
> > > 
> > > 
> > > do you have an idea why? Can you show the diff of the changes you made? 
> > > Is the void specialization not explicit?
> > 
> > 
> > I did a quick test with this:
> > ```
> > diff --git a/clang/lib/AST/QualTypeNames.cpp 
> > b/clang/lib/AST/QualTypeNames.cpp
> > index 26aaa96a1dc6..8b882eda83bb 100644
> > --- a/clang/lib/AST/QualTypeNames.cpp
> > +++ b/clang/lib/AST/QualTypeNames.cpp
> > @@ -287,8 +287,13 @@ static NestedNameSpecifier 
> > *createNestedNameSpecifierForScopeOf(
> >  //
> >  // Make the situation is 'useable' but looking a bit odd by
> >  // picking a random instance as the declaring context.
> > -if (ClassTempl->spec_begin() != ClassTempl->spec_end()) {
> > -  Decl = *(ClassTempl->spec_begin());
> > +auto specialization_iterator = std::find_if(
> > +ClassTempl->spec_begin(), ClassTempl->spec_end(), [](auto a) {
> > +  return !a->isExplicitInstantiationOrSpecialization();
> > +});
> > +
> > +if (specialization_iterator != ClassTempl->spec_end()) {
> > +  Decl = *specialization_iterator;
> >Outer = dyn_cast(Decl);
> >OuterNS = dyn_cast(Decl);
> >  }
> > ```
> > 
> > 
> > 
> >   
> > 
> > 
> >   
> > 
> > 
> > 
> >   
> > Do please let me know if this is incorrect or if I misunderstood your 
> > proposal.
> > We do have explicit references to the void specialization in the codebase 
> > so it would explain the previous choice. But I'm not aware of why it would 
> > be chosen as a non-explicit one too.
> > I can try to debug that on Monday if that can be useful. Albeit it might 
> > take some time.
> 
> You probably need 
> [isExplicitSpecialization](https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html#acd75ba25d34249d2e21ebbecbb2ef70e)()

Wouldn't `isExplicitSpecializationOrInstantiation` be a stronger guarantee than 
isExplicitSpecialization, such that it would exclude a superset of what is 
excluded by `isExplicitSpecialization`? If I did not misunderstand their source 
code.

Nonetheless, I've made a test run with `isExplicitSpecialization`, but in Qt's 
codebase we still get the same result.

I generally don't think we can depend on this kind of behavior, especially as 
it is far too difficult to control for the kind of consistency we want.

I initially missed the fact that the intention of this was to produce 
compilable code. While similar to our use-case it has slightly different 
requirements and I feel that may not be compatible with ours.

I think that is fine, and I think we don't need to force it to work for all use 
cases,  especially because I really don't want to break other people code. My 
assumption was that this might be an improvement for other use-cases too, but I 
failed to see the "give me code that compiles" use case.

The only thing that comes to mind would be to condition the behavior to be 
there or not. Similar to how we have `WighGlobalNsPrefix` we might have another 
boolean or similar, so that the default behavior remains the same but it can be 
conditioned to avoid this case.

But I don't think that is a particularly good solution, so I'm pretty happy 
with maintaining our own version too.

https://github.com/llvm/llvm-project/pull/67566
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Qualify non-dependent types of a class template with its declaration (PR #67566)

2023-10-01 Thread Luca Di sera via cfe-commits

diseraluca wrote:

>  I still do not see why the proposed solution would not work. If it solves 
> the minimal case that you provided in the description of this PR, I am afraid 
> that there is some bit from the Qt setup that we do not understand.

I cannot for certain say if there is an issue or not with how the Qt codebase 
is setup; but I think it is out of the scope of the task we are trying to solve 
to change that based on the behavior of QDoc interoperations with Clang.

For what it is worth, I've been playing with a very small example to check a 
few possibilities, and even excluding explicit specializations we still have 
certain cases that are not stable.

Say in

```
#pragma once

template
class QList {
public:
using Foo = const T&;

void begin(Foo);
};
```

Adding something as `using Bar = QList;`, and this being the only code in 
the translation unit, we still have the addition of such a line modifying our 
output, qualifying the type of the first parameter of `begin` as 
`QList::Foo`, even with your proposal.

Say we can stabilize that, so that it always qualify in the same way, say 
`QList`.

If we are documenting, maybe, some method `QList::Foo QList::bar()` and 
we show to the user the return type as `QList::Foo`, this is going to be 
misleading, 
albeit not as erroneous as the `QFuture` case, for our user.

Indeed, the return type of `bar` really depends on the instantiation of `QList` 
that we are looking at and it would be extremely confusing for a user skimming 
our documentation to think that it always returns a `QList::Foo`.
As a documentation generator we really want to look at the generic case for our 
output.

Now, say we have a very stable output, albeit not adequate for our case, it 
might simplify doing some postprocessing to qualify in the way we want, but at 
that point we still need to maintain something relatively similar to 
`getFullyQualified*`, thus why it isn't that much of a difference for our use 
case to only have a more stable output.

There are some other cases that might be iffy for our use-case too, with this 
behavior.

Thus why I think, albeit unfortunate, our use-cases just happen to be somewhat 
in conflict with regards to the output of `getFullyQualified*`.

@vgvassilev  Both me an my team are deeply thankful for your help. It was 
really kind to try and find a solution for our case.

I will close this PR as I don't think it can be merged, as it would break other 
people use cases.
I will leave it open 1 or 2 days more in case someone else wants to chime in 
with something.

https://github.com/llvm/llvm-project/pull/67566
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Qualify non-dependent types of a class template with its declaration (PR #67566)

2023-10-01 Thread Luca Di sera via cfe-commits

diseraluca wrote:

@vgvassilev  If that is an acceptable interface for the LLVM interface then, 
yes, it would be perfect from our side, and I'm more than happy to update the 
PR in the next few days.

Just to be sure that I understood your proposal.

`getFullyQualified*` calls will accept a new parameter, a callable, that will 
be down the call chain up to `createNestedNameSpecifierForScopeOf(const 
ASTContext &, const Decl *, ...)` and will be called when the teplate case is 
encountered?
Or are you thinking more of a callable that replaces the call to 
`createNestedNameSpecifierForScopeOf(const ASTContext &, const Decl *, ...)`?

https://github.com/llvm/llvm-project/pull/67566
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Qualify non-dependent types of a class template with its declaration (PR #67566)

2023-10-04 Thread Luca Di sera via cfe-commits

diseraluca wrote:

> > @vgvassilev If that is an acceptable interface for the LLVM interface then, 
> > yes, it would be perfect from our side, and I'm more than happy to update 
> > the PR in the next few days.
> > Just to be sure that I understood your proposal.
> > `getFullyQualified*` calls will accept a new parameter, a callable, that 
> > will be passed down the call chain up to 
> > `createNestedNameSpecifierForScopeOf(const ASTContext &, const Decl *, 
> > ...)` and will be called when the teplate case is encountered? Or are you 
> > thinking more of a callable that replaces the call to 
> > `createNestedNameSpecifierForScopeOf(const ASTContext &, const Decl *, 
> > ...)`?
> 
> I hesitate. Maybe we can pass a custom "policy" option and incorporate your 
> code in there... We reiterate if the solution does not look good?

>From our point of view any solution is acceptable. But do note that  from our 
>side it is not so much about incorporating custom code as much as removing 
>that specific behavior at this point in time.

Could you expand about the policy? Are you talking about a "printing policy" or 
a custom policy for `getFullyQualified`?

https://github.com/llvm/llvm-project/pull/67566
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Qualify non-dependent types of a class template with its declaration (PR #67566)

2023-10-17 Thread Luca Di sera via cfe-commits

diseraluca wrote:

Closing this one, as we intend to maintain our own local version.

https://github.com/llvm/llvm-project/pull/67566
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Qualify non-dependent types of a class template with its declaration (PR #67566)

2023-10-17 Thread Luca Di sera via cfe-commits

https://github.com/diseraluca closed 
https://github.com/llvm/llvm-project/pull/67566
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits