r337815 - [Sema] Mark implicitly-inserted ICE's as being part of explicit cast (PR38166)

Roman Lebedev via cfe-commits cfe-commits at lists.llvm.org
Tue Jul 24 01:16:51 PDT 2018


Author: lebedevri
Date: Tue Jul 24 01:16:50 2018
New Revision: 337815

URL: http://llvm.org/viewvc/llvm-project?rev=337815&view=rev
Log:
[Sema] Mark implicitly-inserted ICE's as being part of explicit cast (PR38166)

Summary:
As discussed in [[ https://bugs.llvm.org/show_bug.cgi?id=38166 | PR38166 ]], we need to be able to distinqush whether the cast
we are visiting is actually a cast, or part of an `ExplicitCast`.
There are at least four ways to get there:
1. Introduce a new `CastKind`, and use it instead of `IntegralCast` if we are in `ExplicitCast`.

   Would work, but does not scale - what if we will need more of these cast kinds?
2. Introduce a flag in `CastExprBits`, whether this cast is part of `ExplicitCast` or not.

   Would work, but it isn't immediately clear where it needs to be set.
2. Fix `ScalarExprEmitter::VisitCastExpr()` to visit these `NoOp` casts.

   As pointed out by @rsmith, CodeGenFunction::EmitMaterializeTemporaryExpr calls

   skipRValueSubobjectAdjustments, which steps over the CK_NoOp cast`,

   which explains why we currently don't visit those.

   This is probably impossible, as @efriedma points out, that is intentional as per `[class.temporary]` in the standard
3. And the simplest one, just record which NoOp casts we skip.

   It just kinda works as-is afterwards.

But, the approach with a flag is the least intrusive one, and is probably the best one overall.

Reviewers: rsmith, rjmccall, majnemer, efriedma

Reviewed By: rsmith

Subscribers: cfe-commits, aaron.ballman, vsk, llvm-commits, rsmith

Differential Revision: https://reviews.llvm.org/D49508

Added:
    cfe/trunk/test/Sema/multistep-explicit-cast.c
    cfe/trunk/test/SemaCXX/multistep-explicit-cast.cpp
    cfe/trunk/test/SemaOpenCL/multistep-explicit-cast.cl
Modified:
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/include/clang/AST/Stmt.h
    cfe/trunk/lib/AST/ASTDumper.cpp
    cfe/trunk/lib/Sema/SemaCast.cpp
    cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
    cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
    cfe/trunk/test/PCH/cxx_exprs.cpp

Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=337815&r1=337814&r2=337815&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Tue Jul 24 01:16:50 2018
@@ -2821,6 +2821,7 @@ protected:
               (op && op->containsUnexpandedParameterPack()))),
         Op(op) {
     CastExprBits.Kind = kind;
+    CastExprBits.PartOfExplicitCast = false;
     setBasePathSize(BasePathSize);
     assert(CastConsistency());
   }
@@ -2835,6 +2836,13 @@ public:
   CastKind getCastKind() const { return (CastKind) CastExprBits.Kind; }
   void setCastKind(CastKind K) { CastExprBits.Kind = K; }
 
+  bool getIsPartOfExplicitCast() const {
+    return CastExprBits.PartOfExplicitCast;
+  }
+  void setIsPartOfExplicitCast(bool PartOfExplicitCast) {
+    CastExprBits.PartOfExplicitCast = PartOfExplicitCast;
+  }
+
   static const char *getCastKindName(CastKind CK);
   const char *getCastKindName() const { return getCastKindName(getCastKind()); }
 

Modified: cfe/trunk/include/clang/AST/Stmt.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=337815&r1=337814&r2=337815&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Tue Jul 24 01:16:50 2018
@@ -202,7 +202,8 @@ protected:
     unsigned : NumExprBits;
 
     unsigned Kind : 6;
-    unsigned BasePathSize : 32 - 6 - NumExprBits;
+    unsigned PartOfExplicitCast : 1;
+    unsigned BasePathSize : 32 - 6 - 1 - NumExprBits;
   };
 
   class CallExprBitfields {

Modified: cfe/trunk/lib/AST/ASTDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDumper.cpp?rev=337815&r1=337814&r2=337815&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTDumper.cpp (original)
+++ cfe/trunk/lib/AST/ASTDumper.cpp Tue Jul 24 01:16:50 2018
@@ -2117,6 +2117,9 @@ void ASTDumper::VisitCastExpr(const Cast
   }
   dumpBasePath(OS, Node);
   OS << ">";
+
+  if (Node->getIsPartOfExplicitCast())
+    OS << " part_of_explicit_cast";
 }
 
 void ASTDumper::VisitDeclRefExpr(const DeclRefExpr *Node) {

Modified: cfe/trunk/lib/Sema/SemaCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCast.cpp?rev=337815&r1=337814&r2=337815&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCast.cpp Tue Jul 24 01:16:50 2018
@@ -89,6 +89,14 @@ namespace {
     void CheckCXXCStyleCast(bool FunctionalCast, bool ListInitialization);
     void CheckCStyleCast();
 
+    void updatePartOfExplicitCastFlags(CastExpr *CE) {
+      // Walk down from the CE to the OrigSrcExpr, and mark all immediate
+      // ImplicitCastExpr's as being part of ExplicitCastExpr. The original CE
+      // (which is a ExplicitCastExpr), and the OrigSrcExpr are not touched.
+      while ((CE = dyn_cast<ImplicitCastExpr>(CE->getSubExpr())))
+        CE->setIsPartOfExplicitCast(true);
+    }
+
     /// Complete an apparently-successful cast operation that yields
     /// the given expression.
     ExprResult complete(CastExpr *castExpr) {
@@ -100,6 +108,7 @@ namespace {
                                             CK_Dependent, castExpr, nullptr,
                                             castExpr->getValueKind());
       }
+      updatePartOfExplicitCastFlags(castExpr);
       return castExpr;
     }
 

Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=337815&r1=337814&r2=337815&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Tue Jul 24 01:16:50 2018
@@ -723,6 +723,7 @@ void ASTStmtReader::VisitCastExpr(CastEx
   assert(NumBaseSpecs == E->path_size());
   E->setSubExpr(Record.readSubExpr());
   E->setCastKind((CastKind)Record.readInt());
+  E->setIsPartOfExplicitCast(Record.readInt());
   CastExpr::path_iterator BaseI = E->path_begin();
   while (NumBaseSpecs--) {
     auto *BaseSpec = new (Record.getContext()) CXXBaseSpecifier;

Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=337815&r1=337814&r2=337815&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Tue Jul 24 01:16:50 2018
@@ -2192,6 +2192,7 @@ void ASTWriter::WriteDeclAbbrevs() {
   // CastExpr
   Abv->Add(BitCodeAbbrevOp(0)); // PathSize
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 6)); // CastKind
+  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // PartOfExplicitCast
   // ImplicitCastExpr
   ExprImplicitCastAbbrev = Stream.EmitAbbrev(std::move(Abv));
 

Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=337815&r1=337814&r2=337815&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Tue Jul 24 01:16:50 2018
@@ -665,6 +665,7 @@ void ASTStmtWriter::VisitCastExpr(CastEx
   Record.push_back(E->path_size());
   Record.AddStmt(E->getSubExpr());
   Record.push_back(E->getCastKind()); // FIXME: stable encoding
+  Record.push_back(E->getIsPartOfExplicitCast());
 
   for (CastExpr::path_iterator
          PI = E->path_begin(), PE = E->path_end(); PI != PE; ++PI)

Modified: cfe/trunk/test/PCH/cxx_exprs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx_exprs.cpp?rev=337815&r1=337814&r2=337815&view=diff
==============================================================================
--- cfe/trunk/test/PCH/cxx_exprs.cpp (original)
+++ cfe/trunk/test/PCH/cxx_exprs.cpp Tue Jul 24 01:16:50 2018
@@ -1,9 +1,9 @@
 // Test this without pch.
-// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -include %S/cxx_exprs.h -std=c++11 -fsyntax-only -verify %s -ast-dump
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -include %S/cxx_exprs.h -std=c++11 -fsyntax-only -verify %s -ast-dump | FileCheck %s
 
 // Test with pch. Use '-ast-dump' to force deserialization of function bodies.
 // RUN: %clang_cc1 -fcxx-exceptions -fexceptions -x c++-header -std=c++11 -emit-pch -o %t %S/cxx_exprs.h
-// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-dump
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-dump-all | FileCheck %s
 
 // expected-no-diagnostics
 
@@ -14,19 +14,49 @@ bool boolean;
 
 // CXXStaticCastExpr
 static_cast_result void_ptr = &integer;
+// CHECK: TypedefDecl {{.*}} <{{.*}}, col:{{.*}}> col:{{.*}}{{(imported)?}} referenced static_cast_result 'typeof (static_cast<void *>(0))':'void *'{{$}}
+// CHECK-NEXT: TypeOfExprType {{.*}} 'typeof (static_cast<void *>(0))' sugar{{( imported)?}}{{$}}
+// CHECK-NEXT: ParenExpr {{.*}} <col:{{.*}}, col:{{.*}}> 'void *'{{$}}
+// CHECK-NEXT: CXXStaticCastExpr {{.*}} <col:{{.*}}, col:{{.*}}> 'void *' static_cast<void *> <NoOp>{{$}}
+// CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'void *' <NullToPointer> part_of_explicit_cast{{$}}
+// CHECK-NEXT: IntegerLiteral {{.*}} <col:{{.*}}> 'int' 0{{$}}
 
 // CXXDynamicCastExpr
 Derived *d;
 dynamic_cast_result derived_ptr = d;
+// CHECK: TypedefDecl {{.*}} <{{.*}}, col:{{.*}}> col:{{.*}} referenced dynamic_cast_result 'typeof (dynamic_cast<Derived *>(base_ptr))':'Derived *'{{$}}
+// CHECK-NEXT: TypeOfExprType {{.*}} 'typeof (dynamic_cast<Derived *>(base_ptr))' sugar{{( imported)?}}{{$}}
+// CHECK-NEXT: ParenExpr {{.*}} <col:{{.*}}, col:{{.*}}> 'Derived *'{{$}}
+// CHECK-NEXT: CXXDynamicCastExpr {{.*}} <col:{{.*}}, col:{{.*}}> 'Derived *' dynamic_cast<struct Derived *> <Dynamic>{{$}}
+// CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'Base *' <LValueToRValue> part_of_explicit_cast{{$}}
+// CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'Base *' lvalue Var {{.*}} 'base_ptr' 'Base *'{{$}}
 
 // CXXReinterpretCastExpr
 reinterpret_cast_result void_ptr2 = &integer;
+// CHECK: TypedefDecl {{.*}} <{{.*}}, col:{{.*}}> col:{{.*}} referenced reinterpret_cast_result 'typeof (reinterpret_cast<void *>(0))':'void *'{{$}}
+// CHECK-NEXT: TypeOfExprType {{.*}} 'typeof (reinterpret_cast<void *>(0))' sugar{{( imported)?}}{{$}}
+// CHECK-NEXT: ParenExpr {{.*}} <col:{{.*}}, col:{{.*}}> 'void *'{{$}}
+// CHECK-NEXT: CXXReinterpretCastExpr {{.*}} <col:{{.*}}, col:{{.*}}> 'void *' reinterpret_cast<void *> <IntegralToPointer>{{$}}
+// CHECK-NEXT: IntegerLiteral {{.*}} <col:{{.*}}> 'int' 0{{$}}
 
 // CXXConstCastExpr
 const_cast_result char_ptr = &character;
+// CHECK: TypedefDecl {{.*}} <{{.*}}, col:{{.*}}> col:{{.*}} referenced const_cast_result 'typeof (const_cast<char *>(const_char_ptr_value))':'char *'{{$}}
+// CHECK-NEXT: TypeOfExprType {{.*}} 'typeof (const_cast<char *>(const_char_ptr_value))' sugar{{( imported)?}}{{$}}
+// CHECK-NEXT: ParenExpr {{.*}} <col:{{.*}}, col:{{.*}}> 'char *'{{$}}
+// CHECK-NEXT: CXXConstCastExpr {{.*}} <col:{{.*}}, col:{{.*}}> 'char *' const_cast<char *> <NoOp>{{$}}
+// CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'const char *' <LValueToRValue> part_of_explicit_cast{{$}}
+// CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'const char *' lvalue Var {{.*}} 'const_char_ptr_value' 'const char *'{{$}}
 
 // CXXFunctionalCastExpr
 functional_cast_result *double_ptr = &floating;
+// CHECK: TypedefDecl {{.*}} <{{.*}}, col:{{.*}}> col:{{.*}} referenced functional_cast_result 'typeof (double(int_value))':'double'{{$}}
+// CHECK-NEXT: TypeOfExprType {{.*}} 'typeof (double(int_value))' sugar{{( imported)?}}{{$}}
+// CHECK-NEXT: ParenExpr {{.*}} <col:{{.*}}, col:{{.*}}> 'double'{{$}}
+// CHECK-NEXT: CXXFunctionalCastExpr {{.*}} <col:{{.*}}, col:{{.*}}> 'double' functional cast to double <NoOp>{{$}}
+// CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'double' <IntegralToFloating> part_of_explicit_cast{{$}}
+// CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue> part_of_explicit_cast{{$}}
+// CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue Var {{.*}} 'int_value' 'int'{{$}}
 
 // CXXBoolLiteralExpr
 bool_literal_result *bool_ptr = &boolean;

Added: cfe/trunk/test/Sema/multistep-explicit-cast.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/multistep-explicit-cast.c?rev=337815&view=auto
==============================================================================
--- cfe/trunk/test/Sema/multistep-explicit-cast.c (added)
+++ cfe/trunk/test/Sema/multistep-explicit-cast.c Tue Jul 24 01:16:50 2018
@@ -0,0 +1,70 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -ast-dump %s | FileCheck %s
+
+// We are checking that implicit casts don't get marked with 'part_of_explicit_cast',
+// while in explicit casts, the implicitly-inserted implicit casts are marked with 'part_of_explicit_cast'
+
+unsigned char implicitcast_0(unsigned int x) {
+  // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_0 'unsigned char (unsigned int)'{{$}}
+  // CHECK: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <IntegralCast>{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned int' <LValueToRValue>{{$}}
+  // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}}
+  return x;
+}
+
+signed char implicitcast_1(unsigned int x) {
+  // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_1 'signed char (unsigned int)'{{$}}
+  // CHECK: ImplicitCastExpr {{.*}} <col:{{.*}}> 'signed char' <IntegralCast>{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned int' <LValueToRValue>{{$}}
+  // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}}
+  return x;
+}
+
+unsigned char implicitcast_2(signed int x) {
+  // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_2 'unsigned char (int)'{{$}}
+  // CHECK: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <IntegralCast>{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue>{{$}}
+  // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}}
+  return x;
+}
+
+signed char implicitcast_3(signed int x) {
+  // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_3 'signed char (int)'{{$}}
+  // CHECK: ImplicitCastExpr {{.*}} <col:{{.*}}> 'signed char' <IntegralCast>{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue>{{$}}
+  // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}}
+  return x;
+}
+
+//----------------------------------------------------------------------------//
+
+unsigned char cstylecast_0(unsigned int x) {
+  // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_0 'unsigned char (unsigned int)'{{$}}
+  // CHECK: CStyleCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <IntegralCast>{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned int' <LValueToRValue> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}}
+  return (unsigned char)x;
+}
+
+signed char cstylecast_1(unsigned int x) {
+  // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_1 'signed char (unsigned int)'{{$}}
+  // CHECK: CStyleCastExpr {{.*}} <col:{{.*}}> 'signed char' <IntegralCast>{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned int' <LValueToRValue> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}}
+  return (signed char)x;
+}
+
+unsigned char cstylecast_2(signed int x) {
+  // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_2 'unsigned char (int)'{{$}}
+  // CHECK: CStyleCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <IntegralCast>{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}}
+  return (unsigned char)x;
+}
+
+signed char cstylecast_3(signed int x) {
+  // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_3 'signed char (int)'{{$}}
+  // CHECK: CStyleCastExpr {{.*}} <col:{{.*}}> 'signed char' <IntegralCast>{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}}
+  return (signed char)x;
+}

Added: cfe/trunk/test/SemaCXX/multistep-explicit-cast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/multistep-explicit-cast.cpp?rev=337815&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/multistep-explicit-cast.cpp (added)
+++ cfe/trunk/test/SemaCXX/multistep-explicit-cast.cpp Tue Jul 24 01:16:50 2018
@@ -0,0 +1,155 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -ast-dump %s | FileCheck %s
+
+// We are checking that implicit casts don't get marked with 'part_of_explicit_cast',
+// while in explicit casts, the implicitly-inserted implicit casts are marked with 'part_of_explicit_cast'
+
+unsigned char implicitcast_0(unsigned int x) {
+  // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_0 'unsigned char (unsigned int)'{{$}}
+  // CHECK: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <IntegralCast>{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned int' <LValueToRValue>{{$}}
+  // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}}
+  return x;
+}
+
+signed char implicitcast_1(unsigned int x) {
+  // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_1 'signed char (unsigned int)'{{$}}
+  // CHECK: ImplicitCastExpr {{.*}} <col:{{.*}}> 'signed char' <IntegralCast>{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned int' <LValueToRValue>{{$}}
+  // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}}
+  return x;
+}
+
+unsigned char implicitcast_2(signed int x) {
+  // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_2 'unsigned char (int)'{{$}}
+  // CHECK: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <IntegralCast>{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue>{{$}}
+  // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}}
+  return x;
+}
+
+signed char implicitcast_3(signed int x) {
+  // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_3 'signed char (int)'{{$}}
+  // CHECK: ImplicitCastExpr {{.*}} <col:{{.*}}> 'signed char' <IntegralCast>{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue>{{$}}
+  // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}}
+  return x;
+}
+
+//----------------------------------------------------------------------------//
+
+unsigned char cstylecast_0(unsigned int x) {
+  // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_0 'unsigned char (unsigned int)'{{$}}
+  // CHECK: CStyleCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <NoOp>{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <IntegralCast> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned int' <LValueToRValue> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}}
+  return (unsigned char)x;
+}
+
+signed char cstylecast_1(unsigned int x) {
+  // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_1 'signed char (unsigned int)'{{$}}
+  // CHECK: CStyleCastExpr {{.*}} <col:{{.*}}> 'signed char' <NoOp>{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'signed char' <IntegralCast> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned int' <LValueToRValue> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}}
+  return (signed char)x;
+}
+
+unsigned char cstylecast_2(signed int x) {
+  // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_2 'unsigned char (int)'{{$}}
+  // CHECK: CStyleCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <NoOp>{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <IntegralCast> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}}
+  return (unsigned char)x;
+}
+
+signed char cstylecast_3(signed int x) {
+  // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_3 'signed char (int)'{{$}}
+  // CHECK: CStyleCastExpr {{.*}} <col:{{.*}}> 'signed char' <NoOp>{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'signed char' <IntegralCast> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}}
+  return (signed char)x;
+}
+
+//----------------------------------------------------------------------------//
+
+unsigned char cxxstaticcast_0(unsigned int x) {
+  // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxstaticcast_0 'unsigned char (unsigned int)'{{$}}
+  // CHECK: CXXStaticCastExpr {{.*}} <col:{{.*}}> 'unsigned char' static_cast<unsigned char> <NoOp>{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <IntegralCast> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned int' <LValueToRValue> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}}
+  return static_cast<unsigned char>(x);
+}
+
+signed char cxxstaticcast_1(unsigned int x) {
+  // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxstaticcast_1 'signed char (unsigned int)'{{$}}
+  // CHECK: CXXStaticCastExpr {{.*}} <col:{{.*}}> 'signed char' static_cast<signed char> <NoOp>{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'signed char' <IntegralCast> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned int' <LValueToRValue> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}}
+  return static_cast<signed char>(x);
+}
+
+unsigned char cxxstaticcast_2(signed int x) {
+  // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxstaticcast_2 'unsigned char (int)'{{$}}
+  // CHECK: CXXStaticCastExpr {{.*}} <col:{{.*}}> 'unsigned char' static_cast<unsigned char> <NoOp>{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <IntegralCast> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}}
+  return static_cast<unsigned char>(x);
+}
+
+signed char cxxstaticcast_3(signed int x) {
+  // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxstaticcast_3 'signed char (int)'{{$}}
+  // CHECK: CXXStaticCastExpr {{.*}} <col:{{.*}}> 'signed char' static_cast<signed char> <NoOp>{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'signed char' <IntegralCast> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}}
+  return static_cast<signed char>(x);
+}
+
+//----------------------------------------------------------------------------//
+
+using UnsignedChar = unsigned char;
+using SignedChar = signed char;
+using UnsignedInt = unsigned int;
+using SignedInt = signed int;
+
+UnsignedChar cxxfunctionalcast_0(UnsignedInt x) {
+  // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxfunctionalcast_0 'UnsignedChar (UnsignedInt)'{{$}}
+  // CHECK: CXXFunctionalCastExpr {{.*}} <col:{{.*}}> 'UnsignedChar':'unsigned char' functional cast to UnsignedChar <NoOp>{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'UnsignedChar':'unsigned char' <IntegralCast> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'UnsignedInt':'unsigned int' <LValueToRValue> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'UnsignedInt':'unsigned int' lvalue ParmVar {{.*}} 'x' 'UnsignedInt':'unsigned int'{{$}}
+  return UnsignedChar(x);
+}
+
+SignedChar cxxfunctionalcast_1(UnsignedInt x) {
+  // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxfunctionalcast_1 'SignedChar (UnsignedInt)'{{$}}
+  // CHECK: CXXFunctionalCastExpr {{.*}} <col:{{.*}}> 'SignedChar':'signed char' functional cast to SignedChar <NoOp>{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'SignedChar':'signed char' <IntegralCast> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'UnsignedInt':'unsigned int' <LValueToRValue> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'UnsignedInt':'unsigned int' lvalue ParmVar {{.*}} 'x' 'UnsignedInt':'unsigned int'{{$}}
+  return SignedChar(x);
+}
+
+UnsignedChar cxxfunctionalcast_2(SignedInt x) {
+  // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxfunctionalcast_2 'UnsignedChar (SignedInt)'{{$}}
+  // CHECK: CXXFunctionalCastExpr {{.*}} <col:{{.*}}> 'UnsignedChar':'unsigned char' functional cast to UnsignedChar <NoOp>{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'UnsignedChar':'unsigned char' <IntegralCast> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'SignedInt':'int' <LValueToRValue> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'SignedInt':'int' lvalue ParmVar {{.*}} 'x' 'SignedInt':'int'{{$}}
+  return UnsignedChar(x);
+}
+
+SignedChar cxxfunctionalcast_3(SignedInt x) {
+  // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxfunctionalcast_3 'SignedChar (SignedInt)'{{$}}
+  // CHECK: CXXFunctionalCastExpr {{.*}} <col:{{.*}}> 'SignedChar':'signed char' functional cast to SignedChar <NoOp>{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'SignedChar':'signed char' <IntegralCast> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'SignedInt':'int' <LValueToRValue> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'SignedInt':'int' lvalue ParmVar {{.*}} 'x' 'SignedInt':'int'{{$}}
+  return SignedChar(x);
+}

Added: cfe/trunk/test/SemaOpenCL/multistep-explicit-cast.cl
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaOpenCL/multistep-explicit-cast.cl?rev=337815&view=auto
==============================================================================
--- cfe/trunk/test/SemaOpenCL/multistep-explicit-cast.cl (added)
+++ cfe/trunk/test/SemaOpenCL/multistep-explicit-cast.cl Tue Jul 24 01:16:50 2018
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -ast-dump %s | FileCheck %s
+// expected-no-diagnostics
+
+typedef __attribute__((ext_vector_type(2)))  char char2;
+
+void vectorIncrementDecrementOps() {
+  // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} vectorIncrementDecrementOps 'void (void)'{{$}}
+  // CHECK: CStyleCastExpr {{.*}} <col:{{.*}}> 'char2':'char __attribute__((ext_vector_type(2)))' <VectorSplat>{{$}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'char' <IntegralCast> part_of_explicit_cast{{$}}
+  // CHECK-NEXT: IntegerLiteral {{.*}} <col:{{.*}}> 'int' 1{{$}}
+  char2 A = (char2)(1);
+  A++;
+}




More information about the cfe-commits mailing list