[clang] [Sema] Mark alias/ifunc targets used and consider mangled names (PR #87130)
https://github.com/erichkeane commented: A quick few things I noticed, not nearly a thorough review. https://github.com/llvm/llvm-project/pull/87130 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Factor out OpenACC part of `Sema` (PR #84184)
https://github.com/Endilll updated https://github.com/llvm/llvm-project/pull/84184 >From 23f4208fb9978370f59cae16db0747acb3e2c906 Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov Date: Wed, 6 Mar 2024 18:01:35 +0300 Subject: [PATCH 1/7] [clang] Factor out OpenACC part of `Sema` This patch moves OpenACC parts of `Sema` into a separate class `SemaOpenACC` that is placed in a separate header `Sema/SemaOpenACC.h`. This patch is intended to be a model of factoring things out of `Sema`, so I picked a small OpenACC part. Goals are the following: 1) Split `Sema` into manageable parts. 2) Make dependencies between parts visible. 3) Improve Clang development cycle by avoiding recompiling unrelated parts of the compiler. 4) Avoid compile-time regressions. 5) Avoid notational regressions in the code that uses Sema. --- clang/include/clang/Sema/Sema.h| 77 -- clang/include/clang/Sema/SemaOpenACC.h | 68 +++ clang/lib/Parse/ParseOpenACC.cpp | 22 clang/lib/Sema/Sema.cpp| 4 +- clang/lib/Sema/SemaOpenACC.cpp | 44 --- clang/lib/Sema/TreeTransform.h | 11 ++-- 6 files changed, 137 insertions(+), 89 deletions(-) create mode 100644 clang/include/clang/Sema/SemaOpenACC.h diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index f3d3a57104ee07..932676c52b1f30 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -183,6 +183,7 @@ class Preprocessor; class PseudoDestructorTypeStorage; class PseudoObjectExpr; class QualType; +class SemaOpenACC; class StandardConversionSequence; class Stmt; class StringLiteral; @@ -466,9 +467,8 @@ class Sema final { // 37. Name Lookup for RISC-V Vector Intrinsic (SemaRISCVVectorLookup.cpp) // 38. CUDA (SemaCUDA.cpp) // 39. HLSL Constructs (SemaHLSL.cpp) - // 40. OpenACC Constructs (SemaOpenACC.cpp) - // 41. OpenMP Directives and Clauses (SemaOpenMP.cpp) - // 42. SYCL Constructs (SemaSYCL.cpp) + // 40. OpenMP Directives and Clauses (SemaOpenMP.cpp) + // 41. SYCL Constructs (SemaSYCL.cpp) /// \name Semantic Analysis /// Implementations are in Sema.cpp @@ -1200,6 +1200,27 @@ class Sema final { // // + /// \name Sema Components + /// Parts of Sema + ///@{ + + // Just in this section, private members are followed by public, because + // C++ requires us to create (private) objects before (public) references. + +private: + std::unique_ptr OpenACCPtr; + +public: + SemaOpenACC + + ///@} + + // + // + // - + // + // + /// \name C++ Access Control /// Implementations are in SemaAccess.cpp ///@{ @@ -13309,56 +13330,6 @@ class Sema final { // // - /// \name OpenACC Constructs - /// Implementations are in SemaOpenACC.cpp - ///@{ - -public: - /// Called after parsing an OpenACC Clause so that it can be checked. - bool ActOnOpenACCClause(OpenACCClauseKind ClauseKind, - SourceLocation StartLoc); - - /// Called after the construct has been parsed, but clauses haven't been - /// parsed. This allows us to diagnose not-implemented, as well as set up any - /// state required for parsing the clauses. - void ActOnOpenACCConstruct(OpenACCDirectiveKind K, SourceLocation StartLoc); - - /// Called after the directive, including its clauses, have been parsed and - /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES - /// happen before any associated declarations or statements have been parsed. - /// This function is only called when we are parsing a 'statement' context. - bool ActOnStartOpenACCStmtDirective(OpenACCDirectiveKind K, - SourceLocation StartLoc); - - /// Called after the directive, including its clauses, have been parsed and - /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES - /// happen before any associated declarations or statements have been parsed. - /// This function is only called when we are parsing a 'Decl' context. - bool ActOnStartOpenACCDeclDirective(OpenACCDirectiveKind K, - SourceLocation StartLoc); - /// Called when we encounter an associated statement for our construct, this - /// should check legality of the statement as it appertains to this Construct. - StmtResult ActOnOpenACCAssociatedStmt(OpenACCDirectiveKind K, -StmtResult AssocStmt); - - /// Called after the directive has been completely parsed, including the - /// declaration group or associated statement. - StmtResult ActOnEndOpenACCStmtDirective(OpenACCDirectiveKind K, - SourceLocation StartLoc, - SourceLocation EndLoc, - StmtResult AssocStmt); - /// Called after the directive has been
[clang] [clang] Factor out OpenACC part of `Sema` (PR #84184)
https://github.com/AaronBallman approved this pull request. LGTM, but I think the next steps are two-fold: add a second `Sema` class for something else (perhaps OpenMP?) and add a base class for accessing commonly used functionality (`getASTContext()`, `Diag()`, etc). https://github.com/llvm/llvm-project/pull/84184 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Move tailclipping to bitfield allocation (PR #87090)
https://github.com/urnathan converted_to_draft https://github.com/llvm/llvm-project/pull/87090 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Fix bitfield access unit for vbase corner case (PR #87238)
https://github.com/urnathan created https://github.com/llvm/llvm-project/pull/87238 This fixes #87227 My change to bitfield access unit allocation (#65742) causes an ICE for a corner case of vbase allocation: a class where an unshared (i.e. not the nearly-empty base optimization) vbase is placed below nvsize. Unfortunately, although there was a testcase for such a class layout, it didn't have the immediately preceding bitfield -- the reason the scissor needs to be correct. The fix is to break out the scissor calculation from `accumulateVbases`, and have `allocateBitfields` be aware it is creating either the base subobject, or the complete object. Then it can call the scissor calculator to get the appropriate upper bound. The scissor calculation can cause a base walk, I thought it best to cache the result in `allocateBitfields`, as we can reach that point multiple times with unfortunately-sized bitfield spans. In breaking out the scissor calculation, I discovered a couple more member fns that could be const qualified -- as before do you want that as a separate PR? >From 3b0bfce77d6d70bc35316484b39bb83123b8a583 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Sun, 31 Mar 2024 11:11:13 -0400 Subject: [PATCH] [clang] Fix bitfield access unit for vbase corner case We must account for unshared vbases that are allocated below nvsize. --- clang/lib/CodeGen/CGRecordLayoutBuilder.cpp | 57 +++--- .../test/CodeGenCXX/bitfield-access-tail.cpp | 104 -- 2 files changed, 113 insertions(+), 48 deletions(-) diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp index e32023aeac1e6f..634a55fec5182e 100644 --- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -185,9 +185,10 @@ struct CGRecordLowering { /// Lowers an ASTRecordLayout to a llvm type. void lower(bool NonVirtualBaseType); void lowerUnion(bool isNoUniqueAddress); - void accumulateFields(); + void accumulateFields(bool isNonVirtualBaseType); RecordDecl::field_iterator - accumulateBitFields(RecordDecl::field_iterator Field, + accumulateBitFields(bool isNonVirtualBaseType, + RecordDecl::field_iterator Field, RecordDecl::field_iterator FieldEnd); void computeVolatileBitfields(); void accumulateBases(); @@ -195,8 +196,10 @@ struct CGRecordLowering { void accumulateVBases(); /// Recursively searches all of the bases to find out if a vbase is /// not the primary vbase of some base class. - bool hasOwnStorage(const CXXRecordDecl *Decl, const CXXRecordDecl *Query); + bool hasOwnStorage(const CXXRecordDecl *Decl, + const CXXRecordDecl *Query) const; void calculateZeroInit(); + CharUnits calculateTailClippingOffset(bool isNonVirtualBaseType) const; /// Lowers bitfield storage types to I8 arrays for bitfields with tail /// padding that is or can potentially be used. void clipTailPadding(); @@ -287,7 +290,7 @@ void CGRecordLowering::lower(bool NVBaseType) { computeVolatileBitfields(); return; } - accumulateFields(); + accumulateFields(NVBaseType); // RD implies C++. if (RD) { accumulateVPtrs(); @@ -378,12 +381,12 @@ void CGRecordLowering::lowerUnion(bool isNoUniqueAddress) { Packed = true; } -void CGRecordLowering::accumulateFields() { +void CGRecordLowering::accumulateFields(bool isNonVirtualBaseType) { for (RecordDecl::field_iterator Field = D->field_begin(), FieldEnd = D->field_end(); Field != FieldEnd;) { if (Field->isBitField()) { - Field = accumulateBitFields(Field, FieldEnd); + Field = accumulateBitFields(isNonVirtualBaseType, Field, FieldEnd); assert((Field == FieldEnd || !Field->isBitField()) && "Failed to accumulate all the bitfields"); } else if (Field->isZeroSize(Context)) { @@ -404,9 +407,12 @@ void CGRecordLowering::accumulateFields() { } // Create members for bitfields. Field is a bitfield, and FieldEnd is the end -// iterator of the record. Return the first non-bitfield encountered. +// iterator of the record. Return the first non-bitfield encountered. We need +// to know whether this is the base or complete layout, as virtual bases could +// affect the upper bound of bitfield access unit allocation. RecordDecl::field_iterator -CGRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field, +CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType, + RecordDecl::field_iterator Field, RecordDecl::field_iterator FieldEnd) { if (isDiscreteBitFieldABI()) { // Run stores the first element of the current run of bitfields. FieldEnd is @@ -505,6 +511,10 @@ CGRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field,
[clang] [clang][dataflow] Refactor `widen` API to be explicit about change effect. (PR #87233)
https://github.com/ymand updated https://github.com/llvm/llvm-project/pull/87233 >From d8d875271bd47b71701143afb06ea654546e2b7c Mon Sep 17 00:00:00 2001 From: Yitzhak Mandelbaum Date: Mon, 1 Apr 2024 12:13:39 + Subject: [PATCH] [clang][dataflow] Refactor `widen` API to be explicit about change effect. The previous API relied on pointer equality of inputs and outputs to signal whether a change occured. This was too subtle and led to bugs in practice. It was also very limiting: the override could not return an equivalent (but not identical) value. --- .../FlowSensitive/DataflowEnvironment.h | 47 +++--- .../FlowSensitive/DataflowEnvironment.cpp | 43 ++--- .../TypeErasedDataflowAnalysisTest.cpp| 48 +++ 3 files changed, 104 insertions(+), 34 deletions(-) diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h index c30bccd06674a4..0a37d9d68e2898 100644 --- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h +++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h @@ -97,6 +97,16 @@ class Environment { const Value , const Environment , Value , Environment ) {} +/// The result of the `widen` operation. +struct WidenResult { + /// Non-null pointer to a potentially widened version of the widening + /// input. + Value *V; + /// Whether `V` represents a "change" (that is, a different value) with + /// respect to the previous value in the sequence. + LatticeJoinEffect Effect; +}; + /// This function may widen the current value -- replace it with an /// approximation that can reach a fixed point more quickly than iterated /// application of the transfer function alone. The previous value is @@ -104,14 +114,17 @@ class Environment { /// serve as a comparison operation, by indicating whether the widened value /// is equivalent to the previous value. /// -/// Returns either: -/// -/// `nullptr`, if this value is not of interest to the model, or -/// -/// ``, if the widened value is equivalent to `Prev`, or -/// -/// A non-null value that approximates `Current`. `Prev` is available to -/// inform the chosen approximation. +/// Returns one of the folowing: +/// * `std::nullopt`, if this value is not of interest to the +/// model. +/// * A `WidenResult` with: +///* A non-null `Value *` that points either to `Current` or a widened +/// version of `Current`. This value must be consistent with +/// the flow condition of `CurrentEnv`. We particularly caution +/// against using `Prev`, which is rarely consistent. +///* A `LatticeJoinEffect` indicating whether the value should be +/// considered a new value (`Changed`) or one *equivalent* (if not +/// necessarily equal) to `Prev` (`Unchanged`). /// /// `PrevEnv` and `CurrentEnv` can be used to query child values and path /// condition implications of `Prev` and `Current`, respectively. @@ -122,17 +135,19 @@ class Environment { /// /// `Prev` and `Current` must be assigned to the same storage location in /// `PrevEnv` and `CurrentEnv`, respectively. -virtual Value *widen(QualType Type, Value , const Environment , - Value , Environment ) { +virtual std::optional widen(QualType Type, Value , + const Environment , + Value , + Environment ) { // The default implementation reduces to just comparison, since comparison // is required by the API, even if no widening is performed. switch (compare(Type, Prev, PrevEnv, Current, CurrentEnv)) { -case ComparisonResult::Same: - return -case ComparisonResult::Different: - return -case ComparisonResult::Unknown: - return nullptr; + case ComparisonResult::Unknown: +return std::nullopt; + case ComparisonResult::Same: +return WidenResult{, LatticeJoinEffect::Unchanged}; + case ComparisonResult::Different: +return WidenResult{, LatticeJoinEffect::Changed}; } llvm_unreachable("all cases in switch covered"); } diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index f729d676dd0de8..8ae51b7cdb444d 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -166,17 +166,20 @@ static Value *joinDistinctValues(QualType Type, Value , return JoinedVal; } -// When widening does not change `Current`, return value will equal ``. -static Value
[clang] [RFC][Clang] Enable custom type checking for printf (PR #86801)
AaronBallman wrote: > > I looked at the OpenCL spec for C standard library support and was > > surprised that 1) it's only talking about C99 so it's unclear what happens > > for C11 (clause 6 says "This document describes the modifications and > > restrictions to C99 and C11 in OpenCL C" but 6.11 only talks about C99 > > headers and leaves `iso646.h`, `math.h`, `stdbool.h`, `stddef.h`, (all in > > C99) as well as `stdalign.h`, `stdatomic.h`, `stdnoreturn.h`, `threads.h`, > > and `uchar.h` available?), and 2) OpenCL's `printf` is not really the same > > function as C's `printf` > > (https://registry.khronos.org/OpenCL/specs/3.0-unified/html/OpenCL_C.html#differences-between-opencl-c-and-c99-printf). > > #1 is probably more of an oversight than anything, at least with the C11 > > headers. So maybe this isn't a super slippery slope, but maybe C23 will > > change that (I can imagine `stdbit.h` being of use in OpenCL for > > bit-bashing operations). However, the fact that the builtin isn't really > > `printf` but is `printf`-like makes me think we should make it a separate > > builtin to avoid surprises (we do diagnostics based on builtin IDs and we > > have special checking logic that we perhaps should be exempting in some > > cases). > > Understood. Then I propose the following. > > 1. Currently Builtin TableGen does not seem to support specifying lang > address spaces in function prototypes. this needs to be implemented first if > not already in development. > > 2. We could have two new macro variants probably named "OCL_BUILTIN" and > "OCL_LIB_BUILTIN" which will take the ID's of the form > "BI_OCL##". we would also need corresponding TableGen classes > (probably named similar to the macros) which can expose such overloaded > prototypes when required. > > > How does this sound ? I think that sounds like a reasonable way forward, thank you! https://github.com/llvm/llvm-project/pull/86801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Fix __is_array returning true for zero-sized arrays (PR #86652)
AaronBallman wrote: > Last time I checked, neither GCC nor Clang allowed T[0] to match a partial > specialization for `is_array` so the extension isn't very well extended > :) Oh, I agree, I am learning to loathe this extension the more I look into this. Did you see this lovely bit: > Oh wow, and it gets even more surprising... adding a zero-length array to a > structure reduces the size of the structure (in C++): > https://godbolt.org/z/5E4YsT1Ye But that's why I'm asking questions about what we *should* be doing with the feature overall. As it currently stands, this extension seems like it is broken in C++ in multiple ways. Fixing a tiny corner of it is fine, but I'd like to know what the overall big picture is so we can know whether the tiny corner changes fit or not. We could fix this by changing partial specializations to care about zero-sized arrays, too. (Personally, I would love to "fix" this by deprecating the extension as the only justification for it I've been able to dig up is as a hack for flexible arrays -- deprecating this extension outside of GNU89 mode has some appeal, barring other information about its value.) https://github.com/llvm/llvm-project/pull/86652 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Fix __is_array returning true for zero-sized arrays (PR #86652)
jwakely wrote: Last time I checked, neither GCC nor Clang allowed T[0] to match a partial specialization for `is_array` so the extension isn't very well extended :) https://github.com/llvm/llvm-project/pull/86652 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][dataflow] Refactor `widen` API to be explicit about change effect. (PR #87233)
https://github.com/ymand updated https://github.com/llvm/llvm-project/pull/87233 >From b7f63ed7ca3c503f55eccc215f0a66368e2c5e5e Mon Sep 17 00:00:00 2001 From: Yitzhak Mandelbaum Date: Mon, 1 Apr 2024 12:13:39 + Subject: [PATCH] [clang][dataflow] Refactor `widen` API to be explicit about change effect. The previous API relied on pointer equality of inputs and outputs to signal whether a change occured. This was too subtle and led to bugs in practice. It was also very limiting: the override could not return an equivalent (but not identical) value. --- .../FlowSensitive/DataflowEnvironment.h | 47 --- .../FlowSensitive/DataflowEnvironment.cpp | 43 ++--- 2 files changed, 56 insertions(+), 34 deletions(-) diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h index c30bccd06674a4..0a37d9d68e2898 100644 --- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h +++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h @@ -97,6 +97,16 @@ class Environment { const Value , const Environment , Value , Environment ) {} +/// The result of the `widen` operation. +struct WidenResult { + /// Non-null pointer to a potentially widened version of the widening + /// input. + Value *V; + /// Whether `V` represents a "change" (that is, a different value) with + /// respect to the previous value in the sequence. + LatticeJoinEffect Effect; +}; + /// This function may widen the current value -- replace it with an /// approximation that can reach a fixed point more quickly than iterated /// application of the transfer function alone. The previous value is @@ -104,14 +114,17 @@ class Environment { /// serve as a comparison operation, by indicating whether the widened value /// is equivalent to the previous value. /// -/// Returns either: -/// -/// `nullptr`, if this value is not of interest to the model, or -/// -/// ``, if the widened value is equivalent to `Prev`, or -/// -/// A non-null value that approximates `Current`. `Prev` is available to -/// inform the chosen approximation. +/// Returns one of the folowing: +/// * `std::nullopt`, if this value is not of interest to the +/// model. +/// * A `WidenResult` with: +///* A non-null `Value *` that points either to `Current` or a widened +/// version of `Current`. This value must be consistent with +/// the flow condition of `CurrentEnv`. We particularly caution +/// against using `Prev`, which is rarely consistent. +///* A `LatticeJoinEffect` indicating whether the value should be +/// considered a new value (`Changed`) or one *equivalent* (if not +/// necessarily equal) to `Prev` (`Unchanged`). /// /// `PrevEnv` and `CurrentEnv` can be used to query child values and path /// condition implications of `Prev` and `Current`, respectively. @@ -122,17 +135,19 @@ class Environment { /// /// `Prev` and `Current` must be assigned to the same storage location in /// `PrevEnv` and `CurrentEnv`, respectively. -virtual Value *widen(QualType Type, Value , const Environment , - Value , Environment ) { +virtual std::optional widen(QualType Type, Value , + const Environment , + Value , + Environment ) { // The default implementation reduces to just comparison, since comparison // is required by the API, even if no widening is performed. switch (compare(Type, Prev, PrevEnv, Current, CurrentEnv)) { -case ComparisonResult::Same: - return -case ComparisonResult::Different: - return -case ComparisonResult::Unknown: - return nullptr; + case ComparisonResult::Unknown: +return std::nullopt; + case ComparisonResult::Same: +return WidenResult{, LatticeJoinEffect::Unchanged}; + case ComparisonResult::Different: +return WidenResult{, LatticeJoinEffect::Changed}; } llvm_unreachable("all cases in switch covered"); } diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index f729d676dd0de8..8ae51b7cdb444d 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -166,17 +166,20 @@ static Value *joinDistinctValues(QualType Type, Value , return JoinedVal; } -// When widening does not change `Current`, return value will equal ``. -static Value (QualType Type, Value , - const
[clang] [clang][dataflow] Refactor `widen` API to be explicit about change effect. (PR #87233)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff a1a8bb1d3ae9a535526aba9514e87f76e2d040fa 6889df911a11fc5c27149f138176166aef3e1f73 -- clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp `` View the diff from clang-format here. ``diff diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h index 8e4e846e59..0a37d9d68e 100644 --- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h +++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h @@ -142,12 +142,12 @@ public: // The default implementation reduces to just comparison, since comparison // is required by the API, even if no widening is performed. switch (compare(Type, Prev, PrevEnv, Current, CurrentEnv)) { -case ComparisonResult::Unknown: - return std::nullopt; -case ComparisonResult::Same: - return WidenResult{, LatticeJoinEffect::Unchanged}; -case ComparisonResult::Different: - return WidenResult{, LatticeJoinEffect::Changed}; + case ComparisonResult::Unknown: +return std::nullopt; + case ComparisonResult::Same: +return WidenResult{, LatticeJoinEffect::Unchanged}; + case ComparisonResult::Different: +return WidenResult{, LatticeJoinEffect::Changed}; } llvm_unreachable("all cases in switch covered"); } diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index d41f03262e..8ae51b7cdb 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -170,9 +170,10 @@ namespace { using WidenResult = Environment::ValueModel::WidenResult; } -static WidenResult widenDistinctValues( -QualType Type, Value , const Environment , Value , -Environment , Environment::ValueModel ) { +static WidenResult widenDistinctValues(QualType Type, Value , + const Environment , + Value , Environment , + Environment::ValueModel ) { // Boolean-model widening. if (auto *PrevBool = dyn_cast()) { if (isa(Prev)) `` https://github.com/llvm/llvm-project/pull/87233 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Fix __is_array returning true for zero-sized arrays (PR #86652)
AaronBallman wrote: > As I've just commented at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114479 > the `__is_array` intrinsic exists to optimize `std::is_array` and so should > match its existing behaviour. If you want to change the behaviour of > `std::is_array` then please do so via an LWG issue, e.g. requesting > clarification of the behaviour for `T[0]`. > > An optimization to speed up compilation of `std::is_array` should not dictate > its behaviour. Errr, I think there's some circular logic here perhaps: > [dcl.array] says that for T[N] the value "N specifies the array bound, i.e., > the number of elements in the array; N shall be greater than zero." > > So T[0] is not a valid array type. Except `T[0]` is a valid array type because it's supported as a language extension in Clang and GCC; that's the whole reason you can spell `T[0]` at all. This boils down to a fundamental question: what makes something an array type in the first place? Is it the declaration syntax or is it the semantics? If it's declaration syntax, then `T[0]` is clearly an array type. If it's semantics, then `T[0]` is not an array type but `std::vector` is. Personally, I think the declaration syntax is what makes something an array type per https://eel.is/c++draft/dcl.array#1 saying "a declaration of the form". Yes, it says the size shall not be zero, but that's the bit we've extended, so it's circular to say "the standard says zero isn't allowed and therefore the library behavior is to return false from std::is_array". So I think I'm arguing for an LWG issue. https://github.com/llvm/llvm-project/pull/86652 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][dataflow] Refactor `widen` API to be explicit about change effect. (PR #87233)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Yitzhak Mandelbaum (ymand) Changes The previous API relied on pointer equality of inputs and outputs to signal whether a change occured. This was too subtle and led to bugs in practice. It was also very limiting: the override could not return an equivalent (but not identical) value. --- Full diff: https://github.com/llvm/llvm-project/pull/87233.diff 2 Files Affected: - (modified) clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h (+29-14) - (modified) clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp (+24-18) ``diff diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h index c30bccd06674a4..8e4e846e594f5b 100644 --- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h +++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h @@ -97,6 +97,16 @@ class Environment { const Value , const Environment , Value , Environment ) {} +/// The result of the `widen` operation. +struct WidenResult { + /// Non-null pointer to a potentially widened version of the widening + /// input. + Value *V; + /// Whether `V` represents a "change" (that is, a different value) with + /// respect to the previous value in the sequence. + LatticeJoinEffect Effect; +}; + /// This function may widen the current value -- replace it with an /// approximation that can reach a fixed point more quickly than iterated /// application of the transfer function alone. The previous value is @@ -104,14 +114,17 @@ class Environment { /// serve as a comparison operation, by indicating whether the widened value /// is equivalent to the previous value. /// -/// Returns either: -/// -/// `nullptr`, if this value is not of interest to the model, or -/// -/// ``, if the widened value is equivalent to `Prev`, or -/// -/// A non-null value that approximates `Current`. `Prev` is available to -/// inform the chosen approximation. +/// Returns one of the folowing: +/// * `std::nullopt`, if this value is not of interest to the +/// model. +/// * A `WidenResult` with: +///* A non-null `Value *` that points either to `Current` or a widened +/// version of `Current`. This value must be consistent with +/// the flow condition of `CurrentEnv`. We particularly caution +/// against using `Prev`, which is rarely consistent. +///* A `LatticeJoinEffect` indicating whether the value should be +/// considered a new value (`Changed`) or one *equivalent* (if not +/// necessarily equal) to `Prev` (`Unchanged`). /// /// `PrevEnv` and `CurrentEnv` can be used to query child values and path /// condition implications of `Prev` and `Current`, respectively. @@ -122,17 +135,19 @@ class Environment { /// /// `Prev` and `Current` must be assigned to the same storage location in /// `PrevEnv` and `CurrentEnv`, respectively. -virtual Value *widen(QualType Type, Value , const Environment , - Value , Environment ) { +virtual std::optional widen(QualType Type, Value , + const Environment , + Value , + Environment ) { // The default implementation reduces to just comparison, since comparison // is required by the API, even if no widening is performed. switch (compare(Type, Prev, PrevEnv, Current, CurrentEnv)) { +case ComparisonResult::Unknown: + return std::nullopt; case ComparisonResult::Same: - return + return WidenResult{, LatticeJoinEffect::Unchanged}; case ComparisonResult::Different: - return -case ComparisonResult::Unknown: - return nullptr; + return WidenResult{, LatticeJoinEffect::Changed}; } llvm_unreachable("all cases in switch covered"); } diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index f729d676dd0de8..d41f03262ecf4c 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -166,17 +166,19 @@ static Value *joinDistinctValues(QualType Type, Value , return JoinedVal; } -// When widening does not change `Current`, return value will equal ``. -static Value (QualType Type, Value , - const Environment , Value , - Environment , - Environment::ValueModel ) { +namespace { +using WidenResult = Environment::ValueModel::WidenResult; +} + +static
[clang] [clang][dataflow] Refactor `widen` API to be explicit about change effect. (PR #87233)
https://github.com/ymand created https://github.com/llvm/llvm-project/pull/87233 The previous API relied on pointer equality of inputs and outputs to signal whether a change occured. This was too subtle and led to bugs in practice. It was also very limiting: the override could not return an equivalent (but not identical) value. >From 6889df911a11fc5c27149f138176166aef3e1f73 Mon Sep 17 00:00:00 2001 From: Yitzhak Mandelbaum Date: Mon, 1 Apr 2024 12:13:39 + Subject: [PATCH] [clang][dataflow] Refactor `widen` API to be explicit about change effect. The previous API relied on pointer equality of inputs and outputs to signal whether a change occured. This was too subtle and led to bugs in practice. It was also very limiting: the override could not return an equivalent (but not identical) value. --- .../FlowSensitive/DataflowEnvironment.h | 43 +-- .../FlowSensitive/DataflowEnvironment.cpp | 42 ++ 2 files changed, 53 insertions(+), 32 deletions(-) diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h index c30bccd06674a4..8e4e846e594f5b 100644 --- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h +++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h @@ -97,6 +97,16 @@ class Environment { const Value , const Environment , Value , Environment ) {} +/// The result of the `widen` operation. +struct WidenResult { + /// Non-null pointer to a potentially widened version of the widening + /// input. + Value *V; + /// Whether `V` represents a "change" (that is, a different value) with + /// respect to the previous value in the sequence. + LatticeJoinEffect Effect; +}; + /// This function may widen the current value -- replace it with an /// approximation that can reach a fixed point more quickly than iterated /// application of the transfer function alone. The previous value is @@ -104,14 +114,17 @@ class Environment { /// serve as a comparison operation, by indicating whether the widened value /// is equivalent to the previous value. /// -/// Returns either: -/// -/// `nullptr`, if this value is not of interest to the model, or -/// -/// ``, if the widened value is equivalent to `Prev`, or -/// -/// A non-null value that approximates `Current`. `Prev` is available to -/// inform the chosen approximation. +/// Returns one of the folowing: +/// * `std::nullopt`, if this value is not of interest to the +/// model. +/// * A `WidenResult` with: +///* A non-null `Value *` that points either to `Current` or a widened +/// version of `Current`. This value must be consistent with +/// the flow condition of `CurrentEnv`. We particularly caution +/// against using `Prev`, which is rarely consistent. +///* A `LatticeJoinEffect` indicating whether the value should be +/// considered a new value (`Changed`) or one *equivalent* (if not +/// necessarily equal) to `Prev` (`Unchanged`). /// /// `PrevEnv` and `CurrentEnv` can be used to query child values and path /// condition implications of `Prev` and `Current`, respectively. @@ -122,17 +135,19 @@ class Environment { /// /// `Prev` and `Current` must be assigned to the same storage location in /// `PrevEnv` and `CurrentEnv`, respectively. -virtual Value *widen(QualType Type, Value , const Environment , - Value , Environment ) { +virtual std::optional widen(QualType Type, Value , + const Environment , + Value , + Environment ) { // The default implementation reduces to just comparison, since comparison // is required by the API, even if no widening is performed. switch (compare(Type, Prev, PrevEnv, Current, CurrentEnv)) { +case ComparisonResult::Unknown: + return std::nullopt; case ComparisonResult::Same: - return + return WidenResult{, LatticeJoinEffect::Unchanged}; case ComparisonResult::Different: - return -case ComparisonResult::Unknown: - return nullptr; + return WidenResult{, LatticeJoinEffect::Changed}; } llvm_unreachable("all cases in switch covered"); } diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index f729d676dd0de8..d41f03262ecf4c 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -166,17 +166,19 @@ static Value *joinDistinctValues(QualType Type, Value ,
[clang] [llvm] MIPS: Support -m(no-)unaligned-access for r6 (PR #85174)
urnathan wrote: #65742 is committed, so MIPS' TargetInfo will need adjusting to propagate the unaligned capability. See 7df79ababee8 https://github.com/llvm/llvm-project/pull/85174 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C99] Claim conformance to WG14 N717 (PR #87228)
github-actions[bot] wrote: :warning: Python code formatter, darker found issues in your code. :warning: You can test this locally with the following command: ``bash darker --check --diff -r 84299df301dc07ea83fa8378051103195c3a7c65...f8e130df9e602662444280346b71a82347ae8a29 clang/test/C/C99/n717.py `` View the diff from darker here. ``diff --- n717.py 2024-04-01 11:27:32.00 + +++ n717.py 2024-04-01 11:32:12.636120 + @@ -1,29 +1,41 @@ print("#define M(arg)") + def test(size): - Prefix = 'U' if size == 8 else 'u' - # [0x to 0x00A0) excluding [0x0020, 0x007F) - for val in [val for val in range(0x, 0x00A0) if val < 0x0020 or val >= 0x007F]: - print(f'M(\\{Prefix}{val:0{size}X}) // expected-error universal character name refers to a control character') - print('') - - # [0x0020 to 0x007F), excluding 0x0024, 0x0040, and 0x0060 - for val in [val for val in range(0x0020, 0x007F) if val != 0x0024 and val != 0x0040 and val != 0x0060]: - print(f"M(\\{Prefix}{val:0{size}X}) // expected-error character '{chr(val)}' cannot be specified by a universal character name") - print('') - - # [0xD800 to 0xDFFF] - for val in range(0xD800, 0xDFFF + 1): -print(f'M(\\{Prefix}{val:0{size}X}) // expected-error invalid universal character') - print('') - - # Everything in this range should be accepted, though it may produce a - # warning diagnostic for things like homoglyphs, whitespace, etc. - for val in range(0x00A1, 0xD800): -print(f'M(\\{Prefix}{val:0{size}X})') - print('') +Prefix = "U" if size == 8 else "u" +# [0x to 0x00A0) excluding [0x0020, 0x007F) +for val in [val for val in range(0x, 0x00A0) if val < 0x0020 or val >= 0x007F]: +print( +f"M(\\{Prefix}{val:0{size}X}) // expected-error universal character name refers to a control character" +) +print("") + +# [0x0020 to 0x007F), excluding 0x0024, 0x0040, and 0x0060 +for val in [ +val +for val in range(0x0020, 0x007F) +if val != 0x0024 and val != 0x0040 and val != 0x0060 +]: +print( +f"M(\\{Prefix}{val:0{size}X}) // expected-error character '{chr(val)}' cannot be specified by a universal character name" +) +print("") + +# [0xD800 to 0xDFFF] +for val in range(0xD800, 0xDFFF + 1): +print( +f"M(\\{Prefix}{val:0{size}X}) // expected-error invalid universal character" +) +print("") + +# Everything in this range should be accepted, though it may produce a +# warning diagnostic for things like homoglyphs, whitespace, etc. +for val in range(0x00A1, 0xD800): +print(f"M(\\{Prefix}{val:0{size}X})") +print("") + # Print \u tests test(4) # Print \U tests test(8) @@ -32,8 +44,8 @@ # within the valid (short) range. # This is disabled because enabling the test 1) requires using L because u and # U don't exist until C11, 2) is questionable in terms of value because the # code points could be different if L isn't using a Unicode encoding, and 3) # this addition to the test adds 10x the execution time when running the test. -#for val in range(0x00A1, 0xD800): +# for val in range(0x00A1, 0xD800): # print(f"_Static_assert(L'\\u{val:04X}' == L'\\U{val:08X}', \"\");") -#print('') +# print('') `` https://github.com/llvm/llvm-project/pull/87228 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C99] Claim conformance to WG14 N717 (PR #87228)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Aaron Ballman (AaronBallman) Changes This was the paper that added Universal Character Names to C. --- Full diff: https://github.com/llvm/llvm-project/pull/87228.diff 3 Files Affected: - (added) clang/test/C/C99/n717.c (+69) - (added) clang/test/C/C99/n717.py (+39) - (modified) clang/www/c_status.html (+1-1) ``diff diff --git a/clang/test/C/C99/n717.c b/clang/test/C/C99/n717.c new file mode 100644 index 00..cc1aa0fd5d53cf --- /dev/null +++ b/clang/test/C/C99/n717.c @@ -0,0 +1,69 @@ +// RUN: %clang_cc1 -verify -std=c99 %s +// RUN: %clang_cc1 -verify -std=c99 -fno-dollars-in-identifiers %s + +/* WG14 N717: Clang 17 + * Extended identifiers + */ + +// Used as a sink for UCNs. +#define M(arg) + +// C99 6.4.3p1 specifies the grammar for UCNs. A \u must be followed by exactly +// four hex digits, and \U must be followed by exactly eight. +M(\u1)// expected-warning {{incomplete universal character name; treating as '\' followed by identifier}} +M(\u12) // expected-warning {{incomplete universal character name; treating as '\' followed by identifier}} +M(\u123) // expected-warning {{incomplete universal character name; treating as '\' followed by identifier}} +M(\u1234) // Okay +M(\u12345)// Okay, two tokens (UCN followed by 5) + +M(\U1) // expected-warning {{incomplete universal character name; treating as '\' followed by identifier}} +M(\U12)// expected-warning {{incomplete universal character name; treating as '\' followed by identifier}} +M(\U123) // expected-warning {{incomplete universal character name; treating as '\' followed by identifier}} +M(\U1234) // expected-warning {{incomplete universal character name; treating as '\' followed by identifier}} \ + expected-note {{did you mean to use '\u'?}} +M(\U12345) // expected-warning {{incomplete universal character name; treating as '\' followed by identifier}} +M(\U123456)// expected-warning {{incomplete universal character name; treating as '\' followed by identifier}} +M(\U1234567) // expected-warning {{incomplete universal character name; treating as '\' followed by identifier}} +M(\U12345678) // Okay +M(\U123456789) // Okay-ish, two tokens (valid-per-spec-but-actually-invalid UCN followed by 9) + +// C99 6.4.3p2: +// A universal character name shall not specify a character whose short +// identifier is less than 00A0 other than 0024 ($), 0040 (@), or 0060 (�), nor +// one in the range D800 through DFFF inclusive. +// +// We use a python script to generate the test contents for the large ranges +// without edge cases. +// RUN: %python %S/n717.py >%t.inc +// RUN: %clang_cc1 -verify -std=c99 -Wno-unicode-whitespace -Wno-unicode-homoglyph -Wno-unicode-zero-width -Wno-mathematical-notation-identifier-extension %t.inc + +// Now test the ones that should work. Note, these work in C17 and earlier but +// are part of the basic character set in C23 and thus should be diagnosed in +// that mode. They're valid in a character constant, but not valid in an +// identifier, except for U+0024 which is allowed if -fdollars-in-identifiers +// is enabled. +// FIXME: These three should be handled the same way, and should be accepted +// when dollar signs are allowed in identifiers, rather than rejected, see +// GH87106. +M(\u0024) // expected-error {{character '$' cannot be specified by a universal character name}} +M(\U0024) // expected-error {{character '$' cannot be specified by a universal character name}} +M($) + +// These should always be rejected because they're not valid identifier +// characters. +// FIXME: the diagnostic could be improved to make it clear this is an issue +// with forming an identifier rather than a UCN. +M(\u0040) // expected-error {{character '@' cannot be specified by a universal character name}} +M(\u0060) // expected-error {{character '`' cannot be specified by a universal character name}} +M(\U0040) // expected-error {{character '@' cannot be specified by a universal character name}} +M(\U0060) // expected-error {{character '`' cannot be specified by a universal character name}} + +// These should always be accepted because they're a valid in a character +// constant. +M('\u0024') +M('\u0040') +M('\u0060') + +M('\U0024') +M('\U0040') +M('\U0060') diff --git a/clang/test/C/C99/n717.py b/clang/test/C/C99/n717.py new file mode 100644 index 00..8c02d336ff6f60 --- /dev/null +++ b/clang/test/C/C99/n717.py @@ -0,0 +1,39 @@ +print("#define M(arg)") + +def test(size): + Prefix = 'U' if size == 8 else 'u' + # [0x to 0x00A0) excluding [0x0020, 0x007F) + for val in [val for val in range(0x, 0x00A0) if val < 0x0020 or val >= 0x007F]: + print(f'M(\\{Prefix}{val:0{size}X}) // expected-error universal character name refers to a control character') + print('') + + # [0x0020 to 0x007F), excluding 0x0024, 0x0040, and 0x0060 + for
[clang] [llvm] [PowerPC] Implement 32-bit expansion for rldimi (PR #86783)
bzEq wrote: > due to backward compatibility, it needs to be expanded into series of rlwimi > in 32-bit environment Why must be 'series of rlwimi'? Why don't we just expand it following what ISA describes and let legalizer generates code sequence under 32-bit mode? ``` n ← sh5 || sh0:4 r ← ROTL64((RS), n) b ← mb5 || mb0:4 m ← MASK(b, ¬n) RA ← r | (RA) & ¬m ``` https://github.com/llvm/llvm-project/pull/86783 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)
Pol Marcet =?utf-8?q?Sardà?= , Pol Marcet =?utf-8?q?Sardà?= , Pol Marcet =?utf-8?q?Sardà?= Message-ID: In-Reply-To: @@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { return Success(APValue(ResultElements.data(), ResultElements.size()), E); } +static bool EvaluateVectorOrLValue(APValue , EvalInfo , + const Expr *E, const QualType ) { + if (!Evaluate(Result, Info, E)) +return false; + + if (Result.isLValue()) { +// Source of the data is an lvalue; Manually handle the lvalue as if +// it was an rvalue to get the current APValue. +LValue LValueFound; +LValueFound.setFrom(Info.Ctx, Result); +if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result)) + return false; + } + + return Result.isVector(); +} + +static bool handleVectorConversion(EvalInfo , const FPOptions FPO, + const Expr *E, QualType SourceTy, + QualType DestTy, APValue const , + APValue ) { + if (SourceTy->isIntegerType()) { +if (DestTy->isRealFloatingType()) { + Result = APValue(APFloat(0.0)); + return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(), + DestTy, Result.getFloat()); +} +if (DestTy->isIntegerType()) { + Result = APValue( + HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt())); + return true; +} + } else if (SourceTy->isRealFloatingType()) { +if (DestTy->isRealFloatingType()) { + Result = Original; + return HandleFloatToFloatCast(Info, E, SourceTy, DestTy, +Result.getFloat()); +} +if (DestTy->isIntegerType()) { + Result = APValue(APSInt()); + return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(), + DestTy, Result.getInt()); +} + } + return false; +} + +bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) { + APValue Source; + QualType SourceVecType = E->getSrcExpr()->getType(); + if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType)) +return false; + + QualType DestTy = E->getType()->castAs()->getElementType(); + QualType SourceTy = SourceVecType->castAs()->getElementType(); + + const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts()); + + auto SourceLen = Source.getVectorLength(); + SmallVector ResultElements; + ResultElements.reserve(SourceLen); + for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) { +APValue Elt; +if (!handleVectorConversion(Info, FPO, E, SourceTy, DestTy, +Source.getVectorElt(EltNum), Elt)) + return false; +ResultElements.push_back(std::move(Elt)); + } + + return Success(APValue(ResultElements.data(), ResultElements.size()), E); +} + +static bool handleVectorShuffle(EvalInfo , const ShuffleVectorExpr *E, +QualType ElemType, APValue const , +APValue const , unsigned EltNum, +APValue ) { + unsigned const TotalElementsInAVector = VecVal1.getVectorLength(); + + Expr const *IndexExpr = E->getExpr(2 + EltNum); + APSInt IndexVal; + if (!EvaluateInteger(IndexExpr, IndexVal, Info)) +return false; + + uint32_t index = IndexVal.getZExtValue(); + // The spec says that -1 should be treated as undef for optimizations, + // but in constexpr we need to choose a value. We'll choose 0. + if (index >= TotalElementsInAVector * 2) +index = 0; Destroyerrrocket wrote: Great, let's hope operator[] makes it. The error comes from somewhere in the depths of ExprConst, it intentionally tells you that undefined values are indeed illegal in constexpr code. I agree with you, a shame it makes sense! https://github.com/llvm/llvm-project/pull/76615 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)
Pol Marcet =?utf-8?q?Sardà?= , Pol Marcet =?utf-8?q?Sardà?= , Pol Marcet =?utf-8?q?Sardà?= Message-ID: In-Reply-To: @@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { return Success(APValue(ResultElements.data(), ResultElements.size()), E); } +static bool EvaluateVectorOrLValue(APValue , EvalInfo , + const Expr *E, const QualType ) { + if (!Evaluate(Result, Info, E)) +return false; + + if (Result.isLValue()) { +// Source of the data is an lvalue; Manually handle the lvalue as if +// it was an rvalue to get the current APValue. +LValue LValueFound; +LValueFound.setFrom(Info.Ctx, Result); +if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result)) + return false; + } + + return Result.isVector(); +} + +static bool handleVectorConversion(EvalInfo , const FPOptions FPO, + const Expr *E, QualType SourceTy, + QualType DestTy, APValue const , + APValue ) { + if (SourceTy->isIntegerType()) { +if (DestTy->isRealFloatingType()) { + Result = APValue(APFloat(0.0)); + return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(), + DestTy, Result.getFloat()); +} +if (DestTy->isIntegerType()) { + Result = APValue( + HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt())); + return true; +} + } else if (SourceTy->isRealFloatingType()) { +if (DestTy->isRealFloatingType()) { + Result = Original; + return HandleFloatToFloatCast(Info, E, SourceTy, DestTy, +Result.getFloat()); +} +if (DestTy->isIntegerType()) { + Result = APValue(APSInt()); + return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(), + DestTy, Result.getInt()); +} + } + return false; +} + +bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) { + APValue Source; + QualType SourceVecType = E->getSrcExpr()->getType(); + if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType)) +return false; + + QualType DestTy = E->getType()->castAs()->getElementType(); + QualType SourceTy = SourceVecType->castAs()->getElementType(); + + const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts()); + + auto SourceLen = Source.getVectorLength(); + SmallVector ResultElements; + ResultElements.reserve(SourceLen); + for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) { +APValue Elt; +if (!handleVectorConversion(Info, FPO, E, SourceTy, DestTy, +Source.getVectorElt(EltNum), Elt)) + return false; +ResultElements.push_back(std::move(Elt)); + } + + return Success(APValue(ResultElements.data(), ResultElements.size()), E); +} + +static bool handleVectorShuffle(EvalInfo , const ShuffleVectorExpr *E, +QualType ElemType, APValue const , +APValue const , unsigned EltNum, +APValue ) { + unsigned const TotalElementsInAVector = VecVal1.getVectorLength(); Destroyerrrocket wrote: I see! It seems like Gcc has extra characteristics then. given that at some point it could happen that such a thing needs to be supported, let's actually rewrite the code to support both sizes. Beware, I won't be able to test it, as Sema will prevent it from reaching constexpr. https://github.com/llvm/llvm-project/pull/76615 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)
Pol Marcet =?utf-8?q?Sardà?= , Pol Marcet =?utf-8?q?Sardà?= , Pol Marcet =?utf-8?q?Sardà?= Message-ID: In-Reply-To: @@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { return Success(APValue(ResultElements.data(), ResultElements.size()), E); } +static bool EvaluateVectorOrLValue(APValue , EvalInfo , + const Expr *E, const QualType ) { + if (!Evaluate(Result, Info, E)) +return false; + + if (Result.isLValue()) { +// Source of the data is an lvalue; Manually handle the lvalue as if +// it was an rvalue to get the current APValue. +LValue LValueFound; +LValueFound.setFrom(Info.Ctx, Result); +if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result)) + return false; + } + + return Result.isVector(); +} + +static bool handleVectorConversion(EvalInfo , const FPOptions FPO, + const Expr *E, QualType SourceTy, + QualType DestTy, APValue const , + APValue ) { + if (SourceTy->isIntegerType()) { +if (DestTy->isRealFloatingType()) { + Result = APValue(APFloat(0.0)); + return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(), + DestTy, Result.getFloat()); +} +if (DestTy->isIntegerType()) { + Result = APValue( + HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt())); + return true; +} + } else if (SourceTy->isRealFloatingType()) { +if (DestTy->isRealFloatingType()) { + Result = Original; + return HandleFloatToFloatCast(Info, E, SourceTy, DestTy, +Result.getFloat()); +} +if (DestTy->isIntegerType()) { + Result = APValue(APSInt()); + return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(), + DestTy, Result.getInt()); +} + } + return false; +} + +bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) { + APValue Source; + QualType SourceVecType = E->getSrcExpr()->getType(); + if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType)) +return false; + + QualType DestTy = E->getType()->castAs()->getElementType(); + QualType SourceTy = SourceVecType->castAs()->getElementType(); + + const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts()); + + auto SourceLen = Source.getVectorLength(); + SmallVector ResultElements; Destroyerrrocket wrote: 304 bytes is definitely inside what I'd be slightly worried to allocate without thinking into the stack, but having looked at it I think it's going to be fine. We're not the only case of smallVectors with APValues, and I'm sure that if it ever becomes a problem the default stack size can be modified (or the code can be refactored, I'm sure that if that ever happens it's not going to be "just" the fault of a smallvector of APValues). I thank you for pointing it out, as I simply did not check! https://github.com/llvm/llvm-project/pull/76615 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Fix the lambda call expression inside of a type alias declaration (PR #82310)
zyn0217 wrote: Friendly ping @cor3ntin and @erichkeane if you're back in the offices. https://github.com/llvm/llvm-project/pull/82310 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [PowerPC] Implement 32-bit expansion for rldimi (PR #86783)
https://github.com/ecnelises updated https://github.com/llvm/llvm-project/pull/86783 >From b886dcf2da25417d9f8cd75ff4aa58686e35139d Mon Sep 17 00:00:00 2001 From: Qiu Chaofan Date: Wed, 27 Mar 2024 17:11:04 +0800 Subject: [PATCH] [PowerPC] Implement 32-bit expansion for rldimi rldimi is 64-bit instruction, due to backward compatibility, it needs to be expanded into series of rlwimi in 32-bit environment. In the future, we may improve bit permutation selector and remove such direct codegen. --- clang/lib/Sema/SemaChecking.cpp | 1 - llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 109 -- llvm/test/CodeGen/PowerPC/rldimi.ll | 366 3 files changed, 454 insertions(+), 22 deletions(-) diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 11401b6f56c0ea..d2cbe5417d682d 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -5236,7 +5236,6 @@ static bool isPPC_64Builtin(unsigned BuiltinID) { case PPC::BI__builtin_ppc_fetch_and_andlp: case PPC::BI__builtin_ppc_fetch_and_orlp: case PPC::BI__builtin_ppc_fetch_and_swaplp: - case PPC::BI__builtin_ppc_rldimi: return true; } return false; diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 7436b202fba0d9..3281a0dfd08729 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -643,6 +643,7 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine , // We want to custom lower some of our intrinsics. setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::f64, Custom); + setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::i64, Custom); setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::ppcf128, Custom); setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::v4f32, Custom); setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::v2f64, Custom); @@ -10757,6 +10758,88 @@ static bool getVectorCompareInfo(SDValue Intrin, int , return true; } +static SDValue getRotateInsert32(SelectionDAG , SDLoc Loc, SDValue Dst, + SDValue Src, unsigned SH, unsigned MB, + unsigned ME) { + assert(SH < 32 && MB < 32 && ME < 32 && + "Invalid argument for rotate insert!"); + return SDValue( + DAG.getMachineNode(PPC::RLWIMI, Loc, MVT::i32, + {Dst, Src, DAG.getTargetConstant(SH, Loc, MVT::i32), + DAG.getTargetConstant(MB, Loc, MVT::i32), + DAG.getTargetConstant(ME, Loc, MVT::i32)}), + 0); +} + +static SDValue getRotateInsert64(SelectionDAG , SDLoc Loc, SDValue Dst, + SDValue Src, unsigned SH, unsigned MB, + unsigned ME, bool IsPPC64) { + assert(SH < 64 && MB < 64 && ME < 64 && + "Invalid argument for rotate insert!"); + if (IsPPC64) { +// rldimi requires ME=63-SH, otherwise rotation is needed before rldimi. +if (ME < 63 - SH) { + Src = DAG.getNode(ISD::ROTL, Loc, MVT::i64, Src, +DAG.getConstant(ME + SH + 1, Loc, MVT::i32)); +} else if (ME > 63 - SH) { + Src = DAG.getNode(ISD::ROTL, Loc, MVT::i64, Src, +DAG.getConstant(ME + SH - 63, Loc, MVT::i32)); +} +return SDValue(DAG.getMachineNode( + PPC::RLDIMI, Loc, MVT::i64, + {Dst, Src, DAG.getTargetConstant(63 - ME, Loc, MVT::i32), +DAG.getTargetConstant(MB, Loc, MVT::i32)}), + 0); + } + + // To implement rldimi(Dst, Src) on 32-bit target, four parts are needed. SH + // is adjusted to simplify cases. Invalid ranges will be skipped. + // - SrcHi inserted into DstHi with [0, 32-SH) + // - SrcLo inserted into DstHi with [32-SH, 32) + // - SrcHi inserted into DstLo with [32, 64-SH) + // - SrcLo inserted into DstLo with [64-SH, 64) + auto [SrcLo, SrcHi] = DAG.SplitScalar(Src, Loc, MVT::i32, MVT::i32); + auto [DstLo, DstHi] = DAG.SplitScalar(Dst, Loc, MVT::i32, MVT::i32); + if (SH >= 32) { +SH -= 32; +std::swap(SrcLo, SrcHi); + } + auto GetSubInsert = [, , SH](unsigned Left, unsigned Right, + SDValue Src, SDValue Dst, unsigned MB, + unsigned ME) { +if (Left > Right) + return Dst; + +if (MB <= ME) { + if (MB <= Right && ME >= Left) +return getRotateInsert32(DAG, Loc, Dst, Src, SH, + std::max(MB, Left) % 32, + std::min(ME, Right) % 32); +} else { + if (MB < Left || ME > Right) +return getRotateInsert32(DAG, Loc, Dst, Src, SH, Left % 32, Right % 32); + + if (MB <= Right && ME < Left) +return getRotateInsert32(DAG, Loc, Dst, Src, SH, MB % 32, Right %
[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)
ChuanqiXu9 wrote: I think the support for modules in clangd is pretty important. I posted https://discourse.llvm.org/t/rfc-directions-for-modules-support-in-clangd/78072 and let's see if we can make some progress. https://github.com/llvm/llvm-project/pull/66462 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] ef0291e - [NFC] [Serialization] Reordering lexcical and visible TU block after type decl offsets
Author: Chuanqi Xu Date: 2024-04-01T16:16:03+08:00 New Revision: ef0291e5f4451abbafab0c839bf51a6382f735f3 URL: https://github.com/llvm/llvm-project/commit/ef0291e5f4451abbafab0c839bf51a6382f735f3 DIFF: https://github.com/llvm/llvm-project/commit/ef0291e5f4451abbafab0c839bf51a6382f735f3.diff LOG: [NFC] [Serialization] Reordering lexcical and visible TU block after type decl offsets This patch reorder the lexical block for the translation unit, visible update block for the TU and the viisble upaete block for the extern C context after the type decl offsets block. This should be a NFC patch. This is helpful for later optimizations for eliding unreachable declarations in the global module fragment. See the comments in https://github.com/llvm/llvm-project/pull/76930. Simply, if we want to get the reachable sets of declaratins during the writing process, we need to write the file-level context later than the process of writing declarations (which is the main process to determine the reachable set). Added: Modified: clang/lib/Serialization/ASTWriter.cpp clang/test/Modules/language-linkage.cppm Removed: diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 1e5734c9c834eb..2438fbc166062f 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -4959,38 +4959,12 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema , StringRef isysroot, Stream.EmitRecord(METADATA_OLD_FORMAT, Record); } - // Create a lexical update block containing all of the declarations in the - // translation unit that do not come from other AST files. const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); - SmallVector NewGlobalKindDeclPairs; - for (const auto *D : TU->noload_decls()) { -if (!D->isFromASTFile()) { - NewGlobalKindDeclPairs.push_back(D->getKind()); - NewGlobalKindDeclPairs.push_back(GetDeclRef(D)); -} - } - - auto Abv = std::make_shared(); - Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL)); - Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); - unsigned TuUpdateLexicalAbbrev = Stream.EmitAbbrev(std::move(Abv)); - { -RecordData::value_type Record[] = {TU_UPDATE_LEXICAL}; -Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record, - bytes(NewGlobalKindDeclPairs)); - } - // And a visible updates block for the translation unit. - Abv = std::make_shared(); - Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE)); - Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6)); - Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); - UpdateVisibleAbbrev = Stream.EmitAbbrev(std::move(Abv)); - WriteDeclContextVisibleUpdate(TU); - - // If we have any extern "C" names, write out a visible update for them. - if (Context.ExternCContext) -WriteDeclContextVisibleUpdate(Context.ExternCContext); + // Force all top level declarations to be emitted. + for (const auto *D : TU->noload_decls()) +if (!D->isFromASTFile()) + GetDeclRef(D); // If the translation unit has an anonymous namespace, and we don't already // have an update block for it, write it as an update block. @@ -5131,6 +5105,14 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema , StringRef isysroot, for (auto *D : SemaRef.DeclsToCheckForDeferredDiags) DeclsToCheckForDeferredDiags.push_back(GetDeclRef(D)); + { +auto Abv = std::make_shared(); +Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE)); +Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6)); +Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); +UpdateVisibleAbbrev = Stream.EmitAbbrev(std::move(Abv)); + } + RecordData DeclUpdatesOffsetsRecord; // Keep writing types, declarations, and declaration update records @@ -5158,6 +5140,35 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema , StringRef isysroot, WriteTypeDeclOffsets(); if (!DeclUpdatesOffsetsRecord.empty()) Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord); + + // Create a lexical update block containing all of the declarations in the + // translation unit that do not come from other AST files. + { +SmallVector NewGlobalKindDeclPairs; +for (const auto *D : TU->noload_decls()) { + if (!D->isFromASTFile()) { +NewGlobalKindDeclPairs.push_back(D->getKind()); +NewGlobalKindDeclPairs.push_back(GetDeclRef(D)); + } +} + +auto Abv = std::make_shared(); +Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL)); +Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); +unsigned TuUpdateLexicalAbbrev = Stream.EmitAbbrev(std::move(Abv)); + +RecordData::value_type Record[] = {TU_UPDATE_LEXICAL}; +Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record, + bytes(NewGlobalKindDeclPairs)); +
[clang-tools-extra] [clang-tidy] add new check readability-enum-initial-value (PR #86129)
https://github.com/HerrCai0907 closed https://github.com/llvm/llvm-project/pull/86129 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] 3365d62 - [clang-tidy] add new check readability-enum-initial-value (#86129)
Author: Congcong Cai Date: 2024-04-01T15:53:57+08:00 New Revision: 3365d62179011aad6da3e4cbcb31044eec3462a2 URL: https://github.com/llvm/llvm-project/commit/3365d62179011aad6da3e4cbcb31044eec3462a2 DIFF: https://github.com/llvm/llvm-project/commit/3365d62179011aad6da3e4cbcb31044eec3462a2.diff LOG: [clang-tidy] add new check readability-enum-initial-value (#86129) Fixes: #85243. Added: clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.h clang-tools-extra/docs/clang-tidy/checks/readability/enum-initial-value.rst clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.c clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.cpp Modified: clang-tools-extra/clang-tidy/readability/CMakeLists.txt clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp clang-tools-extra/docs/ReleaseNotes.rst clang-tools-extra/docs/clang-tidy/checks/list.rst Removed: diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt index 5728c9970fb65d..dd772d69202548 100644 --- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt @@ -17,6 +17,7 @@ add_clang_library(clangTidyReadabilityModule DeleteNullPointerCheck.cpp DuplicateIncludeCheck.cpp ElseAfterReturnCheck.cpp + EnumInitialValueCheck.cpp FunctionCognitiveComplexityCheck.cpp FunctionSizeCheck.cpp IdentifierLengthCheck.cpp diff --git a/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp b/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp new file mode 100644 index 00..8f2841c32259a2 --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp @@ -0,0 +1,200 @@ +//===--- EnumInitialValueCheck.cpp - clang-tidy ---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "EnumInitialValueCheck.h" +#include "../utils/LexerUtils.h" +#include "clang/AST/Decl.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::readability { + +static bool isNoneEnumeratorsInitialized(const EnumDecl ) { + return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) { +return ECD->getInitExpr() == nullptr; + }); +} + +static bool isOnlyFirstEnumeratorInitialized(const EnumDecl ) { + bool IsFirst = true; + for (const EnumConstantDecl *ECD : Node.enumerators()) { +if ((IsFirst && ECD->getInitExpr() == nullptr) || +(!IsFirst && ECD->getInitExpr() != nullptr)) + return false; +IsFirst = false; + } + return !IsFirst; +} + +static bool areAllEnumeratorsInitialized(const EnumDecl ) { + return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) { +return ECD->getInitExpr() != nullptr; + }); +} + +/// Check if \p Enumerator is initialized with a (potentially negated) \c +/// IntegerLiteral. +static bool isInitializedByLiteral(const EnumConstantDecl *Enumerator) { + const Expr *const Init = Enumerator->getInitExpr(); + if (!Init) +return false; + return Init->isIntegerConstantExpr(Enumerator->getASTContext()); +} + +static void cleanInitialValue(DiagnosticBuilder , + const EnumConstantDecl *ECD, + const SourceManager , + const LangOptions ) { + const SourceRange InitExprRange = ECD->getInitExpr()->getSourceRange(); + if (InitExprRange.isInvalid() || InitExprRange.getBegin().isMacroID() || + InitExprRange.getEnd().isMacroID()) +return; + std::optional EqualToken = utils::lexer::findNextTokenSkippingComments( + ECD->getLocation(), SM, LangOpts); + if (!EqualToken.has_value() || + EqualToken.value().getKind() != tok::TokenKind::equal) +return; + const SourceLocation EqualLoc{EqualToken->getLocation()}; + if (EqualLoc.isInvalid() || EqualLoc.isMacroID()) +return; + Diag << FixItHint::CreateRemoval(EqualLoc) + << FixItHint::CreateRemoval(InitExprRange); + return; +} + +namespace { + +AST_MATCHER(EnumDecl, isMacro) { + SourceLocation Loc = Node.getBeginLoc(); + return Loc.isMacroID(); +} + +AST_MATCHER(EnumDecl, hasConsistentInitialValues) { + return isNoneEnumeratorsInitialized(Node) || +
[clang] [llvm] [InstCombiner] Remove trivially dead `llvm.allow.{runtime,ubsan}.check()` (PR #84851)
https://github.com/vitalybuka closed https://github.com/llvm/llvm-project/pull/84851 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++20] [Modules] Introduce -fexperimental-modules-reduced-bmi (PR #85050)
ChuanqiXu9 wrote: I'd like to land this patch in next week if no objection comes in. https://github.com/llvm/llvm-project/pull/85050 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++20] [Modules] Introduce -fexperimental-modules-reduced-bmi (PR #85050)
ChuanqiXu9 wrote: > > Got it. I've renamed the flag as `-fexperimental-modules-reduced-bmi`. > > Thanks. > > > I feel the suggestion like let users to use `-Xclang` options look odd.. > > I think the point here is that we want **expert** users to try this out (with > understanding that it might not behave exactly as they expect). Because it is > experimental, it is not yet ready for "end users" - I would expect expert > users to be able to deal with -Xclang x (but I will not insist, it's just > a suggestion) Agreed. https://github.com/llvm/llvm-project/pull/85050 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clangd] Support go-to-definition on type hints. The core part (PR #86629)
https://github.com/zyn0217 updated https://github.com/llvm/llvm-project/pull/86629 >From b8a69cbd9e0ee0aa35b38b7e3a78048cbe61447e Mon Sep 17 00:00:00 2001 From: Younan Zhang Date: Sat, 16 Mar 2024 23:30:10 +0800 Subject: [PATCH 1/9] [clangd] Support go-to-definition on type hints. The core part --- clang-tools-extra/clangd/AST.cpp | 9 + clang-tools-extra/clangd/AST.h| 2 + clang-tools-extra/clangd/InlayHints.cpp | 251 +- .../clangd/index/IndexAction.cpp | 9 +- .../clangd/unittests/InlayHintTests.cpp | 22 ++ 5 files changed, 279 insertions(+), 14 deletions(-) diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp index 1b86ea19cf28da..ef87f1bcb8443c 100644 --- a/clang-tools-extra/clangd/AST.cpp +++ b/clang-tools-extra/clangd/AST.cpp @@ -1019,5 +1019,14 @@ bool isExpandedFromParameterPack(const ParmVarDecl *D) { return getUnderlyingPackType(D) != nullptr; } +std::optional toURI(OptionalFileEntryRef File) { + if (!File) +return std::nullopt; + auto AbsolutePath = File->getFileEntry().tryGetRealPathName(); + if (AbsolutePath.empty()) +return std::nullopt; + return URI::create(AbsolutePath); +} + } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/AST.h b/clang-tools-extra/clangd/AST.h index fb0722d697cd06..3ae624b1ab7415 100644 --- a/clang-tools-extra/clangd/AST.h +++ b/clang-tools-extra/clangd/AST.h @@ -250,6 +250,8 @@ resolveForwardingParameters(const FunctionDecl *D, unsigned MaxDepth = 10); /// reference to one (e.g. `Args&...` or `Args&&...`). bool isExpandedFromParameterPack(const ParmVarDecl *D); +std::optional toURI(OptionalFileEntryRef File); + } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/InlayHints.cpp b/clang-tools-extra/clangd/InlayHints.cpp index cd4f1931b3ce1d..f9e0a51ddcc9f0 100644 --- a/clang-tools-extra/clangd/InlayHints.cpp +++ b/clang-tools-extra/clangd/InlayHints.cpp @@ -21,6 +21,7 @@ #include "clang/AST/Stmt.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/Type.h" +#include "clang/AST/TypeVisitor.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/SourceManager.h" @@ -372,6 +373,197 @@ maybeDropCxxExplicitObjectParameters(ArrayRef Params) { return Params; } +std::optional toLocation(SourceManager , SourceRange Range) { + if (Range.isInvalid()) +return std::nullopt; + if (auto URI = + toURI(SM.getFileEntryRefForID(SM.getFileID(Range.getBegin() { +Location L; +L.range.start = sourceLocToPosition(SM, Range.getBegin()); +L.range.end = sourceLocToPosition(SM, Range.getEnd()); +if (auto File = URIForFile::fromURI(*URI, "")) + L.uri = File.get(); +return L; + } + return std::nullopt; +} + +class TypeInlayHintLabelPartBuilder +: public TypeVisitor { + QualType Current; + ASTContext + const PrintingPolicy + std::vector + + bool ShouldAddLinksToTagTypes = false; + + struct CurrentTypeRAII { +TypeInlayHintLabelPartBuilder +QualType PreviousType; +bool PreviousShouldAddLinksToTagTypes; +CurrentTypeRAII(TypeInlayHintLabelPartBuilder , QualType New, +bool ShouldAddLinksToTagTypes) +: Builder(Builder), PreviousType(Builder.Current) { + Builder.Current = New; + Builder.ShouldAddLinksToTagTypes = ShouldAddLinksToTagTypes; +} +~CurrentTypeRAII() { + Builder.Current = PreviousType; + Builder.ShouldAddLinksToTagTypes = PreviousShouldAddLinksToTagTypes; +} + }; + + void addLabel(llvm::function_ref NamePrinter, +llvm::function_ref SourceRangeGetter) { +auto = LabelChunks.emplace_back(); +llvm::raw_string_ostream OS(Name.value); +NamePrinter(OS); +Name.location = toLocation(Context.getSourceManager(), SourceRangeGetter()); + } + + void printTemplateArgumentList(llvm::ArrayRef Args) { +unsigned Size = Args.size(); +for (unsigned I = 0; I < Size; ++I) { + auto = Args[I]; + if (PP.SuppressDefaultTemplateArgs && TA.getIsDefaulted()) +continue; + if (I) +LabelChunks.emplace_back(", "); + printTemplateArgument(TA); +} + } + + void printTemplateArgument(const TemplateArgument ) { +if (TA.getKind() == TemplateArgument::Pack) + return printTemplateArgumentList(TA.pack_elements()); +if (TA.getKind() == TemplateArgument::Type) { + CurrentTypeRAII Guard(*this, TA.getAsType(), +/*ShouldAddLinksToTagTypes=*/true); + return Visit(TA.getAsType().getTypePtr()); +} +llvm::raw_string_ostream OS(LabelChunks.emplace_back().value); +TA.print(PP, OS, /*IncludeType=*/true); + } + + void + processTemplateSpecialization(TemplateName TN, +llvm::ArrayRef Args, +SourceRange TemplateNameRange = SourceRange()) { +
[clang-tools-extra] [clangd] Support go-to-definition on type hints. The core part (PR #86629)
https://github.com/zyn0217 updated https://github.com/llvm/llvm-project/pull/86629 >From b8a69cbd9e0ee0aa35b38b7e3a78048cbe61447e Mon Sep 17 00:00:00 2001 From: Younan Zhang Date: Sat, 16 Mar 2024 23:30:10 +0800 Subject: [PATCH 1/8] [clangd] Support go-to-definition on type hints. The core part --- clang-tools-extra/clangd/AST.cpp | 9 + clang-tools-extra/clangd/AST.h| 2 + clang-tools-extra/clangd/InlayHints.cpp | 251 +- .../clangd/index/IndexAction.cpp | 9 +- .../clangd/unittests/InlayHintTests.cpp | 22 ++ 5 files changed, 279 insertions(+), 14 deletions(-) diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp index 1b86ea19cf28da..ef87f1bcb8443c 100644 --- a/clang-tools-extra/clangd/AST.cpp +++ b/clang-tools-extra/clangd/AST.cpp @@ -1019,5 +1019,14 @@ bool isExpandedFromParameterPack(const ParmVarDecl *D) { return getUnderlyingPackType(D) != nullptr; } +std::optional toURI(OptionalFileEntryRef File) { + if (!File) +return std::nullopt; + auto AbsolutePath = File->getFileEntry().tryGetRealPathName(); + if (AbsolutePath.empty()) +return std::nullopt; + return URI::create(AbsolutePath); +} + } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/AST.h b/clang-tools-extra/clangd/AST.h index fb0722d697cd06..3ae624b1ab7415 100644 --- a/clang-tools-extra/clangd/AST.h +++ b/clang-tools-extra/clangd/AST.h @@ -250,6 +250,8 @@ resolveForwardingParameters(const FunctionDecl *D, unsigned MaxDepth = 10); /// reference to one (e.g. `Args&...` or `Args&&...`). bool isExpandedFromParameterPack(const ParmVarDecl *D); +std::optional toURI(OptionalFileEntryRef File); + } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/InlayHints.cpp b/clang-tools-extra/clangd/InlayHints.cpp index cd4f1931b3ce1d..f9e0a51ddcc9f0 100644 --- a/clang-tools-extra/clangd/InlayHints.cpp +++ b/clang-tools-extra/clangd/InlayHints.cpp @@ -21,6 +21,7 @@ #include "clang/AST/Stmt.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/Type.h" +#include "clang/AST/TypeVisitor.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/SourceManager.h" @@ -372,6 +373,197 @@ maybeDropCxxExplicitObjectParameters(ArrayRef Params) { return Params; } +std::optional toLocation(SourceManager , SourceRange Range) { + if (Range.isInvalid()) +return std::nullopt; + if (auto URI = + toURI(SM.getFileEntryRefForID(SM.getFileID(Range.getBegin() { +Location L; +L.range.start = sourceLocToPosition(SM, Range.getBegin()); +L.range.end = sourceLocToPosition(SM, Range.getEnd()); +if (auto File = URIForFile::fromURI(*URI, "")) + L.uri = File.get(); +return L; + } + return std::nullopt; +} + +class TypeInlayHintLabelPartBuilder +: public TypeVisitor { + QualType Current; + ASTContext + const PrintingPolicy + std::vector + + bool ShouldAddLinksToTagTypes = false; + + struct CurrentTypeRAII { +TypeInlayHintLabelPartBuilder +QualType PreviousType; +bool PreviousShouldAddLinksToTagTypes; +CurrentTypeRAII(TypeInlayHintLabelPartBuilder , QualType New, +bool ShouldAddLinksToTagTypes) +: Builder(Builder), PreviousType(Builder.Current) { + Builder.Current = New; + Builder.ShouldAddLinksToTagTypes = ShouldAddLinksToTagTypes; +} +~CurrentTypeRAII() { + Builder.Current = PreviousType; + Builder.ShouldAddLinksToTagTypes = PreviousShouldAddLinksToTagTypes; +} + }; + + void addLabel(llvm::function_ref NamePrinter, +llvm::function_ref SourceRangeGetter) { +auto = LabelChunks.emplace_back(); +llvm::raw_string_ostream OS(Name.value); +NamePrinter(OS); +Name.location = toLocation(Context.getSourceManager(), SourceRangeGetter()); + } + + void printTemplateArgumentList(llvm::ArrayRef Args) { +unsigned Size = Args.size(); +for (unsigned I = 0; I < Size; ++I) { + auto = Args[I]; + if (PP.SuppressDefaultTemplateArgs && TA.getIsDefaulted()) +continue; + if (I) +LabelChunks.emplace_back(", "); + printTemplateArgument(TA); +} + } + + void printTemplateArgument(const TemplateArgument ) { +if (TA.getKind() == TemplateArgument::Pack) + return printTemplateArgumentList(TA.pack_elements()); +if (TA.getKind() == TemplateArgument::Type) { + CurrentTypeRAII Guard(*this, TA.getAsType(), +/*ShouldAddLinksToTagTypes=*/true); + return Visit(TA.getAsType().getTypePtr()); +} +llvm::raw_string_ostream OS(LabelChunks.emplace_back().value); +TA.print(PP, OS, /*IncludeType=*/true); + } + + void + processTemplateSpecialization(TemplateName TN, +llvm::ArrayRef Args, +SourceRange TemplateNameRange = SourceRange()) { +