[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
Szelethus wrote: I decided to merge this. We are still miles ahead with these docs, and I don't wanna accidentally forget the PR. https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
https://github.com/Szelethus closed https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
=?utf-8?q?Krist=C3=B3f?= Umann , =?utf-8?q?Krist=C3=B3f?= Umann , =?utf-8?q?Krist=C3=B3f?= Umann , =?utf-8?q?Krist=C3=B3f?= Umann , =?utf-8?q?Krist=C3=B3f?= Umann Message-ID: In-Reply-To: https://github.com/steakhal approved this pull request. https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
https://github.com/Szelethus updated https://github.com/llvm/llvm-project/pull/97407 From 9fed2b7dc5395f487cb91c10eb076bb87e05e9b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20Umann?= Date: Tue, 2 Jul 2024 12:58:19 +0200 Subject: [PATCH 1/6] [analyzer][NFC] Add some docs for LazyCompoundValue Yes, I basically copy-pasted some posts from discord and Artem's book, but these make for a rather decent docs. --- .../StaticAnalyzer/Core/PathSensitive/SVals.h | 39 +++ 1 file changed, 39 insertions(+) diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index 3a4b087257149..e44cda50ef21d 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -326,6 +326,12 @@ class LocAsInteger : public NonLoc { static bool classof(SVal V) { return V.getKind() == LocAsIntegerKind; } }; +/// The simplest example of a concrete compound value is nonloc::CompoundVal, +/// which represents a concrete r-value of an initializer-list or a string. +/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the +/// literal. +/// +/// Source: https://github.com/haoNoQ/clang-analyzer-guide, v0.1, section 5.3.2. class CompoundVal : public NonLoc { friend class ento::SValBuilder; @@ -346,6 +352,39 @@ class CompoundVal : public NonLoc { static bool classof(SVal V) { return V.getKind() == CompoundValKind; } }; +/// The simplest example of a concrete compound value is nonloc::CompoundVal, +/// which represents a concrete r-value of an initializer-list or a string. +/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the +/// literal. +/// +/// However, there is another compound value used in the analyzer, which appears +/// much more often during analysis, which is nonloc::LazyCompoundVal. This +/// value is an r-value that represents a snapshot of any structure "as a whole" +/// at a given moment during the analysis. Such value is already quite far from +/// being re- ferred to as "concrete", as many fields inside it would be unknown +/// or symbolic. nonloc::LazyCompoundVal operates by storing two things: +/// * a reference to the TypedValueRegion being snapshotted (yes, it is always +/// typed), and also +/// * a copy of the whole Store object, obtained from the ProgramState in +/// which it was created. +/// +/// Essentially, nonloc::LazyCompoundVal is a performance optimization for the +/// analyzer. Because Store is immutable, creating a nonloc::LazyCompoundVal is +/// a very cheap operation. Note that the Store contains all region bindings in +/// the program state, not only related to the region. Later, if necessary, such +/// value can be unpacked -- eg. when it is assigned to another variable. +/// +/// Source: https://github.com/haoNoQ/clang-analyzer-guide, v0.1, section 5.3.2. +/// +/// If you ever need to see if a LazyCompoundVal is fully or partially +/// (un)initialized, you can iterBindings(). This is non-typechecked lookup +/// (i.e., you cannot figure out which specific sub-region is initialized by the +/// value you look at, you only get a byte offset). You can also improve +/// iterBindings() to make it possible to restrict the iteration to a single +/// cluster, because within the LazyCompoundVal’s Store only the cluster that +/// corresponds to the LazyCompoundVal’s parent region is relevant. +/// +/// Source: https://discourse.llvm.org/t/analyzer-for-the-undefined-value-of-array-element-the-tracking-information-is-incomplete/49372/2 class LazyCompoundVal : public NonLoc { friend class ento::SValBuilder; From 1980cea32848f889d63cc61444d63a00506b52f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20Umann?= Date: Tue, 16 Jul 2024 14:39:12 +0200 Subject: [PATCH 2/6] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Artem Dergachev Co-authored-by: Donát Nagy Co-authored-by: Balazs Benics --- .../StaticAnalyzer/Core/PathSensitive/SVals.h | 44 +++ 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index e44cda50ef21d..0ddc272de2891 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -352,21 +352,21 @@ class CompoundVal : public NonLoc { static bool classof(SVal V) { return V.getKind() == CompoundValKind; } }; -/// The simplest example of a concrete compound value is nonloc::CompoundVal, -/// which represents a concrete r-value of an initializer-list or a string. -/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the -/// literal. -/// -/// However, there is
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
@@ -363,6 +397,18 @@ class LazyCompoundVal : public NonLoc { /// It might return null. const void *getStore() const; + /// This function itself is immaterial. It is only an implementation detail. + /// LazyCompoundVal represents only the rvalue, the data (known or unknown) + /// that *was* stored in that region *at some point in the past*. The region + /// should not be used for any purpose other than figuring out what part of + /// the frozen Store you're interested in. The value does not represent the + /// *current* value of that region. Sometimes it may, but this should not be + /// relied upon. Instead, if you want to figure out what region it represents, + /// you typically need to see where you got it from in the first place. The + /// region is absolutely not analogous to the C++ "this" pointer. It is also + /// not a valid way to "materialize" the prvalue into a glvalue in C++, + /// because the region represents the *old* storage (sometimes very old), not + /// the *future* storage. Szelethus wrote: @haoNoQ I can't really counter this, can you help us out a bit? :) https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
=?utf-8?q?Kristóf?= Umann , =?utf-8?q?Kristóf?= Umann , =?utf-8?q?Kristóf?= Umann , =?utf-8?q?Kristóf?= Umann Message-ID: In-Reply-To: @@ -346,6 +350,36 @@ class CompoundVal : public NonLoc { static bool classof(SVal V) { return V.getKind() == CompoundValKind; } }; +/// While nonloc::CompoundVal covers a few simple use cases, +/// nonloc::LazyCompoundVal is a more performant and flexible way to represent +/// an rvalue of record type, so it shows up much more frequently during +/// analysis. This value is an r-value that represents a snapshot of any +/// structure "as a whole" at a given moment during the analysis. Such value is +/// already quite far from being referred to as "concrete", as many fields +/// inside it would be unknown or symbolic. nonloc::LazyCompoundVal operates by +/// storing two things: +/// * a reference to the TypedValueRegion being snapshotted (yes, it is always +/// typed), and also +/// * a reference to the whole Store object, obtained from the ProgramState in +///which the nonloc::LazyCompoundVal was created. steakhal wrote: These bulletpoints are indented by different levels. https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
=?utf-8?q?Kristóf?= Umann , =?utf-8?q?Kristóf?= Umann , =?utf-8?q?Kristóf?= Umann , =?utf-8?q?Kristóf?= Umann Message-ID: In-Reply-To: @@ -346,6 +350,36 @@ class CompoundVal : public NonLoc { static bool classof(SVal V) { return V.getKind() == CompoundValKind; } }; +/// While nonloc::CompoundVal covers a few simple use cases, +/// nonloc::LazyCompoundVal is a more performant and flexible way to represent +/// an rvalue of record type, so it shows up much more frequently during +/// analysis. This value is an r-value that represents a snapshot of any +/// structure "as a whole" at a given moment during the analysis. Such value is +/// already quite far from being referred to as "concrete", as many fields +/// inside it would be unknown or symbolic. nonloc::LazyCompoundVal operates by +/// storing two things: +/// * a reference to the TypedValueRegion being snapshotted (yes, it is always +/// typed), and also +/// * a reference to the whole Store object, obtained from the ProgramState in +///which the nonloc::LazyCompoundVal was created. +/// +/// Note that the old ProgramState and its Store is kept alive during the +/// analysis because these are immutable functional data structures and each new +/// Store value is represented as "earlier Store" + "additional binding". +/// +/// Essentially, nonloc::LazyCompoundVal is a performance optimization for the +/// analyzer. Because Store is immutable, creating a nonloc::LazyCompoundVal is +/// a very cheap operation. Note that the Store contains all region bindings in +/// the program state, not only related to the region. Later, if necessary, such +/// value can be unpacked -- eg. when it is assigned to another variable. +/// +/// If you ever need inspect the contents of the LazyCompoundVal, you can use steakhal wrote: ```suggestion /// If you ever need to inspect the contents of the LazyCompoundVal, you can use ``` https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
=?utf-8?q?Kristóf?= Umann , =?utf-8?q?Kristóf?= Umann , =?utf-8?q?Kristóf?= Umann , =?utf-8?q?Kristóf?= Umann Message-ID: In-Reply-To: https://github.com/steakhal edited https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
=?utf-8?q?Kristóf?= Umann , =?utf-8?q?Kristóf?= Umann , =?utf-8?q?Kristóf?= Umann , =?utf-8?q?Kristóf?= Umann Message-ID: In-Reply-To: @@ -363,6 +397,18 @@ class LazyCompoundVal : public NonLoc { /// It might return null. const void *getStore() const; + /// This function itself is immaterial. It is only an implementation detail. + /// LazyCompoundVal represents only the rvalue, the data (known or unknown) + /// that *was* stored in that region *at some point in the past*. The region + /// should not be used for any purpose other than figuring out what part of + /// the frozen Store you're interested in. The value does not represent the + /// *current* value of that region. Sometimes it may, but this should not be + /// relied upon. Instead, if you want to figure out what region it represents, + /// you typically need to see where you got it from in the first place. The + /// region is absolutely not analogous to the C++ "this" pointer. It is also + /// not a valid way to "materialize" the prvalue into a glvalue in C++, + /// because the region represents the *old* storage (sometimes very old), not + /// the *future* storage. steakhal wrote: To be fair, I don't really understand this. To me, this region is the region that one would need to query from the associated `Store` to get the value this `LazyCompoundValue` actually boils down to. So, a region, like every other region, only defines a memory location (an l-value), and there is not much one could do with such a region. But I find this true for any other `MemRegion` anywhere in the engine. Probably I miss something, as I don't usually deal with LCVs, and it's been a while I last touched them. So, to summarize, I don't really understand what `immaterial` means in this context or understand why we mention it for `LCV::getRegion()` instead of mention this for a `MemRegion`. https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
=?utf-8?q?Kristóf?= Umann , =?utf-8?q?Kristóf?= Umann , =?utf-8?q?Kristóf?= Umann , =?utf-8?q?Kristóf?= Umann Message-ID: In-Reply-To: https://github.com/steakhal approved this pull request. I think it's already in a good shape. I found barely any problems with the wording. https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
Szelethus wrote: I'd also love to see some docs for `Loc` and `NonLoc`, because I recall some angry looks from years ago when I touched those on their own, but I can barely recall them :( As well as some docs for the various `ProgramState::getSVal` methods... https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
https://github.com/Szelethus updated https://github.com/llvm/llvm-project/pull/97407 From 9fed2b7dc5395f487cb91c10eb076bb87e05e9b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20Umann?= Date: Tue, 2 Jul 2024 12:58:19 +0200 Subject: [PATCH 1/5] [analyzer][NFC] Add some docs for LazyCompoundValue Yes, I basically copy-pasted some posts from discord and Artem's book, but these make for a rather decent docs. --- .../StaticAnalyzer/Core/PathSensitive/SVals.h | 39 +++ 1 file changed, 39 insertions(+) diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index 3a4b087257149..e44cda50ef21d 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -326,6 +326,12 @@ class LocAsInteger : public NonLoc { static bool classof(SVal V) { return V.getKind() == LocAsIntegerKind; } }; +/// The simplest example of a concrete compound value is nonloc::CompoundVal, +/// which represents a concrete r-value of an initializer-list or a string. +/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the +/// literal. +/// +/// Source: https://github.com/haoNoQ/clang-analyzer-guide, v0.1, section 5.3.2. class CompoundVal : public NonLoc { friend class ento::SValBuilder; @@ -346,6 +352,39 @@ class CompoundVal : public NonLoc { static bool classof(SVal V) { return V.getKind() == CompoundValKind; } }; +/// The simplest example of a concrete compound value is nonloc::CompoundVal, +/// which represents a concrete r-value of an initializer-list or a string. +/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the +/// literal. +/// +/// However, there is another compound value used in the analyzer, which appears +/// much more often during analysis, which is nonloc::LazyCompoundVal. This +/// value is an r-value that represents a snapshot of any structure "as a whole" +/// at a given moment during the analysis. Such value is already quite far from +/// being re- ferred to as "concrete", as many fields inside it would be unknown +/// or symbolic. nonloc::LazyCompoundVal operates by storing two things: +/// * a reference to the TypedValueRegion being snapshotted (yes, it is always +/// typed), and also +/// * a copy of the whole Store object, obtained from the ProgramState in +/// which it was created. +/// +/// Essentially, nonloc::LazyCompoundVal is a performance optimization for the +/// analyzer. Because Store is immutable, creating a nonloc::LazyCompoundVal is +/// a very cheap operation. Note that the Store contains all region bindings in +/// the program state, not only related to the region. Later, if necessary, such +/// value can be unpacked -- eg. when it is assigned to another variable. +/// +/// Source: https://github.com/haoNoQ/clang-analyzer-guide, v0.1, section 5.3.2. +/// +/// If you ever need to see if a LazyCompoundVal is fully or partially +/// (un)initialized, you can iterBindings(). This is non-typechecked lookup +/// (i.e., you cannot figure out which specific sub-region is initialized by the +/// value you look at, you only get a byte offset). You can also improve +/// iterBindings() to make it possible to restrict the iteration to a single +/// cluster, because within the LazyCompoundVal’s Store only the cluster that +/// corresponds to the LazyCompoundVal’s parent region is relevant. +/// +/// Source: https://discourse.llvm.org/t/analyzer-for-the-undefined-value-of-array-element-the-tracking-information-is-incomplete/49372/2 class LazyCompoundVal : public NonLoc { friend class ento::SValBuilder; From 1980cea32848f889d63cc61444d63a00506b52f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20Umann?= Date: Tue, 16 Jul 2024 14:39:12 +0200 Subject: [PATCH 2/5] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Artem Dergachev Co-authored-by: Donát Nagy Co-authored-by: Balazs Benics --- .../StaticAnalyzer/Core/PathSensitive/SVals.h | 44 +++ 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index e44cda50ef21d..0ddc272de2891 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -352,21 +352,21 @@ class CompoundVal : public NonLoc { static bool classof(SVal V) { return V.getKind() == CompoundValKind; } }; -/// The simplest example of a concrete compound value is nonloc::CompoundVal, -/// which represents a concrete r-value of an initializer-list or a string. -/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the -/// literal. -/// -/// However, there is
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
https://github.com/Szelethus updated https://github.com/llvm/llvm-project/pull/97407 From 9fed2b7dc5395f487cb91c10eb076bb87e05e9b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20Umann?= Date: Tue, 2 Jul 2024 12:58:19 +0200 Subject: [PATCH 1/4] [analyzer][NFC] Add some docs for LazyCompoundValue Yes, I basically copy-pasted some posts from discord and Artem's book, but these make for a rather decent docs. --- .../StaticAnalyzer/Core/PathSensitive/SVals.h | 39 +++ 1 file changed, 39 insertions(+) diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index 3a4b087257149..e44cda50ef21d 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -326,6 +326,12 @@ class LocAsInteger : public NonLoc { static bool classof(SVal V) { return V.getKind() == LocAsIntegerKind; } }; +/// The simplest example of a concrete compound value is nonloc::CompoundVal, +/// which represents a concrete r-value of an initializer-list or a string. +/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the +/// literal. +/// +/// Source: https://github.com/haoNoQ/clang-analyzer-guide, v0.1, section 5.3.2. class CompoundVal : public NonLoc { friend class ento::SValBuilder; @@ -346,6 +352,39 @@ class CompoundVal : public NonLoc { static bool classof(SVal V) { return V.getKind() == CompoundValKind; } }; +/// The simplest example of a concrete compound value is nonloc::CompoundVal, +/// which represents a concrete r-value of an initializer-list or a string. +/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the +/// literal. +/// +/// However, there is another compound value used in the analyzer, which appears +/// much more often during analysis, which is nonloc::LazyCompoundVal. This +/// value is an r-value that represents a snapshot of any structure "as a whole" +/// at a given moment during the analysis. Such value is already quite far from +/// being re- ferred to as "concrete", as many fields inside it would be unknown +/// or symbolic. nonloc::LazyCompoundVal operates by storing two things: +/// * a reference to the TypedValueRegion being snapshotted (yes, it is always +/// typed), and also +/// * a copy of the whole Store object, obtained from the ProgramState in +/// which it was created. +/// +/// Essentially, nonloc::LazyCompoundVal is a performance optimization for the +/// analyzer. Because Store is immutable, creating a nonloc::LazyCompoundVal is +/// a very cheap operation. Note that the Store contains all region bindings in +/// the program state, not only related to the region. Later, if necessary, such +/// value can be unpacked -- eg. when it is assigned to another variable. +/// +/// Source: https://github.com/haoNoQ/clang-analyzer-guide, v0.1, section 5.3.2. +/// +/// If you ever need to see if a LazyCompoundVal is fully or partially +/// (un)initialized, you can iterBindings(). This is non-typechecked lookup +/// (i.e., you cannot figure out which specific sub-region is initialized by the +/// value you look at, you only get a byte offset). You can also improve +/// iterBindings() to make it possible to restrict the iteration to a single +/// cluster, because within the LazyCompoundVal’s Store only the cluster that +/// corresponds to the LazyCompoundVal’s parent region is relevant. +/// +/// Source: https://discourse.llvm.org/t/analyzer-for-the-undefined-value-of-array-element-the-tracking-information-is-incomplete/49372/2 class LazyCompoundVal : public NonLoc { friend class ento::SValBuilder; From 1980cea32848f889d63cc61444d63a00506b52f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20Umann?= Date: Tue, 16 Jul 2024 14:39:12 +0200 Subject: [PATCH 2/4] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Artem Dergachev Co-authored-by: Donát Nagy Co-authored-by: Balazs Benics --- .../StaticAnalyzer/Core/PathSensitive/SVals.h | 44 +++ 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index e44cda50ef21d..0ddc272de2891 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -352,21 +352,21 @@ class CompoundVal : public NonLoc { static bool classof(SVal V) { return V.getKind() == CompoundValKind; } }; -/// The simplest example of a concrete compound value is nonloc::CompoundVal, -/// which represents a concrete r-value of an initializer-list or a string. -/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the -/// literal. -/// -/// However, there is
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
https://github.com/Szelethus updated https://github.com/llvm/llvm-project/pull/97407 From 9fed2b7dc5395f487cb91c10eb076bb87e05e9b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20Umann?= Date: Tue, 2 Jul 2024 12:58:19 +0200 Subject: [PATCH 1/3] [analyzer][NFC] Add some docs for LazyCompoundValue Yes, I basically copy-pasted some posts from discord and Artem's book, but these make for a rather decent docs. --- .../StaticAnalyzer/Core/PathSensitive/SVals.h | 39 +++ 1 file changed, 39 insertions(+) diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index 3a4b087257149..e44cda50ef21d 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -326,6 +326,12 @@ class LocAsInteger : public NonLoc { static bool classof(SVal V) { return V.getKind() == LocAsIntegerKind; } }; +/// The simplest example of a concrete compound value is nonloc::CompoundVal, +/// which represents a concrete r-value of an initializer-list or a string. +/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the +/// literal. +/// +/// Source: https://github.com/haoNoQ/clang-analyzer-guide, v0.1, section 5.3.2. class CompoundVal : public NonLoc { friend class ento::SValBuilder; @@ -346,6 +352,39 @@ class CompoundVal : public NonLoc { static bool classof(SVal V) { return V.getKind() == CompoundValKind; } }; +/// The simplest example of a concrete compound value is nonloc::CompoundVal, +/// which represents a concrete r-value of an initializer-list or a string. +/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the +/// literal. +/// +/// However, there is another compound value used in the analyzer, which appears +/// much more often during analysis, which is nonloc::LazyCompoundVal. This +/// value is an r-value that represents a snapshot of any structure "as a whole" +/// at a given moment during the analysis. Such value is already quite far from +/// being re- ferred to as "concrete", as many fields inside it would be unknown +/// or symbolic. nonloc::LazyCompoundVal operates by storing two things: +/// * a reference to the TypedValueRegion being snapshotted (yes, it is always +/// typed), and also +/// * a copy of the whole Store object, obtained from the ProgramState in +/// which it was created. +/// +/// Essentially, nonloc::LazyCompoundVal is a performance optimization for the +/// analyzer. Because Store is immutable, creating a nonloc::LazyCompoundVal is +/// a very cheap operation. Note that the Store contains all region bindings in +/// the program state, not only related to the region. Later, if necessary, such +/// value can be unpacked -- eg. when it is assigned to another variable. +/// +/// Source: https://github.com/haoNoQ/clang-analyzer-guide, v0.1, section 5.3.2. +/// +/// If you ever need to see if a LazyCompoundVal is fully or partially +/// (un)initialized, you can iterBindings(). This is non-typechecked lookup +/// (i.e., you cannot figure out which specific sub-region is initialized by the +/// value you look at, you only get a byte offset). You can also improve +/// iterBindings() to make it possible to restrict the iteration to a single +/// cluster, because within the LazyCompoundVal’s Store only the cluster that +/// corresponds to the LazyCompoundVal’s parent region is relevant. +/// +/// Source: https://discourse.llvm.org/t/analyzer-for-the-undefined-value-of-array-element-the-tracking-information-is-incomplete/49372/2 class LazyCompoundVal : public NonLoc { friend class ento::SValBuilder; From 1980cea32848f889d63cc61444d63a00506b52f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20Umann?= Date: Tue, 16 Jul 2024 14:39:12 +0200 Subject: [PATCH 2/3] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Artem Dergachev Co-authored-by: Donát Nagy Co-authored-by: Balazs Benics --- .../StaticAnalyzer/Core/PathSensitive/SVals.h | 44 +++ 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index e44cda50ef21d..0ddc272de2891 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -352,21 +352,21 @@ class CompoundVal : public NonLoc { static bool classof(SVal V) { return V.getKind() == CompoundValKind; } }; -/// The simplest example of a concrete compound value is nonloc::CompoundVal, -/// which represents a concrete r-value of an initializer-list or a string. -/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the -/// literal. -/// -/// However, there is
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
https://github.com/Szelethus updated https://github.com/llvm/llvm-project/pull/97407 From 9fed2b7dc5395f487cb91c10eb076bb87e05e9b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20Umann?= Date: Tue, 2 Jul 2024 12:58:19 +0200 Subject: [PATCH 1/2] [analyzer][NFC] Add some docs for LazyCompoundValue Yes, I basically copy-pasted some posts from discord and Artem's book, but these make for a rather decent docs. --- .../StaticAnalyzer/Core/PathSensitive/SVals.h | 39 +++ 1 file changed, 39 insertions(+) diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index 3a4b087257149..e44cda50ef21d 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -326,6 +326,12 @@ class LocAsInteger : public NonLoc { static bool classof(SVal V) { return V.getKind() == LocAsIntegerKind; } }; +/// The simplest example of a concrete compound value is nonloc::CompoundVal, +/// which represents a concrete r-value of an initializer-list or a string. +/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the +/// literal. +/// +/// Source: https://github.com/haoNoQ/clang-analyzer-guide, v0.1, section 5.3.2. class CompoundVal : public NonLoc { friend class ento::SValBuilder; @@ -346,6 +352,39 @@ class CompoundVal : public NonLoc { static bool classof(SVal V) { return V.getKind() == CompoundValKind; } }; +/// The simplest example of a concrete compound value is nonloc::CompoundVal, +/// which represents a concrete r-value of an initializer-list or a string. +/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the +/// literal. +/// +/// However, there is another compound value used in the analyzer, which appears +/// much more often during analysis, which is nonloc::LazyCompoundVal. This +/// value is an r-value that represents a snapshot of any structure "as a whole" +/// at a given moment during the analysis. Such value is already quite far from +/// being re- ferred to as "concrete", as many fields inside it would be unknown +/// or symbolic. nonloc::LazyCompoundVal operates by storing two things: +/// * a reference to the TypedValueRegion being snapshotted (yes, it is always +/// typed), and also +/// * a copy of the whole Store object, obtained from the ProgramState in +/// which it was created. +/// +/// Essentially, nonloc::LazyCompoundVal is a performance optimization for the +/// analyzer. Because Store is immutable, creating a nonloc::LazyCompoundVal is +/// a very cheap operation. Note that the Store contains all region bindings in +/// the program state, not only related to the region. Later, if necessary, such +/// value can be unpacked -- eg. when it is assigned to another variable. +/// +/// Source: https://github.com/haoNoQ/clang-analyzer-guide, v0.1, section 5.3.2. +/// +/// If you ever need to see if a LazyCompoundVal is fully or partially +/// (un)initialized, you can iterBindings(). This is non-typechecked lookup +/// (i.e., you cannot figure out which specific sub-region is initialized by the +/// value you look at, you only get a byte offset). You can also improve +/// iterBindings() to make it possible to restrict the iteration to a single +/// cluster, because within the LazyCompoundVal’s Store only the cluster that +/// corresponds to the LazyCompoundVal’s parent region is relevant. +/// +/// Source: https://discourse.llvm.org/t/analyzer-for-the-undefined-value-of-array-element-the-tracking-information-is-incomplete/49372/2 class LazyCompoundVal : public NonLoc { friend class ento::SValBuilder; From 1980cea32848f889d63cc61444d63a00506b52f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20Umann?= Date: Tue, 16 Jul 2024 14:39:12 +0200 Subject: [PATCH 2/2] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Artem Dergachev Co-authored-by: Donát Nagy Co-authored-by: Balazs Benics --- .../StaticAnalyzer/Core/PathSensitive/SVals.h | 44 +++ 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index e44cda50ef21d..0ddc272de2891 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -352,21 +352,21 @@ class CompoundVal : public NonLoc { static bool classof(SVal V) { return V.getKind() == CompoundValKind; } }; -/// The simplest example of a concrete compound value is nonloc::CompoundVal, -/// which represents a concrete r-value of an initializer-list or a string. -/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the -/// literal. -/// -/// However, there is
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
@@ -346,6 +352,39 @@ class CompoundVal : public NonLoc { static bool classof(SVal V) { return V.getKind() == CompoundValKind; } }; +/// The simplest example of a concrete compound value is nonloc::CompoundVal, +/// which represents a concrete r-value of an initializer-list or a string. +/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the +/// literal. +/// +/// However, there is another compound value used in the analyzer, which appears +/// much more often during analysis, which is nonloc::LazyCompoundVal. This +/// value is an r-value that represents a snapshot of any structure "as a whole" +/// at a given moment during the analysis. Such value is already quite far from +/// being re- ferred to as "concrete", as many fields inside it would be unknown +/// or symbolic. nonloc::LazyCompoundVal operates by storing two things: +/// * a reference to the TypedValueRegion being snapshotted (yes, it is always +/// typed), and also +/// * a copy of the whole Store object, obtained from the ProgramState in +/// which it was created. NagyDonat wrote: ```suggestion /// * a reference to the whole Store object, obtained from the ProgramState in ///which the nonloc::LazyCompoundVal was created. /// /// Note that the old ProgramState and its Store is kept alive during the /// analysis because these are immutable functional data structures and each new /// Store value is represented as "earlier Store" + "additional binding". ``` What would you think about this phrasing? https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
@@ -346,6 +352,39 @@ class CompoundVal : public NonLoc { static bool classof(SVal V) { return V.getKind() == CompoundValKind; } }; +/// The simplest example of a concrete compound value is nonloc::CompoundVal, +/// which represents a concrete r-value of an initializer-list or a string. +/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the +/// literal. +/// +/// However, there is another compound value used in the analyzer, which appears +/// much more often during analysis, which is nonloc::LazyCompoundVal. This +/// value is an r-value that represents a snapshot of any structure "as a whole" +/// at a given moment during the analysis. Such value is already quite far from +/// being re- ferred to as "concrete", as many fields inside it would be unknown +/// or symbolic. nonloc::LazyCompoundVal operates by storing two things: +/// * a reference to the TypedValueRegion being snapshotted (yes, it is always +/// typed), and also +/// * a copy of the whole Store object, obtained from the ProgramState in NagyDonat wrote: I do understand functional programming (I had a phase when I learnt Haskell and for a few years I thought that it's the absolutely perfect language :star_struck: -- since then I'm more realistic but I still like it), I was just confused by the fact that this line emphasizes "a copy of the whole Store object" as opposed to the "reference to" in the previous line. In a functional language the word "copy" is practically non-existent (we speak about values, not objects and their identity, so there is no reason to say that this is _a copy of_ e.g. that list -- we simply say that "this is that list"), while in C++ saying "copy" instead of "move" or "pointer/reference" is an important synonym of "we allocate lots of new memory", so I'd still prefer tweaking this line. https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
@@ -346,6 +352,39 @@ class CompoundVal : public NonLoc { static bool classof(SVal V) { return V.getKind() == CompoundValKind; } }; +/// The simplest example of a concrete compound value is nonloc::CompoundVal, +/// which represents a concrete r-value of an initializer-list or a string. +/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the +/// literal. +/// +/// However, there is another compound value used in the analyzer, which appears +/// much more often during analysis, which is nonloc::LazyCompoundVal. This haoNoQ wrote: ```suggestion /// While nonloc::CompoundVal covers a few simple use cases, the nonloc::LazyCompoundVal /// is a more performant and flexible way to represent an rvalue of record type, /// so it shows up much more frequently during analysis. This ``` https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
@@ -346,6 +352,39 @@ class CompoundVal : public NonLoc { static bool classof(SVal V) { return V.getKind() == CompoundValKind; } }; +/// The simplest example of a concrete compound value is nonloc::CompoundVal, +/// which represents a concrete r-value of an initializer-list or a string. +/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the +/// literal. +/// +/// However, there is another compound value used in the analyzer, which appears +/// much more often during analysis, which is nonloc::LazyCompoundVal. This +/// value is an r-value that represents a snapshot of any structure "as a whole" +/// at a given moment during the analysis. Such value is already quite far from +/// being re- ferred to as "concrete", as many fields inside it would be unknown +/// or symbolic. nonloc::LazyCompoundVal operates by storing two things: +/// * a reference to the TypedValueRegion being snapshotted (yes, it is always +/// typed), and also +/// * a copy of the whole Store object, obtained from the ProgramState in haoNoQ wrote: > Is it truly a copy of the store object? This seems to contradict the "is a > very cheap operation" line in the next paragraph...? Yes! Congratulations, now you understand functional programming. Because the Store is an ImmutableMap, it is uniquely identified by a single pointer to the unique, carefully deduplicated instance of that map. The cost of a copy is the cost of a single 64-bit assignment. It's literally cheaper to copy the entire thing than to copy a portion of it, because a portion would be a different object, which we haven't created yet. It's like copy on write, except, the write isn't supported in the first place. Of course the best part is that the "modification" is also cheap. Instead of modifying a map (and ruining everyone's "copy"), we just describe the modified map as essentially "the same as the other map except this one key has a different value". Which is also very quick to describe. Though, we still need to organize them into AVL trees for both fast lookup and fast deduplication. So it's not as straightforward as immutable lists which all naturally "grow on trees". But still, yes, all these operations are cheap, and this is how when you print the exploded graph it prints you every state, every store, behind every node. Because it doesn't cost anything extra to keep the copies around. https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
@@ -346,6 +352,39 @@ class CompoundVal : public NonLoc { static bool classof(SVal V) { return V.getKind() == CompoundValKind; } }; +/// The simplest example of a concrete compound value is nonloc::CompoundVal, +/// which represents a concrete r-value of an initializer-list or a string. +/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the +/// literal. +/// +/// However, there is another compound value used in the analyzer, which appears +/// much more often during analysis, which is nonloc::LazyCompoundVal. This +/// value is an r-value that represents a snapshot of any structure "as a whole" +/// at a given moment during the analysis. Such value is already quite far from +/// being re- ferred to as "concrete", as many fields inside it would be unknown +/// or symbolic. nonloc::LazyCompoundVal operates by storing two things: +/// * a reference to the TypedValueRegion being snapshotted (yes, it is always +/// typed), and also +/// * a copy of the whole Store object, obtained from the ProgramState in +/// which it was created. +/// +/// Essentially, nonloc::LazyCompoundVal is a performance optimization for the +/// analyzer. Because Store is immutable, creating a nonloc::LazyCompoundVal is +/// a very cheap operation. Note that the Store contains all region bindings in +/// the program state, not only related to the region. Later, if necessary, such +/// value can be unpacked -- eg. when it is assigned to another variable. +/// +/// Source: https://github.com/haoNoQ/clang-analyzer-guide, v0.1, section 5.3.2. +/// +/// If you ever need to see if a LazyCompoundVal is fully or partially +/// (un)initialized, you can iterBindings(). This is non-typechecked lookup +/// (i.e., you cannot figure out which specific sub-region is initialized by the +/// value you look at, you only get a byte offset). You can also improve +/// iterBindings() to make it possible to restrict the iteration to a single +/// cluster, because within the LazyCompoundVal’s Store only the cluster that +/// corresponds to the LazyCompoundVal’s parent region is relevant. haoNoQ wrote: ```suggestion /// If you ever need inspect the contents of the LazyCompoundVal, you can use /// StoreManager::iterBindings(). It'll iterate through all values in the Store, /// but you're only interested in the ones that belong to LazyCompoundVal::getRegion(); /// other bindings are immaterial. /// /// NOTE: LazyCompoundVal::getRegion() itself is also immaterial. It is only an /// implementation detail. LazyCompoundVal represents only the rvalue, the data (known or unknown) /// that *was* stored in that region *at some point in the past*. The region should not be used for /// any purpose other than figuring out what part of the frozen Store you're interested in. /// The value does not represent the *current* value of that region. Sometimes it may, but /// this should not be relied upon. Instead, if you want to figure out what region it represents, /// you typically need to see where you got it from in the first place. /// The region is absolutely not analogous to the C++ "this" pointer. /// It is also not a valid way to "materialize" the prvalue into a glvalue in C++, because the region /// represents the *old* storage (sometimes very old), not the *future* storage. ``` https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
@@ -326,6 +326,12 @@ class LocAsInteger : public NonLoc { static bool classof(SVal V) { return V.getKind() == LocAsIntegerKind; } }; +/// The simplest example of a concrete compound value is nonloc::CompoundVal, +/// which represents a concrete r-value of an initializer-list or a string. +/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the +/// literal. +/// +/// Source: https://github.com/haoNoQ/clang-analyzer-guide, v0.1, section 5.3.2. haoNoQ wrote: Yeah please nuke this thank you ^.^ Sometimes we cite the academic papers that describe the specific approaches we've implemented (IPA is a good example) but this one's definitely inside out. The source code should be the primary source of truth about the source code. https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
https://github.com/haoNoQ edited https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
https://github.com/haoNoQ commented: Thanks a lot!! Some comments are very much overdue here. https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
@@ -346,6 +352,39 @@ class CompoundVal : public NonLoc { static bool classof(SVal V) { return V.getKind() == CompoundValKind; } }; +/// The simplest example of a concrete compound value is nonloc::CompoundVal, +/// which represents a concrete r-value of an initializer-list or a string. +/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the +/// literal. +/// +/// However, there is another compound value used in the analyzer, which appears +/// much more often during analysis, which is nonloc::LazyCompoundVal. This +/// value is an r-value that represents a snapshot of any structure "as a whole" +/// at a given moment during the analysis. Such value is already quite far from +/// being re- ferred to as "concrete", as many fields inside it would be unknown +/// or symbolic. nonloc::LazyCompoundVal operates by storing two things: +/// * a reference to the TypedValueRegion being snapshotted (yes, it is always +/// typed), and also +/// * a copy of the whole Store object, obtained from the ProgramState in +/// which it was created. +/// +/// Essentially, nonloc::LazyCompoundVal is a performance optimization for the +/// analyzer. Because Store is immutable, creating a nonloc::LazyCompoundVal is +/// a very cheap operation. Note that the Store contains all region bindings in +/// the program state, not only related to the region. Later, if necessary, such +/// value can be unpacked -- eg. when it is assigned to another variable. +/// +/// Source: https://github.com/haoNoQ/clang-analyzer-guide, v0.1, section 5.3.2. steakhal wrote: ```suggestion ``` https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
@@ -326,6 +326,12 @@ class LocAsInteger : public NonLoc { static bool classof(SVal V) { return V.getKind() == LocAsIntegerKind; } }; +/// The simplest example of a concrete compound value is nonloc::CompoundVal, +/// which represents a concrete r-value of an initializer-list or a string. +/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the +/// literal. +/// +/// Source: https://github.com/haoNoQ/clang-analyzer-guide, v0.1, section 5.3.2. steakhal wrote: If we want to phase out the guide, I don't think it's valuable to mention it here. If you insist, let's mention this additional resource in the dev docs, but not directly here. https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
https://github.com/steakhal commented: Makes sense. It's good to see some love for the docs. https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
https://github.com/steakhal edited https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
@@ -346,6 +352,39 @@ class CompoundVal : public NonLoc { static bool classof(SVal V) { return V.getKind() == CompoundValKind; } }; +/// The simplest example of a concrete compound value is nonloc::CompoundVal, +/// which represents a concrete r-value of an initializer-list or a string. +/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the +/// literal. +/// +/// However, there is another compound value used in the analyzer, which appears +/// much more often during analysis, which is nonloc::LazyCompoundVal. This +/// value is an r-value that represents a snapshot of any structure "as a whole" +/// at a given moment during the analysis. Such value is already quite far from +/// being re- ferred to as "concrete", as many fields inside it would be unknown +/// or symbolic. nonloc::LazyCompoundVal operates by storing two things: +/// * a reference to the TypedValueRegion being snapshotted (yes, it is always +/// typed), and also +/// * a copy of the whole Store object, obtained from the ProgramState in NagyDonat wrote: Perhaps we should mention that `Store` is just a typedef for `const void *`... https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
@@ -346,6 +352,39 @@ class CompoundVal : public NonLoc { static bool classof(SVal V) { return V.getKind() == CompoundValKind; } }; +/// The simplest example of a concrete compound value is nonloc::CompoundVal, +/// which represents a concrete r-value of an initializer-list or a string. +/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the +/// literal. +/// +/// However, there is another compound value used in the analyzer, which appears +/// much more often during analysis, which is nonloc::LazyCompoundVal. This +/// value is an r-value that represents a snapshot of any structure "as a whole" +/// at a given moment during the analysis. Such value is already quite far from +/// being re- ferred to as "concrete", as many fields inside it would be unknown NagyDonat wrote: ```suggestion /// being referred to as "concrete", as many fields inside it would be unknown ``` https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
https://github.com/NagyDonat edited https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
@@ -346,6 +352,39 @@ class CompoundVal : public NonLoc { static bool classof(SVal V) { return V.getKind() == CompoundValKind; } }; +/// The simplest example of a concrete compound value is nonloc::CompoundVal, +/// which represents a concrete r-value of an initializer-list or a string. +/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the +/// literal. +/// +/// However, there is another compound value used in the analyzer, which appears +/// much more often during analysis, which is nonloc::LazyCompoundVal. This +/// value is an r-value that represents a snapshot of any structure "as a whole" +/// at a given moment during the analysis. Such value is already quite far from +/// being re- ferred to as "concrete", as many fields inside it would be unknown +/// or symbolic. nonloc::LazyCompoundVal operates by storing two things: +/// * a reference to the TypedValueRegion being snapshotted (yes, it is always +/// typed), and also +/// * a copy of the whole Store object, obtained from the ProgramState in NagyDonat wrote: Is it truly a _copy_ of the store object? This seems to contradict the "is a very cheap operation" line in the next paragraph...? Or is it a _copied store object_ that _shares the same bulk allocations_ with the original one (but differs in minor details?) https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
https://github.com/NagyDonat commented: I'm really happy that you decided to document these :smile: https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
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 d78211912391b724a064ef017dbf239eff10380a 9fed2b7dc5395f487cb91c10eb076bb87e05e9b6 -- clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h `` View the diff from clang-format here. ``diff diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index e44cda50ef..dbc34e0ae5 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -384,7 +384,8 @@ public: /// cluster, because within the LazyCompoundVal’s Store only the cluster that /// corresponds to the LazyCompoundVal’s parent region is relevant. /// -/// Source: https://discourse.llvm.org/t/analyzer-for-the-undefined-value-of-array-element-the-tracking-information-is-incomplete/49372/2 +/// Source: +/// https://discourse.llvm.org/t/analyzer-for-the-undefined-value-of-array-element-the-tracking-information-is-incomplete/49372/2 class LazyCompoundVal : public NonLoc { friend class ento::SValBuilder; `` https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
llvmbot wrote: @llvm/pr-subscribers-clang @llvm/pr-subscribers-clang-static-analyzer-1 Author: Kristóf Umann (Szelethus) Changes Yes, I basically copy-pasted some posts from discord and Artem's book, but these make for a rather decent docs. --- Full diff: https://github.com/llvm/llvm-project/pull/97407.diff 1 Files Affected: - (modified) clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h (+39) ``diff diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index 3a4b087257149..e44cda50ef21d 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -326,6 +326,12 @@ class LocAsInteger : public NonLoc { static bool classof(SVal V) { return V.getKind() == LocAsIntegerKind; } }; +/// The simplest example of a concrete compound value is nonloc::CompoundVal, +/// which represents a concrete r-value of an initializer-list or a string. +/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the +/// literal. +/// +/// Source: https://github.com/haoNoQ/clang-analyzer-guide, v0.1, section 5.3.2. class CompoundVal : public NonLoc { friend class ento::SValBuilder; @@ -346,6 +352,39 @@ class CompoundVal : public NonLoc { static bool classof(SVal V) { return V.getKind() == CompoundValKind; } }; +/// The simplest example of a concrete compound value is nonloc::CompoundVal, +/// which represents a concrete r-value of an initializer-list or a string. +/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the +/// literal. +/// +/// However, there is another compound value used in the analyzer, which appears +/// much more often during analysis, which is nonloc::LazyCompoundVal. This +/// value is an r-value that represents a snapshot of any structure "as a whole" +/// at a given moment during the analysis. Such value is already quite far from +/// being re- ferred to as "concrete", as many fields inside it would be unknown +/// or symbolic. nonloc::LazyCompoundVal operates by storing two things: +/// * a reference to the TypedValueRegion being snapshotted (yes, it is always +/// typed), and also +/// * a copy of the whole Store object, obtained from the ProgramState in +/// which it was created. +/// +/// Essentially, nonloc::LazyCompoundVal is a performance optimization for the +/// analyzer. Because Store is immutable, creating a nonloc::LazyCompoundVal is +/// a very cheap operation. Note that the Store contains all region bindings in +/// the program state, not only related to the region. Later, if necessary, such +/// value can be unpacked -- eg. when it is assigned to another variable. +/// +/// Source: https://github.com/haoNoQ/clang-analyzer-guide, v0.1, section 5.3.2. +/// +/// If you ever need to see if a LazyCompoundVal is fully or partially +/// (un)initialized, you can iterBindings(). This is non-typechecked lookup +/// (i.e., you cannot figure out which specific sub-region is initialized by the +/// value you look at, you only get a byte offset). You can also improve +/// iterBindings() to make it possible to restrict the iteration to a single +/// cluster, because within the LazyCompoundVal’s Store only the cluster that +/// corresponds to the LazyCompoundVal’s parent region is relevant. +/// +/// Source: https://discourse.llvm.org/t/analyzer-for-the-undefined-value-of-array-element-the-tracking-information-is-incomplete/49372/2 class LazyCompoundVal : public NonLoc { friend class ento::SValBuilder; `` https://github.com/llvm/llvm-project/pull/97407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Add some docs for LazyCompoundValue (PR #97407)
https://github.com/Szelethus created https://github.com/llvm/llvm-project/pull/97407 Yes, I basically copy-pasted some posts from discord and Artem's book, but these make for a rather decent docs. From 9fed2b7dc5395f487cb91c10eb076bb87e05e9b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20Umann?= Date: Tue, 2 Jul 2024 12:58:19 +0200 Subject: [PATCH] [analyzer][NFC] Add some docs for LazyCompoundValue Yes, I basically copy-pasted some posts from discord and Artem's book, but these make for a rather decent docs. --- .../StaticAnalyzer/Core/PathSensitive/SVals.h | 39 +++ 1 file changed, 39 insertions(+) diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index 3a4b087257149..e44cda50ef21d 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -326,6 +326,12 @@ class LocAsInteger : public NonLoc { static bool classof(SVal V) { return V.getKind() == LocAsIntegerKind; } }; +/// The simplest example of a concrete compound value is nonloc::CompoundVal, +/// which represents a concrete r-value of an initializer-list or a string. +/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the +/// literal. +/// +/// Source: https://github.com/haoNoQ/clang-analyzer-guide, v0.1, section 5.3.2. class CompoundVal : public NonLoc { friend class ento::SValBuilder; @@ -346,6 +352,39 @@ class CompoundVal : public NonLoc { static bool classof(SVal V) { return V.getKind() == CompoundValKind; } }; +/// The simplest example of a concrete compound value is nonloc::CompoundVal, +/// which represents a concrete r-value of an initializer-list or a string. +/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the +/// literal. +/// +/// However, there is another compound value used in the analyzer, which appears +/// much more often during analysis, which is nonloc::LazyCompoundVal. This +/// value is an r-value that represents a snapshot of any structure "as a whole" +/// at a given moment during the analysis. Such value is already quite far from +/// being re- ferred to as "concrete", as many fields inside it would be unknown +/// or symbolic. nonloc::LazyCompoundVal operates by storing two things: +/// * a reference to the TypedValueRegion being snapshotted (yes, it is always +/// typed), and also +/// * a copy of the whole Store object, obtained from the ProgramState in +/// which it was created. +/// +/// Essentially, nonloc::LazyCompoundVal is a performance optimization for the +/// analyzer. Because Store is immutable, creating a nonloc::LazyCompoundVal is +/// a very cheap operation. Note that the Store contains all region bindings in +/// the program state, not only related to the region. Later, if necessary, such +/// value can be unpacked -- eg. when it is assigned to another variable. +/// +/// Source: https://github.com/haoNoQ/clang-analyzer-guide, v0.1, section 5.3.2. +/// +/// If you ever need to see if a LazyCompoundVal is fully or partially +/// (un)initialized, you can iterBindings(). This is non-typechecked lookup +/// (i.e., you cannot figure out which specific sub-region is initialized by the +/// value you look at, you only get a byte offset). You can also improve +/// iterBindings() to make it possible to restrict the iteration to a single +/// cluster, because within the LazyCompoundVal’s Store only the cluster that +/// corresponds to the LazyCompoundVal’s parent region is relevant. +/// +/// Source: https://discourse.llvm.org/t/analyzer-for-the-undefined-value-of-array-element-the-tracking-information-is-incomplete/49372/2 class LazyCompoundVal : public NonLoc { friend class ento::SValBuilder; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits