[Lldb-commits] [PATCH] D108717: Fix Reference case for TypeSystemClang::GetChildCompilerTypeAtIndex(...) to avoid possible invalid cast

Raphael Isemann via Phabricator via lldb-commits lldb-commits at lists.llvm.org
Thu Aug 26 01:06:34 PDT 2021


teemperor added inline comments.


================
Comment at: lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp:6505
     if (idx_is_valid) {
-      const clang::ReferenceType *reference_type =
-          llvm::cast<clang::ReferenceType>(GetQualType(type).getTypePtr());
-      CompilerType pointee_clang_type =
-          GetType(reference_type->getPointeeType());
+      CompilerType pointee_clang_type;
+
----------------
shafik wrote:
> teemperor wrote:
> > I really like the idea of reusing the TypeSystemClang functions here (we should do this everywhere I think). FWIW, I think this can all just be `CompilerType pointee_clang_type = GetNonReferenceType(type);` From the code below `GetPointeeType` would also work. We already call the variable here `pointee` type so I don't think calling references pointers here will hurt too much, so I think both is fine.
> I tried `GetNonReferenceType(type).GetPointeeType()` but I get back an empty `CompilerType` it looks like it is doing almost exactly the same thing as the previous code:
> 
> `(*this)->getAs<ReferenceType>()`
I mean the whole thing could be just `GetNonReferenceType`. `GetNonReferenceType` gives you the underlying type, so the `GetPointeeType` after would just fail (-> empty return type) when it gets whatever the underlying type is:

```
CompilerType int_ref = ...;
int_ref.GetName() // -> "int &"
int_ref.GetNonReferenceType().GetName() // -> "int"
int_ref.GetPointeeType().GetName() // -> "int"

CompilerType int = ...;
int.GetName() // -> "int"
int_ref..GetPointeeType().GetName() // -> "" (Invalid CompilerType as int isn't a pointer/reference
```


================
Comment at: lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp:6508
+      if (parent_type_class == clang::Type::LValueReference)
+        pointee_clang_type = GetLValueReferenceType(type).GetPointeeType();
+      else
----------------
shafik wrote:
> teemperor wrote:
> > I think the logic here is reversed? `type` is a reference type (potentially behind a typedef). `GetLValueReferenceType` on `type` returns the reference type *to* that type. Not the underlying reference. The fallback for this is just that it returns the current type IIRC if you already have a reference, that's why this works. So, `GetLValueReferenceType` is just a no-op and `GetPointeeType` is doing the actual dereferencing. I think just the `GetPointeeType` is needed.
> Maybe I am confused but I thought given:
> 
> ```
> TypedefType 0x7fb11c841460 'std::__compressed_pair_elem<struct std::basic_string<char, struct std::char_traits<char>, class std::allocator<char> >::__rep, 0, false>::const_reference' sugar
> |-Typedef 0x7fb11c8413f0 'const_reference'
> `-LValueReferenceType 0x7fb11c8413c0 'const struct std::basic_string<char, struct std::char_traits<char>, class std::allocator<char> >::__rep &'
>   `-QualType 0x7fb11cac3361 'const struct std::basic_string<char, struct std::char_traits<char>, class std::allocator<char> >::__rep' const
>     `-RecordType 0x7fb11cac3360 'struct std::basic_string<char, struct std::char_traits<char>, class std::allocator<char> >::__rep'
>       `-CXXRecord 0x7fb11cac32b8 '__rep'
> ```
> 
> that `llvm::cast<clang::ReferenceType>(GetQualType(type).getTypePtr())` was intended to obtain:
> 
> ```
> LValueReferenceType 0x7fb11c829630 'const struct std::basic_string<char, struct std::char_traits<char>, class std::allocator<char> >::__rep &'
> `-QualType 0x7fb11cac3361 'const struct std::basic_string<char, struct std::char_traits<char>, class std::allocator<char> >::__rep' const
>   `-RecordType 0x7fb11cac3360 'struct std::basic_string<char, struct std::char_traits<char>, class std::allocator<char> >::__rep'
>     `-CXXRecord 0x7fb11cac32b8 '__rep'
> ```
> 
> which is what `GetLValueReferenceType(type)` does.
> 
> 
That is the right intention of the original code, but `GetLValueReferenceType` is just the inverse of what should happen. It takes a non-reference type and returns the reference type for it (`int` -> `int &`). I added some dump calls to the code which might explain what's going on:

```
lang=c++
  case clang::Type::LValueReference:                                            
  case clang::Type::RValueReference:                                            
    if (idx_is_valid) {                                                         
      CompilerType pointee_clang_type;                                          
                                                                                
      if (parent_type_class == clang::Type::LValueReference) {                  
        llvm::errs() << "type:\n";                                              
        GetQualType(type).dump();                                               
        CompilerType tmp = GetLValueReferenceType(type);                        
        llvm::errs() << "tmp (after GetLValueReferenceType):\n";                                               
        tmp.dump();                                                             
        pointee_clang_type = tmp.GetPointeeType();                              
        llvm::errs() << "pointee\n";                                            
        pointee_clang_type.dump();  
```

```
lang=python
type:
LValueReferenceType 0x564ba82bde80 'TTT &'
`-TypedefType 0x564ba82bde30 'TTT' sugar
  |-Typedef 0x564ba82bddc0 'TTT'
  `-BuiltinType 0x564ba82bd5d0 'int'
tmp (after GetLValueReferenceType):
LValueReferenceType 0x564ba82bdeb0 'TTT &'
`-TypedefType 0x564ba82bde30 'TTT' sugar
  |-Typedef 0x564ba82bddc0 'TTT'
  `-BuiltinType 0x564ba82bd5d0 'int'
pointee
TypedefType 0x564ba82bde30 'TTT' sugar
|-Typedef 0x564ba82bddc0 'TTT'
`-BuiltinType 0x564ba82bd5d0 'int'
```

So you get a reference type, then LValueReferenceType does nothing[1] as it's already a reference, and `GetPointeeType` returns the underlying type.

[1] It seems the function actually desugars the type, but `GetPointeeType` can handle sugar so it effectively is a no-op.


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

https://reviews.llvm.org/D108717



More information about the lldb-commits mailing list