[cfe-dev] differentiate type T& from type T when exporting AST expressions

Andrzej Kotulski via cfe-dev cfe-dev at lists.llvm.org
Mon Oct 12 03:06:23 PDT 2015


I’m trying to extract type information from clang::Expr by using getType() function. I found that while it almost always gives correct type, but it has unexpected behavior when using reference types – it doesn’t keep information about reference in a type.
Is this expected behavior? If so, is there another more reliable source of type information that keeps reference types separate?

It makes it hard to know whether given object should be treated as a pointer type or not. Some examples where this is causing us troubles:
1. Should we treat this object as a pointer or not? Treatment of type `T&` is closer to `T*` than to `T` in our use case
2. Casts – is it casting variable from Type1 to Type2 OR from Type1& to Type2&?
3. Virtual function calls - should it use dynamic dispatch, or not?

For example, consider following code:


int by_value(int x) {
  x = x + 1;
  return x;
}

int ref_param(int& x) {
  x = x + 1;
  return x;
}

int& ref_param_ret(int& x) {
  x = x + 1;
  return x;
}


I attach AST dump below. When you dump AST of code above, it is very similar for all functions, expressions basically lose information about something being reference type. The only place to see the difference is:

  1.  ‘x’ is reference type -> looking at the type of variable in DeclRefExpr (but not DeclRefExpr::getType() which doesn’t have reference type information)
  2.  Function returns reference type -> looking at function type signature.

How I read ast-dump output:
    DeclRefExpr 0x103072a98 <col:7> 'int' lvalue ParmVar 0x1030728f0 'x' 'int &’

Line above means, that:

  1.  This is DeclRefExpr expression
  2.  This expression has type int (DeclRefExpr::getType() == int). <- Why isn’t it int& ??
  3.  It’s dereferencing parameter variable `x`
  4.  Variable has type int&

-ast-dump output:

TranslationUnitDecl 0x103030cc0 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0x103031200 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128'
|-TypedefDecl 0x103031260 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128'
|-TypedefDecl 0x103031660 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list '__va_list_tag [1]'
|-FunctionDecl 0x103031780 <smallest2.cpp:1:1, line:4:1> line:1:5 by_value 'int (int)'
| |-ParmVarDecl 0x1030316c0 <col:14, col:18> col:18 used x 'int'
| `-CompoundStmt 0x103031968 <col:21, line:4:1>
|   |-BinaryOperator 0x1030318e0 <line:2:3, col:11> 'int' lvalue '='
|   | |-DeclRefExpr 0x103031830 <col:3> 'int' lvalue ParmVar 0x1030316c0 'x' 'int'
|   | `-BinaryOperator 0x1030318b8 <col:7, col:11> 'int' '+'
|   |   |-ImplicitCastExpr 0x1030318a0 <col:7> 'int' <LValueToRValue>
|   |   | `-DeclRefExpr 0x103031858 <col:7> 'int' lvalue ParmVar 0x1030316c0 'x' 'int'
|   |   `-IntegerLiteral 0x103031880 <col:11> 'int' 1
|   `-ReturnStmt 0x103031948 <line:3:3, col:10>
|     `-ImplicitCastExpr 0x103031930 <col:10> 'int' <LValueToRValue>
|       `-DeclRefExpr 0x103031908 <col:10> 'int' lvalue ParmVar 0x1030316c0 'x' 'int'
|-FunctionDecl 0x1030726c0 <line:6:1, line:9:1> line:6:5 ref_param 'int (int &)'
| |-ParmVarDecl 0x103072600 <col:15, col:20> col:20 used x 'int &'
| `-CompoundStmt 0x1030728a8 <col:23, line:9:1>
|   |-BinaryOperator 0x103072820 <line:7:3, col:11> 'int' lvalue '='
|   | |-DeclRefExpr 0x103072770 <col:3> 'int' lvalue ParmVar 0x103072600 'x' 'int &'
|   | `-BinaryOperator 0x1030727f8 <col:7, col:11> 'int' '+'
|   |   |-ImplicitCastExpr 0x1030727e0 <col:7> 'int' <LValueToRValue>
|   |   | `-DeclRefExpr 0x103072798 <col:7> 'int' lvalue ParmVar 0x103072600 'x' 'int &'
|   |   `-IntegerLiteral 0x1030727c0 <col:11> 'int' 1
|   `-ReturnStmt 0x103072888 <line:8:3, col:10>
|     `-ImplicitCastExpr 0x103072870 <col:10> 'int' <LValueToRValue>
|       `-DeclRefExpr 0x103072848 <col:10> 'int' lvalue ParmVar 0x103072600 'x' 'int &'
`-FunctionDecl 0x1030729c0 <line:11:1, line:14:1> line:11:6 ref_param_ret 'int &(int &)'
  |-ParmVarDecl 0x1030728f0 <col:20, col:25> col:25 used x 'int &'
  `-CompoundStmt 0x103072b90 <col:28, line:14:1>
    |-BinaryOperator 0x103072b20 <line:12:3, col:11> 'int' lvalue '='
    | |-DeclRefExpr 0x103072a70 <col:3> 'int' lvalue ParmVar 0x1030728f0 'x' 'int &'
    | `-BinaryOperator 0x103072af8 <col:7, col:11> 'int' '+'
    |   |-ImplicitCastExpr 0x103072ae0 <col:7> 'int' <LValueToRValue>
    |   | `-DeclRefExpr 0x103072a98 <col:7> 'int' lvalue ParmVar 0x1030728f0 'x' 'int &'
    |   `-IntegerLiteral 0x103072ac0 <col:11> 'int' 1
    `-ReturnStmt 0x103072b70 <line:13:3, col:10>
      `-DeclRefExpr 0x103072b48 <col:10> 'int' lvalue ParmVar 0x1030728f0 'x' 'int &'
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20151012/ba2a695a/attachment.html>


More information about the cfe-dev mailing list