ConditionalOperator: rvalue or lvalue?

Hi all,

In the code fragment [1] ConditionalOperator is lvalue in clang AST, while in code fragments [2] and [3] it is reported as rvalue. The difference is that [2] declares DEFAULT_WEIGHT as enum constant, and [3] declares it as int constant.

Is this behavior correct? Why in [1] ConditionalOperator is not rvalue too?

Code [1]

class A {
  unsigned m_fn1(unsigned x) const;
  static const unsigned DEFAULT_WEIGHT = 1;
};
unsigned A::m_fn1(unsigned x) const {
  unsigned ret = x ? x : DEFAULT_WEIGHT;
  return ret;
}

Code [2]

class A {
  unsigned m_fn1(unsigned x) const;
  enum { DEFAULT_WEIGHT = 1 };
};
unsigned A::m_fn1(unsigned x) const {
  unsigned ret = x ? x : DEFAULT_WEIGHT;
  return ret;
}

Code [3]

class A {
  unsigned m_fn1(unsigned x) const;
  static const signed DEFAULT_WEIGHT = 1;
};
unsigned A::m_fn1(unsigned x) const {
  unsigned ret = x ? x : DEFAULT_WEIGHT;
  return ret;
}

AST dump [1]

TranslationUnitDecl 0x3234cf0 <<invalid sloc>>

-TypedefDecl 0x3235230 <<invalid sloc>> __int128_t '__int128'
-TypedefDecl 0x3235290 <<invalid sloc>> __uint128_t 'unsigned __int128'
-TypedefDecl 0x3235650 <<invalid sloc>> __builtin_va_list '__va_list_tag [1]'
-CXXRecordDecl 0x32356a0 <BranchProbabilityInfo.cpp:1:1, line:4:1> class A
>-CXXRecordDecl 0x32357b0 <line:1:1, col:7> class A
>-CXXMethodDecl 0x3235910 <line:2:3, col:30> m_fn1 'unsigned int (unsigned int) const'
> `-ParmVarDecl 0x3235850 <col:18, col:27> x 'unsigned int'
`-VarDecl 0x32671d0 <line:3:3, col:42> DEFAULT_WEIGHT 'const unsigned int' static
  `-ImplicitCastExpr 0x3267248 <col:42> 'const unsigned int' <IntegralCast>
    `-IntegerLiteral 0x3267228 <col:42> 'int' 1

`-CXXMethodDecl 0x3267370 parent 0x32356a0 prev 0x3235910 <line:5:1, line:8:1> m_fn1 'unsigned int (unsigned int) const'
  >-ParmVarDecl 0x32672f0 <line:5:19, col:28> x 'unsigned int'
  `-CompoundStmt 0x3267648 <col:37, line:8:1>
    >-DeclStmt 0x32675d0 <line:6:3, col:40>
    > `-VarDecl 0x3267470 <col:3, col:26> ret 'unsigned int'
    > `-ImplicitCastExpr 0x32675b8 <col:18, col:26> 'unsigned int' <LValueToRValue>
    > `-ConditionalOperator 0x3267588 <col:18, col:26> 'const unsigned int' lvalue
    > >-ImplicitCastExpr 0x3267558 <col:18> '_Bool' <IntegralToBoolean>
    > > `-ImplicitCastExpr 0x3267540 <col:18> 'unsigned int' <LValueToRValue>
    > > `-DeclRefExpr 0x32674c8 <col:18> 'unsigned int' lvalue ParmVar 0x32672f0 'x' 'unsigned int'
    > >-ImplicitCastExpr 0x3267570 <col:22> 'const unsigned int' lvalue <NoOp>
    > > `-DeclRefExpr 0x32674f0 <col:22> 'unsigned int' lvalue ParmVar 0x32672f0 'x' 'unsigned int'
    > `-DeclRefExpr 0x3267518 <col:26> 'const unsigned int' lvalue Var 0x32671d0 'DEFAULT_WEIGHT' 'const unsigned int'
    `-ReturnStmt 0x3267628 <line:7:3, col:10>
      `-ImplicitCastExpr 0x3267610 <col:10> 'unsigned int' <LValueToRValue>
        `-DeclRefExpr 0x32675e8 <col:10> 'unsigned int' lvalue Var 0x3267470 'ret' 'unsigned int'

AST dump [2]

TranslationUnitDecl 0x1d74cf0 <<invalid sloc>>

