Incompatible pointer to integer conversion diagnostic checks would
trigger an assertion when the designated initializer is for an array of
unknown bounds.
Fixes#154046
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
This is a first pass at implementing
[P2841R7](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2841r7.pdf).
The implementation is far from complete; however, I'm aiming to do that
in chunks, to make our lives easier.
In particular, this does not implement
- Subsumption
- Mangling
- Satisfaction checking is minimal as we should focus on #141776 first
(note that I'm currently very stuck)
FTM, release notes, status page, etc, will be updated once the feature
is more mature. Given the state of the feature, it is not yet allowed in
older language modes.
Of note:
- Mismatches between template template arguments and template template
parameters are a bit wonky. This is addressed by #130603
- We use `UnresolvedLookupExpr` to model template-id. While this is
pre-existing, I have been wondering if we want to introduce a different
OverloadExpr subclass for that. I did not make the change in this patch.
In C, a char array needs no "nonstring" attribute, if its initializer is
a string literal that 1) explicitly ends with '\0' and 2) fits in the
array after a possible truncation.
For example
`char a[4] = "ABC\0"; // fine, needs no "nonstring" attr`
rdar://152506883
This reland disables the test for linux so that it will not block the
buildbot: https://lab.llvm.org/buildbot/#/builders/144/builds/28591.
In C, a char array needs no "nonstring" attribute, if its initializer is
a string literal that 1) explicitly ends with '\0' and 2) fits in the
array after a possible truncation.
For example
`char a[4] = "ABC\0"; // fine, needs no "nonstring" attr`
rdar://152506883
Static analysis flagged that Var could be nullptr but we were not
checking in the branch and unconditionally dereferences the pointer.
Note, code was added by 576161cb6069
Reland with debug traces to try to understand a bug that only happens on
one CI configuration
===
This introduces a way detect the libstdc++ version,
use that to enable workarounds.
The version is cached.
This should make it easier in the future to find and remove
these hacks.
I did not find the need for enabling a hack between or after
specific versions, so it's left as a future exercise.
We can extend this fature to other libraries as the need arise.
===
This introduces a way detect the libstdc++ version, use that to enable
workarounds.
The version is cached.
This should make it easier in the future to find and remove these hacks.
I did not find the need for enabling a hack between or after specific
versions, so it's left as a future exercise.
We can extend this fature to other libraries as the need arise.
These are identified by misc-include-cleaner. I've filtered out those
that break builds. Also, I'm staying away from llvm-config.h,
config.h, and Compiler.h, which likely cause platform- or
compiler-specific build failures.
There are two related issues being fixed in this patch. Both issues
relate to use of an invalid structure which contains a member that we
error recover such that the field has the same type as the structure. In
both cases, we would hit an infinite loop while analyzing the fields
because the type of the field matches the type of the record.
Fixes#140887
When using InitChecker with VerifyOnly, we create a new designated
initializer to handle anonymous fields. However in the last call to
CheckDesignatedInitializer, the subinitializer isn't properly preserved
but it gets overwritten by the cloned one. Which causes the initializer
to reference the dependent field, breaking assumptions when we
initialize the instantiated specialization.
Fixes https://github.com/llvm/llvm-project/issues/67173
This addresses post-commit review feedback from someone who discovered
that we diagnosed code like the following:
```
struct S {
int len;
const char fam[];
} s;
```
despite it being invalid to initialize the flexible array member.
Note, this applies to flexible array members and zero-sized arrays at
the end of a structure (an old-style flexible array member), but it does
not apply to one-sized arrays at the end of a structure because those do
occupy storage that can be initialized.
A default-initialized union with a const member is generally reasonable
in C and isn't necessarily incompatible with C++, so we now silence the
diagnostic in that case. However, we do still diagnose a const-
qualified, default-initialized union as that is incompatible with C++.
This patch adds fp8 variants to existing intrinsics, whose operation
doesn't depend on arguments being a specific type.
It also changes mfloat8 type representation in memory from `i8` to
`<1xi8>`
We document libstdc++4.8 as the minimum supported version, and we
carried a hack for `include/tr1/hashtable.h` fixed in 4.7.
Cleanup some libstdc++ compatibility comments.
This drops the "and is incompatible with C++" phrasing from the
diagnostic unless -Wc++-compat is explicitly passed. This makes the
diagnostic less confusing when it is on by default rather than enabled
because of C++ compatibility concerns
This patch adds templated `operator<<` for diagnostics that pass scoped
enums, saving people from `llvm::to_underlying()` clutter on the side of
emitting the diagnostic. This eliminates 80 out of 220 usages of
`llvm::to_underlying()` in Clang.
I also backported `std::is_scoped_enum_v` from C++23.
Post-commit review feedback on
https://github.com/llvm/llvm-project/pull/137166 raised a concern from
the Linux kernel about wanting to silence the new diagnostic when the
uninitialized object is a const member of a structure. These members can
be initialized later if the containing object is non-const, such as
through a call to memset, for example.
This splits the diagnostic groups into:
```
-Wc++-compat
-Wdefault-const-init
-Wdefault-const-init-field
-Wdefault-const-init-var
-Wdefault-const-init-unsafe
-Wdefault-const-init-field-unsafe
-Wdefault-const-init-var-unsafe
```
---------
Co-authored-by: Mariya Podchishchaeva <mariya.podchishchaeva@intel.com>
This introduces three things related to intialization like:
char buf[3] = "foo";
where the array does not declare enough space for the null terminator
but otherwise can represent the array contents exactly.
1) An attribute named 'nonstring' which can be used to mark that a
field or variable is not intended to hold string data.
2) -Wunterminated-string-initialization, which is grouped under
-Wextra, and diagnoses the above construct unless the declaration
uses the 'nonstring' attribute.
3) -Wc++-unterminated-string-initialization, which is grouped under
-Wc++-compat, and diagnoses the above construct even if the
declaration uses the 'nonstring' attribute.
Fixes#137705
Unlike C++, C allows the definition of an uninitialized `const` object.
If the object has static or thread storage duration, it is still
zero-initialized, otherwise, the object is left uninitialized. In either
case, the code is not compatible with C++.
This adds a new diagnostic group, `-Wdefault-const-init-unsafe`, which
is on by default and diagnoses any definition of a `const` object which
remains uninitialized.
It also adds another new diagnostic group, `-Wdefault-const-init` (which
also enabled the `unsafe` variant) that diagnoses any definition of a
`const` object (including ones which are zero-initialized). This
diagnostic is off by default.
Finally, it adds `-Wdefault-const-init` to `-Wc++-compat`. GCC diagnoses
these situations under this flag.
Fixes#19297
This introduces a new diagnostic group (-Wimplicit-void-ptr-cast),
grouped under -Wc++-compat, which diagnoses implicit conversions from
void * to another pointer type in C. It's a common source of
incompatibility with C++ and is something GCC diagnoses (though GCC does
not have a specific warning group for this).
Fixes#17792
Previously using the `counted_by` or `counted_by_or_null` attribute on a
pointer with an incomplete pointee type was forbidden. Unfortunately
this prevented a situation like the following from being allowed.
Header file:
```
struct EltTy; // Incomplete type
struct Buffer {
size_t count;
struct EltTy* __counted_by(count) buffer; // error before this patch
};
```
Implementation file:
```
struct EltTy {
// definition
};
void allocBuffer(struct Buffer* b) {
b->buffer = malloc(sizeof(EltTy)* b->count);
}
```
To allow code like the above but still enforce that the pointee
type size is known in locations where `-fbounds-safety` needs to
emit bounds checks the following scheme is used.
* For incomplete pointee types that can never be completed (e.g. `void`)
these are treated as error where the attribute is written (just like
before this patch).
* For incomplete pointee types that might be completable later on
(struct, union, and enum forward declarations)
in the translation unit, writing the attribute on the incomplete
pointee type is allowed on the FieldDecl declaration but "uses" of the
declared pointer are forbidden if at the point of "use" the pointee
type is still incomplete.
For this patch a "use" of a FieldDecl covers:
* Explicit and Implicit initialization (note see **Tentative Definition
Initialization** for an exception to this)
* Assignment
* Conversion to an lvalue (e.g. for use in an expression)
In the swift lang fork of Clang the `counted_by` and
`counted_by_or_null` attribute are allowed in many more contexts. That
isn't the case for upstream Clang so the "use" checks for the attribute
on VarDecl, ParamVarDecl, and function return type have been omitted
from this patch because they can't be tested. However, the
`BoundsSafetyCheckAssignmentToCountAttrPtrWithIncompletePointeeTy` and
`BoundsSafetyCheckUseOfCountAttrPtrWithIncompletePointeeTy` functions
retain the ability to emit diagnostics for these other contexts to avoid
unnecessary divergence between upstream Clang and Apple's internal fork.
Support for checking "uses" will be upstreamed when upstream Clang
allows the `counted_by` and `counted_by_or_null` attribute in additional
contexts.
This patch has a few limitations:
** 1. Tentative Defition Initialization **
This patch currently allows something like:
```
struct IncompleteTy;
struct Buffer {
int count;
struct IncompleteTy* __counted_by(count) buf;
};
// Tentative definition
struct Buffer GlobalBuf;
```
The Tentative definition in this example becomes an actual definition
whose initialization **should be checked** but it currently isn't.
Addressing this problem will be done in a subseqent patch.
** 2. When the incomplete pointee type is a typedef diagnostics are slightly misleading **
For this situation:
```
struct IncompleteTy;
typedef struct IncompleteTy Incomplete_t;
struct Buffer {
int count;
struct IncompleteTy* __counted_by(count) buf;
};
void use(struct Buffer b) {
b.buf = 0x0;
}
```
This code emits `note: forward declaration of 'Incomplete_t' (aka
'struct IncompleteTy')` but the location is on the `struct
IncompleteTy;` forward declaration. This is misleading because
`Incomplete_t` isn't actually forward declared there (instead the
underlying type is). This could be resolved by additional diagnostics
that walk the chain of typedefs and explain each step of the walk.
However, that would be very verbose and didn't seem like a direction
worth pursuing.
rdar://133600117
This implements the same overload resolution behavior as GCC,
as described in https://wg21.link/p3606 (section 1-2, not 3)
If during overload resolution, there is a non-template candidate
that would be always be picked - because each of the argument
is a perfect match (ie the source and target types are the same),
we do not perform deduction for any template candidate
that might exists.
The goal is to be able to merge
https://github.com/llvm/llvm-project/pull/122423 without being too
disruptive.
This change means that the selection of the best viable candidate and
template argument deduction become interleaved.
To avoid rewriting half of Clang we store in `OverloadCandidateSet`
enough information to be able to deduce template candidates from
`OverloadCandidateSet::BestViableFunction`. Which means
the lifetime of any object used by template argument must outlive
a call to `Add*Template*Candidate`.
This two phase resolution is not performed for some initialization
as there are cases where template candidate are better match
in these cases per the standard. It's also bypassed for code completion.
The change has a nice impact on compile times
https://llvm-compile-time-tracker.com/compare.php?from=719b029c16eeb1035da522fd641dfcc4cee6be74&to=bf7041045c9408490c395230047c5461de72fc39&stat=instructions%3Au
Fixes https://github.com/llvm/llvm-project/issues/62096
Fixes https://github.com/llvm/llvm-project/issues/74581
Reapplies #133426
This implements the same overload resolution behavior as GCC,
as described in https://wg21.link/p3606 (sections 1-2, not 3)
If, during overload resolution, a non-template candidate is always
picked because each argument is a perfect match (i.e., the source and
target types are the same), we do not perform deduction for any template
candidate that might exist.
The goal is to be able to merge #122423 without being too disruptive.
This change means that the selection of the best viable candidate and
template argument deduction become interleaved.
To avoid rewriting half of Clang, we store in `OverloadCandidateSet`
enough information to deduce template candidates from
`OverloadCandidateSet::BestViableFunction`. This means the lifetime of
any object used by the template argument must outlive a call to
`Add*Template*Candidate`.
This two-phase resolution is not performed for some initialization as
there are cases where template candidates are a better match per the
standard. It's also bypassed for code completion.
The change has a nice impact on compile times
https://llvm-compile-time-tracker.com/compare.php?from=edc22c64e527171041876f26a491bb1d03d905d5&to=8170b860bd4b70917005796c05a9be013a95abb2&stat=instructions%3AuFixes#62096Fixes#74581Fixes#53454
This feature largely models the same behavior as in C++11. It is
technically a breaking change between C99 and C11, so the paper is not
being backported to older language modes.
One difference between C++ and C is that things which are rvalues in C
are often lvalues in C++ (such as the result of a ternary operator or a
comma operator).
Fixes#96486
Alias template class template argument deduction is a documented C++20
feature. C++17 also happens to support it, but there is no message
output to indicate the officially supported version. This PR adds that.
Also updated relevant CTAD test cases.
Closes#125913
* Move parts of `InitializationSequence::InitializeFrom` corresponding
to C++ [dcl.init.general] p16.6.1 and p16.6.2 into a separate
function,`TryConstructorOrParenListInitialization`
* Use it in `TryListInitialization` to implement [dcl.init.list] p3.2
* Fix parenthesized aggregate initialization being attempted in
copy-initialization contexts or when the constructor call is ambiguous
Co-authored-by: cor3ntin <corentinjabot@gmail.com>
StringLiteral is used as internal data of EmbedExpr and we directly use
it as an initializer if a single EmbedExpr appears in the initializer
list of a char array. It is fast and convenient, but it is causing
problems when string literal character values are checked because #embed
data values are within a range [0-2^(char width)] but ordinary
StringLiteral is of maybe signed char type.
This PR introduces new kind of StringLiteral to hold binary data coming
from an embedded resource to mitigate these problems. The new kind of
StringLiteral is not assumed to have signed char type. The new kind of
StringLiteral also helps to prevent crashes when trying to find
StringLiteral token locations since these simply do not exist for binary
data.
Fixes https://github.com/llvm/llvm-project/issues/119256
Instead of manually adding a note pointing to the relevant template
parameter to every relevant error, which is very easy to miss, this
patch adds a new instantiation context note, so that this can work using
RAII magic.
This fixes a bunch of places where these notes were missing, and is more
future-proof.
Some diagnostics are reworked to make better use of this note:
- Errors about missing template arguments now refer to the parameter
which is missing an argument.
- Template Template parameter mismatches now refer to template
parameters as parameters instead of arguments.
It's likely this will add the note to some diagnostics where the
parameter is not super relevant, but this can be reworked with time and
the decrease in maintenance burden makes up for it.
This bypasses the templight dumper for the new context entry, as the
tests are very hard to update.
This depends on #125453, which is needed to avoid losing the context
note for errors occuring during template argument deduction.
Tune SemaInit code handling #embed to take into account how many array
elements remains to initialize.
Also issue a warning/error message when the array/struct is at the end
but there is still #embed data left.
Fixes https://github.com/llvm/llvm-project/issues/128987
Sometimes number of expressions in InitListExpr is used for template
argument deduction. So, in these cases we need to pay attention to real
number of expressions including expanded #embed data.
Fixes https://github.com/llvm/llvm-project/issues/122306