[llvm-bugs] [Bug 38017] New: Is AST incorrectly representing C++'s explicit casts?

via llvm-bugs llvm-bugs at lists.llvm.org
Mon Jul 2 06:57:44 PDT 2018


https://bugs.llvm.org/show_bug.cgi?id=38017

            Bug ID: 38017
           Summary: Is AST incorrectly representing C++'s explicit casts?
           Product: clang
           Version: trunk
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: Frontend
          Assignee: unassignedclangbugs at nondot.org
          Reporter: lebedev.ri at gmail.com
                CC: llvm-bugs at lists.llvm.org

https://godbolt.org/g/eE1GkJ

Given this simple C source, containing the explicit cast:

unsigned char t0(unsigned int src) {
  return (unsigned char)src;
}

The resulting AST is as you would expect:

TranslationUnitDecl
`-FunctionDecl <line:1:1, line:3:1> line:1:15 t0 'unsigned char (unsigned int)'
  |-ParmVarDecl <col:18, col:31> col:31 used src 'unsigned int'
  `-CompoundStmt <col:36, line:3:1>
    `-ReturnStmt <line:2:3, col:25>
      `-CStyleCastExpr <col:10, col:25> 'unsigned char' <IntegralCast>
        `-ImplicitCastExpr <col:25> 'unsigned int' <LValueToRValue>
          `-DeclRefExpr <col:25> 'unsigned int' lvalue ParmVar 0x563fcaa5ad70
'src' 'unsigned int'

The CStyleCastExpr is not an NoOp, it actually does what is spelled in the
source code.

But.

Given this C++ source code:

unsigned char t0(unsigned int src) {
  return (unsigned char)src;
}
unsigned char t1(unsigned int src) {
  return static_cast<unsigned char>(src);
}
using UnsignedChar = unsigned char;
UnsignedChar t2(unsigned int src) {
  return UnsignedChar(src);
}
unsigned char t3(unsigned int src) {
  return static_cast<UnsignedChar>(src);
}


The AST is strange:

TranslationUnitDecl
|-FunctionDecl <line:1:1, line:3:1> line:1:15 t0 'unsigned char (unsigned int)'
| |-ParmVarDecl <col:18, col:31> col:31 used src 'unsigned int'
| `-CompoundStmt <col:36, line:3:1>
|   `-ReturnStmt <line:2:3, col:25>
|     `-CStyleCastExpr <col:10, col:25> 'unsigned char' <NoOp>
|       `-ImplicitCastExpr <col:25> 'unsigned char' <IntegralCast>
|         `-ImplicitCastExpr <col:25> 'unsigned int' <LValueToRValue>
|           `-DeclRefExpr <col:25> 'unsigned int' lvalue ParmVar 0x55b2a6f4d720
'src' 'unsigned int'
|-FunctionDecl <line:4:1, line:6:1> line:4:15 t1 'unsigned char (unsigned int)'
| |-ParmVarDecl <col:18, col:31> col:31 used src 'unsigned int'
| `-CompoundStmt <col:36, line:6:1>
|   `-ReturnStmt <line:5:3, col:40>
|     `-CXXStaticCastExpr <col:10, col:40> 'unsigned char' static_cast<unsigned
char> <NoOp>
|       `-ImplicitCastExpr <col:37> 'unsigned char' <IntegralCast>
|         `-ImplicitCastExpr <col:37> 'unsigned int' <LValueToRValue>
|           `-DeclRefExpr <col:37> 'unsigned int' lvalue ParmVar 0x55b2a6f4d9b0
'src' 'unsigned int'
|-TypeAliasDecl <line:7:1, col:31> col:7 referenced UnsignedChar 'unsigned
char'
| `-BuiltinType 'unsigned char'
|-FunctionDecl <line:8:1, line:10:1> line:8:14 t2 'UnsignedChar (unsigned int)'
| |-ParmVarDecl <col:17, col:30> col:30 used src 'unsigned int'
| `-CompoundStmt <col:35, line:10:1>
|   `-ReturnStmt <line:9:3, col:26>
|     `-CXXFunctionalCastExpr <col:10, col:26> 'UnsignedChar':'unsigned char'
functional cast to UnsignedChar <NoOp>
|       `-ImplicitCastExpr <col:23> 'UnsignedChar':'unsigned char'
<IntegralCast>
|         `-ImplicitCastExpr <col:23> 'unsigned int' <LValueToRValue>
|           `-DeclRefExpr <col:23> 'unsigned int' lvalue ParmVar 0x55b2a6f4dc68
'src' 'unsigned int'
`-FunctionDecl <line:11:1, line:13:1> line:11:15 t3 'unsigned char (unsigned
int)'
  |-ParmVarDecl <col:18, col:31> col:31 used src 'unsigned int'
  `-CompoundStmt <col:36, line:13:1>
    `-ReturnStmt <line:12:3, col:39>
      `-CXXStaticCastExpr <col:10, col:39> 'UnsignedChar':'unsigned char'
static_cast<UnsignedChar> <NoOp>
        `-ImplicitCastExpr <col:36> 'UnsignedChar':'unsigned char'
<IntegralCast>
          `-ImplicitCastExpr <col:36> 'unsigned int' <LValueToRValue>
            `-DeclRefExpr <col:36> 'unsigned int' lvalue ParmVar 0x55b2a6f4deb0
'src' 'unsigned int'

So all the CStyleCastExpr/CXXStaticCastExpr/CXXFunctionalCastExpr are actually
NoOp,
and an ImplicitCastExpr is inserted as their child, which actually does the
cast.

Is this actually correct? It looks at the very least fishy to me.
Can this be fixed so these explicit casts are not a NoOp, but actually do the
work?

This complicates #21530.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20180702/e9416e8d/attachment.html>


More information about the llvm-bugs mailing list