[PATCH] D125778: [llvm-dva] 03 - Logical elements

Carlos Alberto Enciso via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 29 01:25:11 PDT 2022


CarlosAlbertoEnciso added inline comments.


================
Comment at: llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h:188
+  }
+  LVObject &operator=(LVObject const &) = delete;
+  virtual ~LVObject() = default;
----------------
psamolysov wrote:
> We have a copy constructor but no copy assigned operator. Could you explain why? Thank you.
Good question. We do not allow any copy/assignment of logical elements.

The only place where we allow copy an LVObject is in `printAttributes` when we need to print some modified attributes for the current object. Those modifications are temporary and are used to create a fake scope.
```
void LVObject::printAttributes(raw_ostream &OS, bool Full, StringRef Name,
                               LVObject *Parent, StringRef Value,
                               bool UseQuotes, bool PrintRef) const {
  // The current object will be the enclosing scope, use its offset and level.
  LVObject Object(*Parent);
  Object.setLevel(Parent->getLevel() + 1);
  Object.setLineNumber(0);
  Object.printAttributes(OS, Full);
  ..
}
```



================
Comment at: llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h:109
+  StringRef getFilename() const { return InputFilename; }
+  void setFilename(std::string Name) { InputFilename = Name; }
+  StringRef getFileFormatName() const { return FileFormatName; }
----------------
psamolysov wrote:
> probinson wrote:
> > psamolysov wrote:
> > > 
> > Should Name be a reference parameter? Passing std::string by value could result in a creating/destroying a temp copy.
> Using `std::move` after getting a parameter by value has the following advantage: if the actual parameter (`Name` in our case) is a temporary or also moved value (`rvalue`?) so:
> 
> ```
> LVReader r;
> r.setFilename(getFilename(...));
> ```
> 
> or 
> 
> ```
> LVReader r;
> std::string name = getFilename(...);
> r.setFilename(std::move(name));
> ```
> 
> the move constructor of `std::string` will be called twice and the copy constructor will not be called at all. If we use pass-by-const-reference for the `Name` parameter in the `setFilename` method, the copy constructor will be called but only once. In the general case, move constructor is much cheaper and two calls of a move constructor could be more preferable than even a single call of a copy constructor but for `std::string` this is not obvious due to short string optimization. If filenames are usually short strings, shorter than 32 characters, using pass by reference for the `Name` looks better for me.
Thanks for both great explanations.

Looking at the whole code `setFilename` is only used in one the unit tests. Replaced with `std::move`.


================
Comment at: llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h:211
+  virtual LVScope *getCompileUnitParent() const override {
+    return LVElement::getCompileUnitParent();
+  }
----------------
psamolysov wrote:
> I'm not sure but is `using LVElement::getCompileUnitParent();` not enough?
Sorry, I'm afraid I don't follow you.


================
Comment at: llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp:214
+bool LVScope::removeElement(LVElement *Element) {
+  auto predicate = [&](LVElement *Item) -> bool { return Item == Element; };
+  auto removeElement = [&](auto &Container) -> bool {
----------------
psamolysov wrote:
> `Element` is just a pointer, it can be captured by value.
Capture `Element` by value.
```
  auto Predicate = [Element](LVElement *Item) -> bool { return Item == Element; };
```


================
Comment at: llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp:215
+  auto predicate = [&](LVElement *Item) -> bool { return Item == Element; };
+  auto removeElement = [&](auto &Container) -> bool {
+    auto Iter = std::remove_if(Container->begin(), Container->end(), predicate);
----------------
psamolysov wrote:
> Only captured variables are `Element` that is a pointer and `predicate` that is a lambda with a very short capture list. Both can be captured by value but by reference is ok too.
Capture both `Element` and `Predicate` by value.
```
auto RemoveElement = [Element, Predicate](auto &Container) -> bool {
```


================
Comment at: llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp:254-255
+  LVSymbols References;
+  References.insert(References.end(), ReferenceSymbols->begin(),
+                    ReferenceSymbols->end());
+
----------------
psamolysov wrote:
> 
Replaced with `append`.


================
Comment at: llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp:260
+        std::remove_if(Symbols.begin(), Symbols.end(),
+                       [&](LVSymbol *Item) -> bool { return Item == Symbol; });
+    if (Iter != Symbols.end())
----------------
psamolysov wrote:
> `Symbol` is just a pointer and can be captured by value.
Capture `Symbol` by value.
```
[Symbol](LVSymbol *Item) -> bool { return Item == Symbol; });
```


================
Comment at: llvm/unittests/DebugInfo/LogicalView/LogicalElementsTest.cpp:64
+  template <typename T> T *create() {
+    T *Element = new T();
+    EXPECT_NE(Element, nullptr);
----------------
psamolysov wrote:
> A `std::bad_alloc` will be thrown if the test is out of memory. It makes sense to wrap the line in the `try-catch` block or use the non-throwing overload of the new operator.
Changed to use the non-throwing overload.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D125778/new/

https://reviews.llvm.org/D125778



More information about the llvm-commits mailing list