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 fixes an ambiguous type type_info when you try and reference the
`type_info` type while using clang modulemaps with `-fms-compatibility`
enabled
Fixes#38400
This commit handles the following types:
- clang::ExternalASTSource
- clang::TargetInfo
- clang::ASTContext
- clang::SourceManager
- clang::FileManager
Part of cleanup #151026
Previously Clang would give an unwarranted error on the capture of '&a'
in the function below, even though the parent function and the lambda
are both `__arm_streaming` functions, when the target is compiled with
+sme only.
```
void test_both_streaming(int32_t *out) __arm_streaming {
svint32_t a;
[&a, &out]() __arm_streaming {
^
error: SVE vector type 'svint32_t' (aka '__SVInt32_t') cannot be used in a non-streaming function
a = svdup_s32(1);
svst1(svptrue_b32(), out, a);
}();
}
```
That seems to happen because when `checkTypeSupport` is called the
`FunctionDecl` context of the lambda isn't yet complete and
`FD->getType()` returns a Null `QualTy`.
This is loosely related to #94976 which removed a `FD->hasBody()` check
in the same place, because `hasBody()` may incorrectly return `false`
when Clang is still processing a function.
Tracked at https://github.com/llvm/llvm-project/issues/112294
This patch implements from [basic.link]p14 to [basic.link]p18 partially.
The explicitly missing parts are:
- Anything related to specializations.
- Decide if a pointer is associated with a TU-local value at compile
time.
- [basic.link]p15.1.2 to decide if a type is TU-local.
- Diagnose if TU-local functions from other TU are collected to the
overload set. See [basic.link]p19, the call to 'h(N::A{});' in
translation unit #2
There should be other implicitly missing parts as the wording uses
"names" briefly several times. But to implement this precisely, we have
to visit the whole AST, including Decls, Expression and Types, which may
be harder to implement and be more time-consuming for compilation time.
So I choose to implement the common parts.
It won't be too bad to miss some cases since we DIDN'T do any such
checks in the past 3 years. Any new check is an improvement. Given
modules have been basically available since clang15 without such checks,
it will be user unfriendly if we give a hard error now. And there are
a lot of cases which violating the rule actually just fine. So I decide
to emit it as warnings instead of hard errors.
This is similar to -msve-vector-bits, but for streaming mode: it
constrains the legal values of "vscale", allowing optimizations based on
that constraint.
This also fixes conversions between SVE vectors and fixed-width vectors
in streaming functions with -msve-vector-bits and
-msve-streaming-vector-bits.
This rejects any use of arm_sve_vector_bits types in streaming
functions; if it becomes relevant, we could add
arm_sve_streaming_vector_bits types in the future.
This doesn't touch the __ARM_FEATURE_SVE_BITS define.
Fixes#106445 by using the lexer to find the correct range for the
removal FixIts. Previously the ranges that were generated assuming no
unsurprising formatting, which for the most part works. Being correct in
all cases requires using the lexer to find the bounding tokens for the
region to remove.
As part of this it adds Sema::getRangeForNextToken to wrap
Lexer::findNextToken.
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
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>
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
Previously, analysis-based diagnostics (like -Wconsumed) had to be
enabled at file scope in order to be run at the end of each function
body. This meant that they did not respect #pragma clang diagnostic
enabling or disabling the diagnostic.
Now, these pragmas can control the diagnostic emission.
Fixes#42199
This is a basic implementation of P2719: "Type-aware allocation and
deallocation functions" described at http://wg21.link/P2719
The proposal includes some more details but the basic change in
functionality is the addition of support for an additional implicit
parameter in operators `new` and `delete` to act as a type tag. Tag is
of type `std::type_identity<T>` where T is the concrete type being
allocated. So for example, a custom type specific allocator for `int`
say can be provided by the declaration of
void *operator new(std::type_identity<int>, size_t, std::align_val_t);
void operator delete(std::type_identity<int>, void*, size_t, std::align_val_t);
However this becomes more powerful by specifying templated declarations,
for example
template <typename T> void *operator new(std::type_identity<T>, size_t, std::align_val_t);
template <typename T> void operator delete(std::type_identity<T>, void*, size_t, std::align_val_t););
Where the operators being resolved will be the concrete type being
operated over (NB. A completely unconstrained global definition as above
is not recommended as it triggers many problems similar to a general
override of the global operators).
These type aware operators can be declared as either free functions or
in class, and can be specified with or without the other implicit
parameters, with overload resolution performed according to the existing
standard parameter prioritisation, only with type parameterised
operators having higher precedence than non-type aware operators. The
only exception is destroying_delete which for reasons discussed in the
paper we do not support type-aware variants by default.
- fixes#132303
- Moves dot2add from a language builtin to a target builtin.
- Sets the scaffolding for Sema checks for DX builtins
- Setup DirectX backend as able to have target builtins
- Adds a DX TargetBuiltins emitter in
`clang/lib/CodeGen/TargetBuiltins/DirectX.cpp`
This introduces a new class 'UnsignedOrNone', which models a lite
version of `std::optional<unsigned>`, but has the same size as
'unsigned'.
This replaces most uses of `std::optional<unsigned>`, and similar
schemes utilizing 'int' and '-1' as sentinel.
Besides the smaller size advantage, this is simpler to serialize, as its
internal representation is a single unsigned int as well.
Close https://github.com/llvm/llvm-project/issues/125999
The cause of the problem is, when we instantiate the pending
instantiation, the owning module of the TU gets into 'foo' instead of
the GMF.
The concern of the patch is, I am not sure the point of 'pending'
instantiations. I mean, if there is a reason we **must** pending the
intantiations to the end of the TU.
Currently the deferred diag fails to diagnose calling of host function
in host device function in device compilation triggered by destructors.
This can be further divided into two issuse:
1. the deferred diag visitor does not visit dtor of member and parent
class when visiting dtor, which it should
2. the deferred diag visitor does not visit virtual dtor of explicit
template class instantiation, which it should
Due to these issues, some constexpr functions which call host functions
are emitted on device side, which causes undefind symbols in linking
stage, as revealed by
https://github.com/llvm/llvm-project/issues/108548
By fixing these issue, clang will diag the issues early during
compilation instead of linking.
All variable declarations in the global scope that are not resources,
static or empty are implicitly added to implicit constant buffer
`$Globals`. They are created in `hlsl_constant` address space and
collected in an implicit `HLSLBufferDecl` node that is added to the AST
at the end of the translation unit. Codegen is the same as for explicit
constant buffers.
Fixes#123801
This is a second attempt to implement this feature. The first attempt
had to be reverted because of memory leaks. The problem was adding a
`SmallVector` member on `HLSLBufferDecl` node to represent a list of
default buffer declarations. When this vector needed to grow, it
allocated memory that was never released, because all memory used by AST
nodes must be allocated by `ASTContext` allocator and is released all at
once. Destructors on AST nodes are never called.
It this change the list of default buffer declarations is collected in a
`SmallVector` instance on `SemaHLSL`. The `HLSLBufDecl` representing
`$Globals` is created at the end of the translation unit when the number
of declarations is known, and the list is copied into an array allocated
by the `ASTContext` allocator.
All variable declarations in the global scope that are not resources,
static or empty are implicitly added to implicit constant buffer
`$Globals`. They are created in `hlsl_constant` address space and
collected in an implicit `HLSLBufferDecl` node that is added to the AST
at the end of the translation unit. Codegen is the same as for explicit
constant buffers.
Fixes#123801
This patch makes it so the correct instantiation context is printed for
diagnostics suppessed by template argument deduction.
The context is saved along with the suppressed diagnostic, and when the
declaration they were attached to becomes used, we print the correct
context, instead of whatever context was at this point.
Implement HLSL Aggregate Splat casting that handles splatting for arrays
and structs, and vectors if splatting from a vec1.
Closes#100609 and Closes#100619
Depends on #118842
This is take two of #70976. This iteration of the patch makes sure that
custom
diagnostics without any warning group don't get promoted by `-Werror` or
`-Wfatal-errors`.
This implements parts of the extension proposed in
https://discourse.llvm.org/t/exposing-the-diagnostic-engine-to-c/73092/7.
Specifically, this makes it possible to specify a diagnostic group in an
optional third argument.
- Update pr labeler so new SPIRV files get properly labeled.
- Add distance target builtin to BuiltinsSPIRV.td.
- Update TargetBuiltins.h to account for spirv builtins.
- Update clang basic CMakeLists.txt to build spirv builtin tablegen.
- Hook up sema for SPIRV in Sema.h|cpp, SemaSPIRV.h|cpp, and
SemaChecking.cpp.
- Hookup sprv target builtins to SPIR.h|SPIR.cpp target.
- Update GBuiltin.cpp to emit spirv intrinsics when we get the expected
spirv target builtin.
Consensus was reach in this RFC to add both target builtins and pattern
matching:
https://discourse.llvm.org/t/rfc-add-targetbuiltins-for-spirv-to-support-hlsl/83329.
pattern matching will come in a separate pr this one just sets up the
groundwork to do target builtins for spirv.
partially resolves
[#99107](https://github.com/llvm/llvm-project/issues/99107)
Get inout/out parameters working for HLSL Arrays.
Utilizes the fix from #109323, and corrects the assignment behavior
slightly to allow for Non-LValues on the RHS.
Closes#106917
---------
Co-authored-by: Chris B <beanz@abolishcrlf.org>
Consider #109148:
```c++
template <typename ...Ts>
void f() {
[] {
(^Ts);
};
}
```
When we encounter `^Ts`, we try to parse a block and subsequently call
`DiagnoseUnexpandedParameterPack()` (in `ActOnBlockArguments()`), which
sees `Ts` and sets `ContainsUnexpandedParameterPack` to `true` in the
`LambdaScopeInfo` of the enclosing lambda. However, the entire block is
subsequently discarded entirely because it isn’t even syntactically
well-formed. As a result, `ContainsUnexpandedParameterPack` is `true`
despite the lambda’s body no longer containing any unexpanded packs,
which causes an assertion the next time
`DiagnoseUnexpandedParameterPack()` is called.
This pr moves handling of unexpanded parameter packs into
`CapturingScopeInfo` instead so that the same logic is used for both
blocks and lambdas. This fixes this issue since the
`ContainsUnexpandedParameterPack` flag is now part of the block (and
before that, its `CapturingScopeInfo`) and no longer affects the
surrounding lambda directly when the block is parsed. Moreover, this
change makes blocks actually usable with pack expansion.
This fixes#109148.
By allowing AnnotateAttr to be applied to statements, users can place arbitrary information in the AST for later use.
For example, this can be used for HW-targeted language extensions that involve specialized loop annotations.
- In Sema, when encountering Decls with function effects needing
verification, add them to a vector, DeclsWithEffectsToVerify.
- Update AST serialization to include DeclsWithEffectsToVerify.
- In AnalysisBasedWarnings, use DeclsWithEffectsToVerify as a work
queue, verifying functions with declared effects, and inferring (when
permitted and necessary) whether their callees have effects.
---------
Co-authored-by: Doug Wyatt <dwyatt@apple.com>
Co-authored-by: Sirraide <aeternalmail@gmail.com>
Co-authored-by: Erich Keane <ekeane@nvidia.com>
This reverts commit e39205654dc11c50bd117e8ccac243a641ebd71f.
There are further discussions in
https://github.com/llvm/llvm-project/pull/70976, happening for past two
weeks. Since there were no responses for couple weeks now, reverting
until author is back.
Resolves: #70930 (and probably latest comments from clangd/clangd#251)
by fixing racing for the shared DiagStorage value which caused messing with args inside the storage and then formatting the following message with getArgSInt(1) == 2:
def err_module_odr_violation_function : Error<
"%q0 has different definitions in different modules; "
"%select{definition in module '%2'|defined here}1 "
"first difference is "
which causes HandleSelectModifier to go beyond the ArgumentLen so the recursive call to FormatDiagnostic was made with DiagStr > DiagEnd that leads to infinite while (DiagStr != DiagEnd).
The Main Idea:
Reuse the existing DiagStorageAllocator logic to make all DiagnosticBuilders having independent states.
Also, encapsulating the rest of state (e.g. ID and Loc) into DiagnosticBuilder.
The last attempt failed -
https://github.com/llvm/llvm-project/pull/108187#issuecomment-2353122096
so was reverted - #108838
Resolves: #70930 (and probably latest comments from
https://github.com/clangd/clangd/issues/251)
by fixing racing for the shared `DiagStorage` value which caused messing
with args inside the storage and then formatting the following message
with `getArgSInt(1)` == 2:
```
def err_module_odr_violation_function : Error<
"%q0 has different definitions in different modules; "
"%select{definition in module '%2'|defined here}1 "
"first difference is "
```
which causes `HandleSelectModifier` to go beyond the `ArgumentLen` so
the recursive call to `FormatDiagnostic` was made with `DiagStr` >
`DiagEnd` that leads to infinite `while (DiagStr != DiagEnd)`.
**The Main Idea:**
Reuse the existing `DiagStorageAllocator` logic to make all
`DiagnosticBuilder`s having independent states.
Also, encapsulating the rest of state (e.g. ID and Loc) into
`DiagnosticBuilder`.
**TODO (if it will be requested by reviewer):**
- [x] add a test (I have no idea how to turn a whole bunch of my
proprietary code which leads `clangd` to OOM into a small public
example.. probably I must try using
[this](https://github.com/llvm/llvm-project/issues/70930#issuecomment-2209872975)
instead)
- [x] [`Diag.CurDiagID !=
diag::fatal_too_many_errors`](https://github.com/llvm/llvm-project/pull/108187#pullrequestreview-2296395489)
- [ ] ? get rid of `DiagStorageAllocator` at all and make
`DiagnosticBuilder` having they own `DiagnosticStorage` coz it seems
pretty small so should fit the stack for short-living
`DiagnosticBuilder` instances
This reverts commit e7f782e7481cea23ef452a75607d3d61f5bd0d22.
This had UBSan failures:
[----------] 1 test from ConfigCompileTests
[ RUN ] ConfigCompileTests.DiagnosticSuppression
Config fragment: compiling <unknown>:0 -> 0x00007B8366E2F7D8 (trusted=false)
/usr/local/google/home/fmayer/large/llvm-project/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h:203:33: runtime error: reference binding to null pointer of type 'clang::DiagnosticIDs'
UndefinedBehaviorSanitizer: undefined-behavior /usr/local/google/home/fmayer/large/llvm-project/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h:203:33
Pull Request: https://github.com/llvm/llvm-project/pull/108645