This is a major change on how we represent nested name qualifications in
the AST.
* The nested name specifier itself and how it's stored is changed. The
prefixes for types are handled within the type hierarchy, which makes
canonicalization for them super cheap, no memory allocation required.
Also translating a type into nested name specifier form becomes a no-op.
An identifier is stored as a DependentNameType. The nested name
specifier gains a lightweight handle class, to be used instead of
passing around pointers, which is similar to what is implemented for
TemplateName. There is still one free bit available, and this handle can
be used within a PointerUnion and PointerIntPair, which should keep
bit-packing aficionados happy.
* The ElaboratedType node is removed, all type nodes in which it could
previously apply to can now store the elaborated keyword and name
qualifier, tail allocating when present.
* TagTypes can now point to the exact declaration found when producing
these, as opposed to the previous situation of there only existing one
TagType per entity. This increases the amount of type sugar retained,
and can have several applications, for example in tracking module
ownership, and other tools which care about source file origins, such as
IWYU. These TagTypes are lazily allocated, in order to limit the
increase in AST size.
This patch offers a great performance benefit.
It greatly improves compilation time for
[stdexec](https://github.com/NVIDIA/stdexec). For one datapoint, for
`test_on2.cpp` in that project, which is the slowest compiling test,
this patch improves `-c` compilation time by about 7.2%, with the
`-fsyntax-only` improvement being at ~12%.
This has great results on compile-time-tracker as well:

This patch also further enables other optimziations in the future, and
will reduce the performance impact of template specialization resugaring
when that lands.
It has some other miscelaneous drive-by fixes.
About the review: Yes the patch is huge, sorry about that. Part of the
reason is that I started by the nested name specifier part, before the
ElaboratedType part, but that had a huge performance downside, as
ElaboratedType is a big performance hog. I didn't have the steam to go
back and change the patch after the fact.
There is also a lot of internal API changes, and it made sense to remove
ElaboratedType in one go, versus removing it from one type at a time, as
that would present much more churn to the users. Also, the nested name
specifier having a different API avoids missing changes related to how
prefixes work now, which could make existing code compile but not work.
How to review: The important changes are all in
`clang/include/clang/AST` and `clang/lib/AST`, with also important
changes in `clang/lib/Sema/TreeTransform.h`.
The rest and bulk of the changes are mostly consequences of the changes
in API.
PS: TagType::getDecl is renamed to `getOriginalDecl` in this patch, just
for easier to rebasing. I plan to rename it back after this lands.
Fixes#136624
Fixes https://github.com/llvm/llvm-project/issues/43179
Fixes https://github.com/llvm/llvm-project/issues/68670
Fixes https://github.com/llvm/llvm-project/issues/92757
Followup work of #140498 to continue the work on clangd/clangd#529
Introduce the use of the Clang doxygen parser to parse the documentation
of hovered code.
- ASTContext independent doxygen parsing
- Parsing doxygen commands to markdown for hover information
Note: after this PR I have planned another patch to rearrange the
information shown in the hover info.
This PR is just for the basic introduction of doxygen parsing for hover
information.
---------
Co-authored-by: Maksim Ivanov <emaxx@google.com>
This is a preparation for fixing clangd/clangd#529.
It changes the Markup rendering to markdown and plaintext.
- Properly separate paragraphs using an empty line between
- Dont escape markdown syntax for markdown output except for HTML
- Dont do any formatting for markdown because the client is handling the
actual markdown rendering
The checks for the 'z' and 't' format specifiers added in the original
PR #143653 had some issues and were overly strict, causing some build
failures and were consequently reverted at
4c85bf2fe8.
In the latest commit
27c58629ec,
I relaxed the checks for the 'z' and 't' format specifiers, so warnings
are now only issued when they are used with mismatched types.
The original intent of these checks was to diagnose code that assumes
the underlying type of `size_t` is `unsigned` or `unsigned long`, for
example:
```c
printf("%zu", 1ul); // Not portable, but not an error when size_t is unsigned long
```
However, it produced a significant number of false positives. This was
partly because Clang does not treat the `typedef` `size_t` and
`__size_t` as having a common "sugar" type, and partly because a large
amount of existing code either assumes `unsigned` (or `unsigned long`)
is `size_t`, or they define the equivalent of size_t in their own way
(such as
sanitizer_internal_defs.h).2e67dcfdcd/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h (L203)
Including the results of `sizeof`, `sizeof...`, `__datasizeof`,
`__alignof`, `_Alignof`, `alignof`, `_Countof`, `size_t` literals, and
signed `size_t` literals, the results of pointer-pointer subtraction and
checks for standard library functions (and their calls).
The goal is to enable clang and downstream tools such as clangd and
clang-tidy to provide more portable hints and diagnostics.
The previous discussion can be found at #136542.
This PR implements this feature by introducing a new subtype of `Type`
called `PredefinedSugarType`, which was considered appropriate in
discussions. I tried to keep `PredefinedSugarType` simple enough yet not
limited to `size_t` and `ptrdiff_t` so that it can be used for other
purposes. `PredefinedSugarType` wraps a canonical `Type` and provides a
name, conceptually similar to a compiler internal `TypedefType` but
without depending on a `TypedefDecl` or a source file.
Additionally, checks for the `z` and `t` format specifiers in format
strings for `scanf` and `printf` were added. It will precisely match
expressions using `typedef`s or built-in expressions.
The affected tests indicates that it works very well.
Several code require that `SizeType` is canonical, so I kept `SizeType`
to its canonical form.
The failed tests in CI are allowed to fail. See the
[comment](https://github.com/llvm/llvm-project/pull/135386#issuecomment-3049426611)
in another PR #135386.
This makes use of the changes introduced in D134604, in order to
instantiate alias templates witn a final sugared substitution.
This comes at no additional relevant cost.
Since we don't track / unique them in specializations, we wouldn't be
able to resugar them later anyway.
Differential Revision: https://reviews.llvm.org/D136565
This checks if the layout of `std::initializer_list` is something Clang
can handle much earlier and deduplicates the checks in
CodeGen/CGExprAgg.cpp and AST/ExprConstant.cpp
Also now diagnose `union initializer_list` (Fixes#95495), bit-field for
the size (Fixes a crash that would happen during codegen if it were
unnamed), base classes (that wouldn't be initialized) and polymorphic
classes (whose vtable pointer wouldn't be initialized).
The following snippet causes a crash:
```
template<typename T>
struct A
{
bool operator<=>(const A&) const requires true = default;
};
bool f(A<int> a)
{
return a != A<int>();
}
```
This occurs because during the rewrite from `operator<=>` to
`operator==`, the "pattern" `operator<=>` function is set as the
instantiated from function for the newly created `operator==` function.
This is obviously incorrect, and this patch fixes it.
With the commit d5308949cf884d8e4b971d51a8b4f73584c4adec, we now
preserve the initializer for invalid decls with the recovery-expr.
However there is a chance that the original init expr is a typo-expr, we
should not preserve it in the final AST, as typo-expr is an internal AST
node. We should use the one after the typo correction.
This is spotted by a clangd hover crash on the testcase.
When hovering over variables larger than 64 bits, with more than 64
active bits, there were assertion failures since Hover is trying to
print the value as a 64-bit hex value.
There is already protection avoiding to call printHex if there is more
than 64 significant bits. And we already truncate and print negative
values using only 32 bits, when possible. So we can simply truncate
values with more than 64 bits to avoid the assert when using
getZExtValue. The result will be that for example a negative 128 bit
variable is printed using 64 bits, when possible.
There is still no support for printing more than 64 bits. That would
involve more changes since for example llvm::FormatterNumber is limited
to 64 bits.
This is a second attempt at landing this patch. Now with protection
to ensure we use a triple that supports __int128_t.
When hovering over variables larger than 64 bits, with more than 64
active bits, there were assertion failures since Hover is trying to
print the value as a 64-bit hex value.
There is already protection avoiding to call printHex if there is more
than 64 significant bits. And we already truncate and print negative
values using only 32 bits, when possible. So we can simply truncate
values with more than 64 bits to avoid the assert when using
getZExtValue. The result will be that for example a negative 128 bit
variable is printed using 64 bits, when possible.
There is still no support for printing more than 64 bits. That would
involve more changes since for example llvm::FormatterNumber is limited
to 64 bits.
Now we can store it in DynTypedNode, we can target these nodes
(SelectionTree) and resolve them (FindTarget).
This makes Hover, go-to-def etc work in all(?) cases.
Also support it in DumpAST.
Differential Revision: https://reviews.llvm.org/D159299
The code mistakenly returns the value as evaluated whenever the
temporary is allocated, but not yet evaluated.
I could only reproduce in Clangd and could not come up with an example
that would crash the compiler. Clangd runs more evaluations for hover
than the language would allow.
Reviewed By: kadircet
Differential Revision: https://reviews.llvm.org/D158985
This makes sure we can preserve invalid-ness for consumers of this
node, it prevents crashes. It also aligns better with rest of the places that
store invalid expressions.
Differential Revision: https://reviews.llvm.org/D157868
Concepts aren't fully supporteb by hover yet. For the currently
supported case we add a test here to prevent regressions in the future.
Differential Revision: https://reviews.llvm.org/D155558
In C++20 some binary operations can be rewritten, e.g. `a != b`
can be rewritten to `!(a == b)` if `!=` is not explicitly defined.
The `TargetFinder` hasn't considered the corresponding `CXXRewrittenBinaryOperator` yet. This resulted that the definition of such operators couldn't be found
when navigating to such a `!=` operator, see https://github.com/clangd/clangd/issues/1476.
In this patch we add support of `CXXRewrittenBinaryOperator` in `FindTarget`.
In such a case we redirect to the inner binary operator of the decomposed form.
E.g. in case that `a != b` has been rewritten to `!(a == b)` we go to the
`==` operator. The `==` operator might be implicitly defined (e.g. by a `<=>`
operator), but this case is already handled, see the new test.
I'm not sure if I the hover test which is added in this patch is the right one,
but at least is passed with this patch and fails without it :)
Note, that it might be a bit missleading that hovering over a `!=` refers to
"instance method operator==".
Differential Revision: https://reviews.llvm.org/D153331
Previously for overloaded functions we'd show:
Provides: foo, bar bar bar bar
The symbol name is duplicated
==> only show unique names, since we're not displaying the signature
Commas are missing
==> fix the logic which was checking for "last element" by value
(though after the above fix this bug is dead anyway)
While here, remove a redundant bounds check before take_front().
Differential Revision: https://reviews.llvm.org/D150683
Creating a SelectionTree at the location where macro expands allows
us to obtain the associated expression, which might then be used to
evaluate compile-time values if possible.
Closesclangd/clangd#1595.
Reviewed By: nridge
Differential Revision: https://reviews.llvm.org/D148457
This patch adapts to D140059, which makes an assumption that the
caller of `APSInt::getExtValue` promises no narrowing conversion
happens, i.e., from unsigned int64 to signed int64.
It also fixesclangd/clangd#1557.
Reviewed By: nridge
Differential Revision: https://reviews.llvm.org/D146874
This is very useful when inlay hints are disabled.
Also, improve presentation of Hover when variable is passed by value to
a function with an unnamed parameter
Differential Revision: https://reviews.llvm.org/D140775
The needed tweaks are mostly trivial, the one nasty bit is Clang's usage
of OptionalStorage. To keep this working old Optional stays around as
clang::CustomizableOptional, with the default Storage removed.
Optional<File/DirectoryEntryRef> is replaced with a typedef.
I tested this with GCC 7.5, the oldest supported GCC I had around.
Differential Revision: https://reviews.llvm.org/D140332
This patch mechanically replaces None with std::nullopt where the
compiler would warn if None were deprecated. The intent is to reduce
the amount of manual work required in migrating from Optional to
std::optional.
This is part of an effort to migrate from llvm::Optional to
std::optional:
https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
This makes use of the changes introduced in D134604, in order to
instantiate alias templates witn a final sugared substitution.
This comes at no additional relevant cost.
Since we don't track / unique them in specializations, we wouldn't be
able to resugar them later anyway.
Signed-off-by: Matheus Izvekov <mizvekov@gmail.com>
Differential Revision: https://reviews.llvm.org/D136565
This patch reverts
- commit d4b1964f0554046b1e64908e5c1cd701b25f4c9e
- commit 59f0827e2cf3755834620e7e0b6d946832440f80([clang] Instantiate alias templates with sugar)
As it makes clang fail to pass some code it used to compile.
See comments: https://reviews.llvm.org/D136564#3891065
This makes use of the changes introduced in D134604, in order to
instantiate alias templates witn a final sugared substitution.
This comes at no additional relevant cost.
Since we don't track / unique them in specializations, we wouldn't be
able to resugar them later anyway.
Signed-off-by: Matheus Izvekov <mizvekov@gmail.com>
Differential Revision: https://reviews.llvm.org/D136565
This makes use of the changes introduced in D134604, in order to
instantiate alias templates witn a final sugared substitution.
This comes at no additional relevant cost.
Since we don't track / unique them in specializations, we wouldn't be
able to resugar them later anyway.
Signed-off-by: Matheus Izvekov <mizvekov@gmail.com>
Differential Revision: https://reviews.llvm.org/D136565
After upgrading the type deduction machinery to retain type sugar in
D110216, we were left with a situation where there is no general
well behaved mechanism in Clang to unify the type sugar of multiple
deductions of the same type parameter.
So we ended up making an arbitrary choice: keep the sugar of the first
deduction, ignore subsequent ones.
In general, we already had this problem, but in a smaller scale.
The result of the conditional operator and many other binary ops
could benefit from such a mechanism.
This patch implements such a type sugar unification mechanism.
The basics:
This patch introduces a `getCommonSugaredType(QualType X, QualType Y)`
method to ASTContext which implements this functionality, and uses it
for unifying the results of type deduction and return type deduction.
This will return the most derived type sugar which occurs in both X and
Y.
Example:
Suppose we have these types:
```
using Animal = int;
using Cat = Animal;
using Dog = Animal;
using Tom = Cat;
using Spike = Dog;
using Tyke = Dog;
```
For `X = Tom, Y = Spike`, this will result in `Animal`.
For `X = Spike, Y = Tyke`, this will result in `Dog`.
How it works:
We take two types, X and Y, which we wish to unify as input.
These types must have the same (qualified or unqualified) canonical
type.
We dive down fast through top-level type sugar nodes, to the
underlying canonical node. If these canonical nodes differ, we
build a common one out of the two, unifying any sugar they had.
Note that this might involve a recursive call to unify any children
of those. We then return that canonical node, handling any qualifiers.
If they don't differ, we walk up the list of sugar type nodes we dived
through, finding the last identical pair, and returning that as the
result, again handling qualifiers.
Note that this patch will not unify sugar nodes if they are not
identical already. We will simply strip off top-level sugar nodes that
differ between X and Y. This sugar node unification will instead be
implemented in a subsequent patch.
This patch also implements a few users of this mechanism:
* Template argument deduction.
* Auto deduction, for functions returning auto / decltype(auto), with
special handling for initializer_list as well.
Further users will be implemented in a subsequent patch.
Signed-off-by: Matheus Izvekov <mizvekov@gmail.com>
Differential Revision: https://reviews.llvm.org/D111283
This reverts commit d200db38637884fd0b421802c6094b2a03ceb29e, which causes a
clang crash. See https://reviews.llvm.org/D111283#3785755
Test case for convenience:
```
template <typename T>
using P = int T::*;
template <typename T, typename... A>
void j(P<T>, T, A...);
template <typename T>
void j(P<T>, T);
struct S {
int b;
};
void g(P<S> k, S s) { j(k, s); }
```