-TypedefDecl 0x1d75230 <<invalid sloc>> __int128_t '__int128'
-TypedefDecl 0x1d75290 <<invalid sloc>> __uint128_t 'unsigned __int128'
-TypedefDecl 0x1d75650 <<invalid sloc>> __builtin_va_list '__va_list_tag [1]'
-CXXRecordDecl 0x1d756a0 <BranchProbabilityInfo4.cpp:1:1, line:4:1> class A
>-CXXRecordDecl 0x1d757b0 <line:1:1, col:7> class A
>-CXXMethodDecl 0x1d75910 <line:2:3, col:30> m_fn1 'unsigned int (unsigned int) const'
> `-ParmVarDecl 0x1d75850 <col:18, col:27> x 'unsigned int'
`-EnumDecl 0x1da71c0 <line:3:3, col:29>
  `-EnumConstantDecl 0x1da7290 <col:10, col:27> DEFAULT_WEIGHT 'enum A::<anonymous at BranchProbabilityInfo4.cpp:3:3>'
    `-ImplicitCastExpr 0x1da72e0 <col:27> 'unsigned int' <IntegralCast>
      `-IntegerLiteral 0x1da7270 <col:27> 'int' 1

`-CXXMethodDecl 0x1da73c0 parent 0x1d756a0 prev 0x1d75910 <line:5:1, line:8:1> m_fn1 'unsigned int (unsigned int) const'
  >-ParmVarDecl 0x1da7340 <line:5:19, col:28> x 'unsigned int'
  `-CompoundStmt 0x1da7698 <col:37, line:8:1>
    >-DeclStmt 0x1da7620 <line:6:3, col:40>
    > `-VarDecl 0x1da74c0 <col:3, col:26> ret 'unsigned int'
    > `-ConditionalOperator 0x1da75f0 <col:18, col:26> 'unsigned int'
    > >-ImplicitCastExpr 0x1da75a8 <col:18> '_Bool' <IntegralToBoolean>
    > > `-ImplicitCastExpr 0x1da7590 <col:18> 'unsigned int' <LValueToRValue>
    > > `-DeclRefExpr 0x1da7518 <col:18> 'unsigned int' lvalue ParmVar 0x1da7340 'x' 'unsigned int'
    > >-ImplicitCastExpr 0x1da75c0 <col:22> 'unsigned int' <LValueToRValue>
    > > `-DeclRefExpr 0x1da7540 <col:22> 'unsigned int' lvalue ParmVar 0x1da7340 'x' 'unsigned int'
    > `-ImplicitCastExpr 0x1da75d8 <col:26> 'unsigned int' <IntegralCast>
    > `-DeclRefExpr 0x1da7568 <col:26> 'enum A::<anonymous at BranchProbabilityInfo4.cpp:3:3>' EnumConstant 0x1da7290 'DEFAULT_WEIGHT' 'enum A::<anonymous at BranchProbabilityInfo4.cpp:3:3>'
    `-ReturnStmt 0x1da7678 <line:7:3, col:10>
      `-ImplicitCastExpr 0x1da7660 <col:10> 'unsigned int' <LValueToRValue>
        `-DeclRefExpr 0x1da7638 <col:10> 'unsigned int' lvalue Var 0x1da74c0 'ret' 'unsigned int'

AST dump [3]

TranslationUnitDecl 0x308acf0 <<invalid sloc>>

-TypedefDecl 0x308b230 <<invalid sloc>> __int128_t '__int128'
-TypedefDecl 0x308b290 <<invalid sloc>> __uint128_t 'unsigned __int128'
-TypedefDecl 0x308b650 <<invalid sloc>> __builtin_va_list '__va_list_tag [1]'
-CXXRecordDecl 0x308b6a0 <BranchProbabilityInfo5.cpp:1:1, line:4:1> class A
>-CXXRecordDecl 0x308b7b0 <line:1:1, col:7> class A
>-CXXMethodDecl 0x308b910 <line:2:3, col:30> m_fn1 'unsigned int (unsigned int) const'
> `-ParmVarDecl 0x308b850 <col:18, col:27> x 'unsigned int'
`-VarDecl 0x30bd1d0 <line:3:3, col:40> DEFAULT_WEIGHT 'const int' static
  `-IntegerLiteral 0x30bd228 <col:40> 'int' 1

`-CXXMethodDecl 0x30bd360 parent 0x308b6a0 prev 0x308b910 <line:5:1, line:8:1> m_fn1 'unsigned int (unsigned int) const'
  >-ParmVarDecl 0x30bd2e0 <line:5:19, col:28> x 'unsigned int'
  `-CompoundStmt 0x30bd650 <col:37, line:8:1>
    >-DeclStmt 0x30bd5d8 <line:6:3, col:40>
    > `-VarDecl 0x30bd460 <col:3, col:26> ret 'unsigned int'
    > `-ConditionalOperator 0x30bd5a8 <col:18, col:26> 'unsigned int'
    > >-ImplicitCastExpr 0x30bd548 <col:18> '_Bool' <IntegralToBoolean>
    > > `-ImplicitCastExpr 0x30bd530 <col:18> 'unsigned int' <LValueToRValue>
    > > `-DeclRefExpr 0x30bd4b8 <col:18> 'unsigned int' lvalue ParmVar 0x30bd2e0 'x' 'unsigned int'
    > >-ImplicitCastExpr 0x30bd560 <col:22> 'unsigned int' <LValueToRValue>
    > > `-DeclRefExpr 0x30bd4e0 <col:22> 'unsigned int' lvalue ParmVar 0x30bd2e0 'x' 'unsigned int'
    > `-ImplicitCastExpr 0x30bd590 <col:26> 'unsigned int' <IntegralCast>
    > `-ImplicitCastExpr 0x30bd578 <col:26> 'int' <LValueToRValue>
    > `-DeclRefExpr 0x30bd508 <col:26> 'const int' lvalue Var 0x30bd1d0 'DEFAULT_WEIGHT' 'const int'
    `-ReturnStmt 0x30bd630 <line:7:3, col:10>
      `-ImplicitCastExpr 0x30bd618 <col:10> 'unsigned int' <LValueToRValue>
        `-DeclRefExpr 0x30bd5f0 <col:10> 'unsigned int' lvalue Var 0x30bd460 'ret' 'unsigned int'

says it's an lvalue.

-Eli

Thank you!

Is it solely because of 3.10.5 ("An expression which holds a temporary object resulting from a cast to a nonreference type is an rvalue"), or am I missing something else?

-Eli