[PATCH] D96976: [analyzer] Fix reinterpret_cast handling for pointer-to-member

Deep Majumder via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Feb 26 06:30:35 PST 2021


RedDocMD added a comment.

> So here you are implying that for reinterpret casts, the `CastE->path_begin()-end()` range is empty? And that is why you need to manually come up with a //possible// CXXBaseSpecifier list?

@steakhal, Yes. For illustration, the following code:

  struct Base {
    int field;
  };
  
  struct Derived : public Base {};
  struct DoubleDerived : public Derived {};
  
  int f() {
    int DoubleDerived::*ddf = &Derived::field;
    int Base::*bf1 = static_cast<int Base::*>(ddf);
    int Base::*bf2 = reinterpret_cast<int Base::*>(ddf);
  }

produces the following (truncated) AST dump

  -FunctionDecl 0x12f3890 <line:8:1, line:12:1> line:8:5 f 'int ()'
    `-CompoundStmt 0x12f3ec0 <col:9, line:12:1>
      |-DeclStmt 0x12f3b70 <line:9:3, col:44>
      | `-VarDecl 0x12f3a18 <col:3, col:39> col:23 used ddf 'int DoubleDerived::*' cinit
      |   `-ImplicitCastExpr 0x12f3b48 <col:29, col:39> 'int DoubleDerived::*' <BaseToDerivedMemberPointer (Derived -> Base)>
      |     `-UnaryOperator 0x12f3b30 <col:29, col:39> 'int Base::*' prefix '&' cannot overflow
      |       `-DeclRefExpr 0x12f3ad0 <col:30, col:39> 'int' lvalue Field 0x12f33d0 'field' 'int'
      |-DeclStmt 0x12f3d20 <line:10:3, col:49>
      | `-VarDecl 0x12f3bf0 <col:3, col:48> col:14 bf1 'int Base::*' cinit
      |   `-CXXStaticCastExpr 0x12f3ce0 <col:20, col:48> 'int Base::*' static_cast<int struct Base::*> <DerivedToBaseMemberPointer (Derived -> Base)>
      |     `-ImplicitCastExpr 0x12f3cc8 <col:45> 'int DoubleDerived::*' <LValueToRValue> part_of_explicit_cast
      |       `-DeclRefExpr 0x12f3c60 <col:45> 'int DoubleDerived::*' lvalue Var 0x12f3a18 'ddf' 'int DoubleDerived::*'
      `-DeclStmt 0x12f3ea8 <line:11:3, col:54>
        `-VarDecl 0x12f3d88 <col:3, col:53> col:14 bf2 'int Base::*' cinit
          `-CXXReinterpretCastExpr 0x12f3e78 <col:20, col:53> 'int Base::*' reinterpret_cast<int struct Base::*> <ReinterpretMemberPointer>
            `-ImplicitCastExpr 0x12f3e60 <col:50> 'int DoubleDerived::*' <LValueToRValue> part_of_explicit_cast
              `-DeclRefExpr 0x12f3df8 <col:50> 'int DoubleDerived::*' lvalue Var 0x12f3a18 'ddf' 'int DoubleDerived::*'

If you compare the three cases:

1. The first statement has an implicit cast inserted during parsing, and so we need not calculate the path manually
2. The second statement has a `static_cast` and it also supplies a path, except that we need to remove these bases instead of adding. (Ref to D95877 <https://reviews.llvm.org/D95877>).
3. The third statement has no path provided, because it is a `reinterpret_cast` and the parser cannot produce a path in all cases (if you cast to an integer for an instance) - so it doesn't produce any path

With the parser not providing us with info, we have to figure it out in a different way. 
Also, it is not one //possible// path but the //only// possible path. If there are multiple acceptable paths then it is illegal to define such a member-pointer and the frontend will reject it as such.

> I strongly encourage you to find a better alternative to this manual graph search.
> This information must be available somewhere.
>
> Have you looked at `CXXRecordDecl::isDerivedFrom()`? Or any other member functions of that class?

Unfortunately, all the methods on CXXRecordDecl, like the one you mentioned, are for querying and thus returns a `bool`, while I need the entire path.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D96976



More information about the cfe-commits mailing list