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>
See issue https://github.com/clangd/clangd/issues/2375
The clangd textDocument/documentLink request does not support include
statements with macro argument and fails by returning an invalid range.
This PR adds support for macro argument by detecting what form of
include statement is currently being processed and returning a range
accordingly
First time contributing to LLVM, so if you have advice, questions or if
I messed up procedure please tell me !
---------
Co-authored-by: Adrien Garbani <garbani.adrien@frayien.fr>
Handles clang::DiagnosticsEngine and clang::DiagnosticIDs.
For DiagnosticIDs, this mostly migrates from `new DiagnosticIDs` to
convenience method `DiagnosticIDs::create()`.
Part of cleanup https://github.com/llvm/llvm-project/issues/151026
This relands commit
7355ea3f6b.
The original commit was reverted in
bfd73a5161
because it was breaking the buildbot.
The issue has now been resolved by
38f82534bb.
Original PR: https://github.com/llvm/llvm-project/pull/139348
Original commit message:
<blockquote>
closes https://github.com/clangd/clangd/issues/1037
closes https://github.com/clangd/clangd/issues/2240
Example:
```c++
class Base {
public:
virtual void publicMethod() = 0;
protected:
virtual auto privateMethod() const -> int = 0;
};
// Before:
// // cursor here
class Derived : public Base{}^ ;
// After:
class Derived : public Base {
public:
void publicMethod() override {
// TODO: Implement this pure virtual method.
static_assert(false, "Method `publicMethod` is not implemented.");
}
protected:
auto privateMethod() const -> int override {
// TODO: Implement this pure virtual method.
static_assert(false, "Method `privateMethod` is not implemented.");
}
};
```
https://github.com/user-attachments/assets/79de40d9-1004-4c2e-8f5c-be1fb074c6de
</blockquote>
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
closes https://github.com/clangd/clangd/issues/1037
closes https://github.com/clangd/clangd/issues/2240
Example:
```c++
class Base {
public:
virtual void publicMethod() = 0;
protected:
virtual auto privateMethod() const -> int = 0;
};
// Before:
// // cursor here
class Derived : public Base{}^ ;
// After:
class Derived : public Base {
public:
void publicMethod() override {
// TODO: Implement this pure virtual method.
static_assert(false, "Method `publicMethod` is not implemented.");
}
protected:
auto privateMethod() const -> int override {
// TODO: Implement this pure virtual method.
static_assert(false, "Method `privateMethod` is not implemented.");
}
};
```
https://github.com/user-attachments/assets/79de40d9-1004-4c2e-8f5c-be1fb074c6de
---------
Co-authored-by: Marco Maia <marco.maia@iarasystems.com.br>
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.
The missing include diagnostic has the capability to introduce the
necessary headers into the source file. However, it does not currently
follow the inclusion style found in the `.clangd` file. For example, if
the file explicitly mentions that headers should be include with angled
brackets, they could be included with quotes instead. More details in
https://github.com/llvm/llvm-project/issues/138740. This PR fixes this
gap, so that the style configuration is followed.
This reverts commit e2a885537f11f8d9ced1c80c2c90069ab5adeb1d. Build failures were fixed right away and reverting the original commit without the fixes breaks the build again.
The `DiagnosticOptions` class is currently intrusively
reference-counted, which makes reasoning about its lifetime very
difficult in some cases. For example, `CompilerInvocation` owns the
`DiagnosticOptions` instance (wrapped in `llvm::IntrusiveRefCntPtr`) and
only exposes an accessor returning `DiagnosticOptions &`. One would
think this gives `CompilerInvocation` exclusive ownership of the object,
but that's not the case:
```c++
void shareOwnership(CompilerInvocation &CI) {
llvm::IntrusiveRefCntPtr<DiagnosticOptions> CoOwner = &CI.getDiagnosticOptions();
// ...
}
```
This is a perfectly valid pattern that is being actually used in the
codebase.
I would like to ensure the ownership of `DiagnosticOptions` by
`CompilerInvocation` is guaranteed to be exclusive. This can be
leveraged for a copy-on-write optimization later on. This PR changes
usages of `DiagnosticOptions` across `clang`, `clang-tools-extra` and
`lldb` to not be intrusively reference-counted.
`CallHierarchyOutgoingCall::fromRanges` are interpreted as ranges in the
same file as the item for which 'outgoingCalls' was called.
It's possible for outgoing calls to be in a different file than that
item if the item is just a declaration (e.g. in a header file). Now,
such calls are dropped instead of being returned to the client.
This is the same as the change made in #111616, but now for outgoing
calls.
Fixesclangd/clangd#2350
---------
Co-authored-by: Nathan Ridge <zeratul976@hotmail.com>
* Only show for blocks 10 lines or taller (including braces)
* Add parens for function call: "// if foo" -> "// if foo()" or "// if foo(...)"
* Print literal nullptr
* Escaping for abbreviated strings
Fixes https://github.com/clangd/clangd/issues/1807.
Based on the original PR at https://github.com/llvm/llvm-project/pull/72345.
Co-authored-by: daiyousei-qz <qyzheng2@outlook.com>
Avoid using PreservesMost in the testcase as it is not supported on all
targets.
Original PR #118290.
Co-authored-by: Robert Dazi <14996868+v01dXYZ@users.noreply.github.com>
Co-authored-by: v01dxyz <v01dxyz@v01d.xyz>
This is a follow-up to https://github.com/llvm/llvm-project/pull/131074.
After moving the default argument heuristic to `simplifyType` in that
patch, the heuristic no longer applied to the
`DependentScopeDeclRefExpr` case, because that wasn't using
`simplifyType`.
This patch fixes that, with an added testcase.
This makes it so that `CompilerInvocation` can be the only entity that
manages ownership of `HeaderSearchOptions`, making it possible to
implement copy-on-write semantics.
This is a cleaner design than using identifier and an optional `Selector`. It also allows rename of Objective-C method names if no declaration is at hand and thus no `Selector` instance can be formed. For example, when finding the ranges to rename based on an index that’s not clangd’s built-in index.
Support the trivial "header"/source switch for module interfaces.
I initially thought the naming are bad and we should rename it. But
later I feel it is better to split patches as much as possible.
From the codes it looks like there are problems. e.g., `isHeaderFile`.
But let's try to fix them in different patches.
Original PR: #130537
Originally reverted due to revert of dependent commit. Relanding with no
changes.
This changes the MemberPointerType representation to use a
NestedNameSpecifier instead of a Type to represent the base class.
Since the qualifiers are always parsed as nested names, there was an
impedance mismatch when converting these back and forth into types, and
this led to issues in preserving sugar.
The nested names are indeed a better match for these, as the differences
which a QualType can represent cannot be expressed syntatically, and
they represent the use case more exactly, being either dependent or
referring to a CXXRecord, unqualified.
This patch also makes the MemberPointerType able to represent sugar for
a {up/downcast}cast conversion of the base class, although for now the
underlying type is canonical, as preserving the sugar up to that point
requires further work.
As usual, includes a few drive-by fixes in order to make use of the
improvements.
Original PR: #130537
Reland after updating lldb too.
This changes the MemberPointerType representation to use a
NestedNameSpecifier instead of a Type to represent the base class.
Since the qualifiers are always parsed as nested names, there was an
impedance mismatch when converting these back and forth into types, and
this led to issues in preserving sugar.
The nested names are indeed a better match for these, as the differences
which a QualType can represent cannot be expressed syntatically, and
they represent the use case more exactly, being either dependent or
referring to a CXXRecord, unqualified.
This patch also makes the MemberPointerType able to represent sugar for
a {up/downcast}cast conversion of the base class, although for now the
underlying type is canonical, as preserving the sugar up to that point
requires further work.
As usual, includes a few drive-by fixes in order to make use of the
improvements.
This changes the MemberPointerType representation to use a
NestedNameSpecifier instead of a Type to represent the class.
Since the qualifiers are always parsed as nested names, there was an
impedance mismatch when converting these back and forth into types, and
this led to issues in preserving sugar.
The nested names are indeed a better match for these, as the differences
which a QualType can represent cannot be expressed syntactically, and it
also represents the use case more exactly, being either dependent or
referring to a CXXRecord, unqualified.
This patch also makes the MemberPointerType able to represent sugar for
a {up/downcast}cast conversion of the base class, although for now the
underlying type is canonical, as preserving the sugar up to that point
requires further work.
As usual, includes a few drive-by fixes in order to make use of the
improvements, and removing some duplications, for example
CheckBaseClassAccess is deduplicated from across SemaAccess and
SemaCast.
Clangd does not support its checker because the checker relies on having
seen preprocessor conditionals that occur in the preamble, and clangd
does not currently replay those.
This checker was already disabled under its main name,
modernize-macro-to-enum (https://github.com/clangd/clangd/issues/1464).
This commit disables it under the alternative name
cppcoreguidelines-macro-to-enum as well.
Fixes https://github.com/llvm/llvm-project/issues/127965
This commit adds a namespace check to the code for detecting name
collisions, allowing `bar` to be renamed to `foo` in the following
snippet:
```c
typedef struct foo {} Foo;
Foo bar;
```
Previously, such a rename would fail because a declaration for `foo`
already exists in the same scope.