Summary:
It's extremely common to conditionally blend two vectors. Previously
this was done with mask registers, which is what the normal ternary code
generation does when used on a vector. However, since Clang 15 we have
supported boolean vector types in the compiler. These are useful in
general for checking the mask registers, but are currently limited
because they do not map to an LLVM-IR select instruction.
This patch simply relaxes these checks, which are technically forbidden
by
the OpenCL standard. However, general vector support should be able to
handle these. We already support this for Arm SVE types, so this should
be make more consistent with the clang vector type.
This patch replaces SmallSet<T *, N> with SmallPtrSet<T *, N>. Note
that SmallSet.h "redirects" SmallSet to SmallPtrSet for pointer
element types:
template <typename PointeeType, unsigned N>
class SmallSet<PointeeType*, N> : public SmallPtrSet<PointeeType*, N>
{};
We only have 30 instances that rely on this "redirection", with about
half of them under clang/. Since the redirection doesn't improve
readability, this patch replaces SmallSet with SmallPtrSet for pointer
element types.
I'm planning to remove the redirection eventually.
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
Client apps can (and in the case of the MSVC STL do) set cdecl
explicitly on `new` / `delete` implementations. On the other hand, Clang
generates implicit decls with the target's default CC. This is
problematic for SPIR-V, since the default there is spir_function, which
is not compatible. Since we cannot change pre-existing headers /
implementations, this patch sets the CC to C for the implicit host-side
decls, when compiling for device, to prevent the conflict. This is fine
because the host-side overloards do not get emitted on device.
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.
Add `NamespaceBaseDecl` as common base class of `NamespaceDecl` and
`NamespaceAliasDecl`. This simplifies `NestedNameSpecifier` a bit.
Co-authored-by: Matheus Izvekov <mizvekov@gmail.com>
ASTContext::getDefaultCallingConvention() was documented as returning
"the default calling convention for the current target", but did not do
this, and was never intended to do this, it has always been controlled
by command-line options to deviate from the target default.
This commit changes ASTContext::getDefaultCallingConvention() to reflect
the fact that it returns the context's default calling convention, not
the target's default calling convention. The IsBuiltin parameter, which
was used to return the target's default calling convention rather than
the context's, is removed in favor of
getTargetInfo().getDefaultCallingConv() which is more explicit of the
intent.
Before this patch, the following code gave misleading diagnostics about
absence of `#include <new>`:
```cpp
#include <new>
struct X { int n; };
int foo() {
const X cx = {5};
// error: no matching 'operator new' function for non-allocating placement new expression; include <new>
(void)new(&cx) X{10};
};
```
Now it gives correct diagnostics about constness of passed argument:
```cpp
#include <new>
struct X { int n; };
int foo() {
const X cx = {5};
// error: placement new expression with a const-qualified argument of type 'const X *' is not allowed
(void)new(&cx) X{10};
};
```
Fixes https://github.com/llvm/llvm-project/issues/143708.
---------
Co-authored-by: Corentin Jabot <corentinjabot@gmail.com>
Deal with the following scenario
```cpp
struct S {
char* c = new char;
constexpr ~S() {
delete c;
}
};
if constexpr((S{}, true)){};
```
There were two issues
- We need to produce a full expression _before_ evaluating the condition
(otherwise, automatic variables are never destroyed)
- We need to preserve the evaluation context of the condition while
doing the semantics analysis for it (lest it is evaluated in a
non-constant-evaluated context)
Fixes#120197Fixes#134820
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.
This introduces the attribute discussed in
https://discourse.llvm.org/t/rfc-function-type-attribute-to-prevent-cfi-instrumentation/85458.
The proposed name has been changed from `no_cfi` to
`cfi_unchecked_callee` to help differentiate from `no_sanitize("cfi")`
more easily. The proposed attribute has the following semantics:
1. Indirect calls to a function type with this attribute will not be
instrumented with CFI. That is, the indirect call will not be checked.
Note that this only changes the behavior for indirect calls on pointers
to function types having this attribute. It does not prevent all
indirect function calls for a given type from being checked.
2. All direct references to a function whose type has this attribute
will always reference the true function definition rather than an entry
in the CFI jump table.
3. When a pointer to a function with this attribute is implicitly cast
to a pointer to a function without this attribute, the compiler will
give a warning saying this attribute is discarded. This warning can be
silenced with an explicit C-style cast or C++ static_cast.
Resolves#138939
When enabling `--fno-exceptions` flag, discarded statements containing
`try/catch/throw` in an independent context can be avoided from being
rejected.
There are several type traits that produce a boolean value or type based
on the well-formedness of some expression (more precisely, the immediate
context, i.e. for example excluding nested template instantiation):
* `__is_constructible` and variants,
* `__is_convertible` and variants,
* `__is_assignable` and variants,
* `__reference_{binds_to,{constructs,converts}_from}_temporary`,
* `__is_trivially_equality_comparable`,
* `__builtin_common_type`.
(It should be noted that the standard doesn't always base this on the
immediate context being well-formed: for `std::common_type` it's based
on whether some expression "denotes a valid type." But I assume that's
an editorial issue and means the same thing.)
Errors in the immediate context are suppressed, instead the type traits
return another value or produce a different type if the expression is
not well-formed. This is achieved using an `SFINAETrap` with
`AccessCheckingSFINAE` set to true. If the type trait is used outside of
an SFINAE context, errors are discarded because in that case the
`SFINAETrap` sets `InNonInstantiationSFINAEContext`, which makes
`isSFINAEContext` return an `optional(nullptr)`, which causes the errors
to be discarded in `EmitDiagnostic`. However, in an SFINAE context this
doesn't happen, and errors are added to `SuppressedDiagnostics` in the
`TemplateDeductionInfo` returned by `isSFINAEContext`. Once we're done
with deducing template arguments and have decided which template is
going to be instantiated, the errors corresponding to the chosen
template are then emitted. At this point we get errors from those type
traits that we wouldn't have seen if used with the same arguments
outside of an SFINAE context. That doesn't seem right.
So what we want to do is always set `InNonInstantiationSFINAEContext`
when evaluating these well-formed-testing type traits, regardless of
whether we're in an SFINAE context or not. This should only affect the
immediate context, as nested contexts add a new `CodeSynthesisContext`
that resets `InNonInstantiationSFINAEContext` for the time it's active.
Going through uses of `SFINAETrap` with `AccessCheckingSFINAE` = `true`,
it occurred to me that all of them want this behavior and we can just
use this parameter to decide whether to use a non-instantiation context.
The uses are precisely the type traits mentioned above plus the
`TentativeAnalysisScope`, where I think it is also fine. (Though I think
we don't do tentative analysis in SFINAE contexts anyway.)
Because the parameter no longer just sets `AccessCheckingSFINAE` in Sema
but also `InNonInstantiationSFINAEContext`, I think it should be renamed
(along with uses, which also point the reviewer to the affected places).
Since we're testing for validity of some expression, `ForValidityCheck`
seems to be a good name.
The added tests should more or less correspond to the users of
`SFINAETrap` with `AccessCheckingSFINAE` = `true`. I added a test for
errors outside of the immediate context for only one type trait, because
it requires some setup and is relatively noisy.
We put the `ForValidityCheck` condition first because it's constant in
all uses and this would then allow the compiler to prune the call to
`isSFINAEContext` when true.
Fixes#132044.
The C++26 standard relocatable type traits has slightly different
semantics, so we introduced a new
``__builtin_is_cpp_trivially_relocatable``
when implementing trivial relocation in #127636.
However, having multiple relocatable traits would be confusing
in the long run, so we deprecate the old trait.
As discussed in #127636
`__builtin_is_cpp_trivially_relocatable` should be used instead.
The C++26 standard relocatable type traits has slightly different
semantics, so we introduced a new
``__builtin_is_cpp_trivially_relocatable`` when implementing trivial
relocation in #127636.
However, having multiple relocatable traits would be confusing in the
long run, so we deprecate the old trait.
As discussed in #127636
`__builtin_is_cpp_trivially_relocatable` should be used instead.
---------
Co-authored-by: Aaron Ballman <aaron@aaronballman.com>
This adds
- The parsing of `trivially_relocatable_if_eligible`,
`replaceable_if_eligible` keywords
- `__builtin_trivially_relocate`, implemented in terms of memmove. In
the future this should
- Add the appropriate start/end lifetime markers that llvm does not have
(`start_lifetime_as`)
- Add support for ptrauth when that's upstreamed
- the `__builtin_is_cpp_trivially_relocatable` and
`__builtin_is_replaceable` traits
Fixes#127609
We were testing the immediate DeclContext for found new and delete
operators, which is incorrect if the declarations are contained by a
transparent decl as can be induced with extern or export statements.
This implements [LWG4113](https://cplusplus.github.io/LWG/issue411)
This is technically a breaking change, but it's a fix, and I think
anyone who relies on this today is in a world of hurt.
Fixes#118350
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.
Static analysis flagged this code b/c we should have been using
std::move when passing by value since the value is not used anymore. In
this case the simpler fix is just to use a temporary value as many of
the other cases where we simply use MakeIntValue to then create an
APValue result from it.
Reland #134174
Update Sema Checking to always do an HLSL Array RValue cast in the case
we are dealing with hlsl constant array types
Instead of comparing canonical types, compare canonical unqualified
types
Add a test to show it is possible to assign an array from a cbuffer.
Closes https://github.com/llvm/llvm-project/issues/133767
Update Sema Checking to always do an HLSL Array RValue cast in the case
we are dealing with hlsl constant array types
Instead of comparing canonical types, compare canonical unqualified
types
Add a test to show it is possible to assign an array from a cbuffer.
Closes#133767
This reapplies #134038
Since the last patch, this fixes a null pointer dereference where the
TSI of the destructor wasn't properly propagated into the
DeclarationNameInfo. We now construct a LocInfoType for dependent cases,
as done elsewhere in getDestructorName, such that GetTypeFromParser can
correctly obtain the TSI.
---
This patch fixes two long-standing bugs that prevent Clang from
instantiating local class members inside a dependent context. These bugs
were introduced in commits
21eb1af469
and
919df9d75a.
21eb1af469
introduced a concept called eligible methods such that it did an attempt
to skip past ineligible method instantiation when instantiating class
members. Unfortunately, this broke the instantiation chain for local
classes - getTemplateInstantiationPattern() would fail to find the
correct definition pattern if the class was defined within a partially
transformed dependent context.
919df9d75a
introduced a separate issue by incorrectly copying the
DeclarationNameInfo during function definition instantiation from the
template pattern, even though that DNI might contain a transformed
TypeSourceInfo. Since that TSI was already updated when the declaration
was instantiated, this led to inconsistencies. As a result, the final
instantiated function could lose track of the transformed declarations,
hence we crash: https://compiler-explorer.com/z/vjvoG76Tf.
This PR corrects them by
1. Removing the bypass logic for method instantiation. The eligible flag
is independent of instantiation and can be updated properly afterward,
so skipping instantiation is unnecessary.
2. Carefully handling TypeSourceInfo by creating a new instance that
preserves the pattern's source location while using the already
transformed type.
The qualifier allows programmer to directly control how pointers are
signed when they are stored in a particular variable.
The qualifier takes three arguments: the signing key, a flag specifying
whether address discrimination should be used, and a non-negative
integer that is used for additional discrimination.
```
typedef void (*my_callback)(const void*);
my_callback __ptrauth(ptrauth_key_process_dependent_code, 1, 0xe27a) callback;
```
Co-Authored-By: John McCall rjmccall@apple.com
The P2719 implementation refactored diagnostics for cleanup delete, and
as part of that I attempted to fix handling of inaccessible cleanup
operator delete. Alas the new branch was incorrect as it was performing
an implicit bool conversion, which resulted in friend accessible cleanup
operators incorrectly being considered erroneous and the allocation path
errored out. This error however did not get diagnosed, so the result was
and so we did not actually error out before codegen.
Added both Sema and CodeGen tests to cover this.