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

Richard Smith via cfe-dev cfe-dev at lists.llvm.org
Mon Oct 12 13:41:36 PDT 2015


On Mon, Oct 12, 2015 at 3:06 AM, Andrzej Kotulski via cfe-dev <
cfe-dev at lists.llvm.org> wrote:

> 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?
>

Yes, expressions never have reference type.


> If so, is there another more reliable source of type information that
> keeps reference types separate?
>

It sounds like you want to know whether the expression is a glvalue or a
prvalue; use Expr::isGLValue for that. You will probably also want to look
at Expr::getObjectKind, which identifies the kinds of lvalues that don't
have pointer-like semantics (for instance, an lvalue referring to a
bit-field).

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 &'
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20151012/16e41eaf/attachment.html>


More information about the cfe-dev mailing list