Index: include/clang/AST/Expr.h =================================================================== --- include/clang/AST/Expr.h +++ include/clang/AST/Expr.h @@ -2821,6 +2821,7 @@ (op && op->containsUnexpandedParameterPack()))), Op(op) { CastExprBits.Kind = kind; + CastExprBits.PartOfExplicitCast = false; setBasePathSize(BasePathSize); assert(CastConsistency()); } @@ -2835,6 +2836,13 @@ 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()); } Index: include/clang/AST/Stmt.h =================================================================== --- include/clang/AST/Stmt.h +++ include/clang/AST/Stmt.h @@ -202,7 +202,8 @@ unsigned : NumExprBits; unsigned Kind : 6; - unsigned BasePathSize : 32 - 6 - NumExprBits; + unsigned PartOfExplicitCast : 1; + unsigned BasePathSize : 32 - 6 - 1 - NumExprBits; }; class CallExprBitfields { Index: lib/AST/ASTDumper.cpp =================================================================== --- lib/AST/ASTDumper.cpp +++ lib/AST/ASTDumper.cpp @@ -2117,6 +2117,9 @@ } dumpBasePath(OS, Node); OS << ">"; + + if (Node->getIsPartOfExplicitCast()) + OS << " part_of_explicit_cast"; } void ASTDumper::VisitDeclRefExpr(const DeclRefExpr *Node) { Index: lib/Sema/SemaCast.cpp =================================================================== --- lib/Sema/SemaCast.cpp +++ lib/Sema/SemaCast.cpp @@ -89,6 +89,14 @@ 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(CE->getSubExpr()))) + CE->setIsPartOfExplicitCast(true); + } + /// Complete an apparently-successful cast operation that yields /// the given expression. ExprResult complete(CastExpr *castExpr) { @@ -100,6 +108,7 @@ CK_Dependent, castExpr, nullptr, castExpr->getValueKind()); } + updatePartOfExplicitCastFlags(castExpr); return castExpr; } Index: lib/Serialization/ASTReaderStmt.cpp =================================================================== --- lib/Serialization/ASTReaderStmt.cpp +++ lib/Serialization/ASTReaderStmt.cpp @@ -723,6 +723,7 @@ 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; Index: lib/Serialization/ASTWriterDecl.cpp =================================================================== --- lib/Serialization/ASTWriterDecl.cpp +++ lib/Serialization/ASTWriterDecl.cpp @@ -2192,6 +2192,7 @@ // 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)); Index: lib/Serialization/ASTWriterStmt.cpp =================================================================== --- lib/Serialization/ASTWriterStmt.cpp +++ lib/Serialization/ASTWriterStmt.cpp @@ -665,6 +665,7 @@ 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) Index: test/PCH/cxx_exprs.cpp =================================================================== --- test/PCH/cxx_exprs.cpp +++ test/PCH/cxx_exprs.cpp @@ -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 @@ // CXXStaticCastExpr static_cast_result void_ptr = &integer; +// CHECK: TypedefDecl {{.*}} <{{.*}}, col:{{.*}}> col:{{.*}}{{(imported)?}} referenced static_cast_result 'typeof (static_cast(0))':'void *'{{$}} +// CHECK-NEXT: TypeOfExprType {{.*}} 'typeof (static_cast(0))' sugar{{( imported)?}}{{$}} +// CHECK-NEXT: ParenExpr {{.*}} 'void *'{{$}} +// CHECK-NEXT: CXXStaticCastExpr {{.*}} 'void *' static_cast {{$}} +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void *' part_of_explicit_cast{{$}} +// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 0{{$}} // CXXDynamicCastExpr Derived *d; dynamic_cast_result derived_ptr = d; +// CHECK: TypedefDecl {{.*}} <{{.*}}, col:{{.*}}> col:{{.*}} referenced dynamic_cast_result 'typeof (dynamic_cast(base_ptr))':'Derived *'{{$}} +// CHECK-NEXT: TypeOfExprType {{.*}} 'typeof (dynamic_cast(base_ptr))' sugar{{( imported)?}}{{$}} +// CHECK-NEXT: ParenExpr {{.*}} 'Derived *'{{$}} +// CHECK-NEXT: CXXDynamicCastExpr {{.*}} 'Derived *' dynamic_cast {{$}} +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'Base *' part_of_explicit_cast{{$}} +// CHECK-NEXT: DeclRefExpr {{.*}} 'Base *' lvalue Var {{.*}} 'base_ptr' 'Base *'{{$}} // CXXReinterpretCastExpr reinterpret_cast_result void_ptr2 = &integer; +// CHECK: TypedefDecl {{.*}} <{{.*}}, col:{{.*}}> col:{{.*}} referenced reinterpret_cast_result 'typeof (reinterpret_cast(0))':'void *'{{$}} +// CHECK-NEXT: TypeOfExprType {{.*}} 'typeof (reinterpret_cast(0))' sugar{{( imported)?}}{{$}} +// CHECK-NEXT: ParenExpr {{.*}} 'void *'{{$}} +// CHECK-NEXT: CXXReinterpretCastExpr {{.*}} 'void *' reinterpret_cast {{$}} +// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 0{{$}} // CXXConstCastExpr const_cast_result char_ptr = &character; +// CHECK: TypedefDecl {{.*}} <{{.*}}, col:{{.*}}> col:{{.*}} referenced const_cast_result 'typeof (const_cast(const_char_ptr_value))':'char *'{{$}} +// CHECK-NEXT: TypeOfExprType {{.*}} 'typeof (const_cast(const_char_ptr_value))' sugar{{( imported)?}}{{$}} +// CHECK-NEXT: ParenExpr {{.*}} 'char *'{{$}} +// CHECK-NEXT: CXXConstCastExpr {{.*}} 'char *' const_cast {{$}} +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'const char *' part_of_explicit_cast{{$}} +// CHECK-NEXT: DeclRefExpr {{.*}} '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 {{.*}} 'double'{{$}} +// CHECK-NEXT: CXXFunctionalCastExpr {{.*}} 'double' functional cast to double {{$}} +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'double' part_of_explicit_cast{{$}} +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' part_of_explicit_cast{{$}} +// CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'int_value' 'int'{{$}} // CXXBoolLiteralExpr bool_literal_result *bool_ptr = &boolean; Index: test/Sema/multistep-explicit-cast.c =================================================================== --- test/Sema/multistep-explicit-cast.c +++ test/Sema/multistep-explicit-cast.c @@ -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 {{.*}} 'unsigned char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' {{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} '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 {{.*}} 'signed char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' {{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} '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 {{.*}} 'unsigned char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' {{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} '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 {{.*}} 'signed char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' {{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} '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 {{.*}} 'unsigned char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} '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 {{.*}} 'signed char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} '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 {{.*}} 'unsigned char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} '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 {{.*}} 'signed char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}} + return (signed char)x; +} Index: test/SemaCXX/multistep-explicit-cast.cpp =================================================================== --- test/SemaCXX/multistep-explicit-cast.cpp +++ test/SemaCXX/multistep-explicit-cast.cpp @@ -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 {{.*}} 'unsigned char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' {{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} '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 {{.*}} 'signed char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' {{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} '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 {{.*}} 'unsigned char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' {{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} '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 {{.*}} 'signed char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' {{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} '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 {{.*}} 'unsigned char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned char' part_of_explicit_cast{{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} '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 {{.*}} 'signed char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'signed char' part_of_explicit_cast{{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} '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 {{.*}} 'unsigned char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned char' part_of_explicit_cast{{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} '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 {{.*}} 'signed char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'signed char' part_of_explicit_cast{{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} '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 {{.*}} 'unsigned char' static_cast {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned char' part_of_explicit_cast{{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}} + return static_cast(x); +} + +signed char cxxstaticcast_1(unsigned int x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxstaticcast_1 'signed char (unsigned int)'{{$}} + // CHECK: CXXStaticCastExpr {{.*}} 'signed char' static_cast {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'signed char' part_of_explicit_cast{{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}} + return static_cast(x); +} + +unsigned char cxxstaticcast_2(signed int x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxstaticcast_2 'unsigned char (int)'{{$}} + // CHECK: CXXStaticCastExpr {{.*}} 'unsigned char' static_cast {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned char' part_of_explicit_cast{{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}} + return static_cast(x); +} + +signed char cxxstaticcast_3(signed int x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxstaticcast_3 'signed char (int)'{{$}} + // CHECK: CXXStaticCastExpr {{.*}} 'signed char' static_cast {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'signed char' part_of_explicit_cast{{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}} + return static_cast(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 {{.*}} 'UnsignedChar':'unsigned char' functional cast to UnsignedChar {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'UnsignedChar':'unsigned char' part_of_explicit_cast{{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'UnsignedInt':'unsigned int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} '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 {{.*}} 'SignedChar':'signed char' functional cast to SignedChar {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'SignedChar':'signed char' part_of_explicit_cast{{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'UnsignedInt':'unsigned int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} '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 {{.*}} 'UnsignedChar':'unsigned char' functional cast to UnsignedChar {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'UnsignedChar':'unsigned char' part_of_explicit_cast{{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'SignedInt':'int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} '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 {{.*}} 'SignedChar':'signed char' functional cast to SignedChar {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'SignedChar':'signed char' part_of_explicit_cast{{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'SignedInt':'int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'SignedInt':'int' lvalue ParmVar {{.*}} 'x' 'SignedInt':'int'{{$}} + return SignedChar(x); +} Index: test/SemaOpenCL/multistep-explicit-cast.cl =================================================================== --- test/SemaOpenCL/multistep-explicit-cast.cl +++ test/SemaOpenCL/multistep-explicit-cast.cl @@ -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 {{.*}} 'char2':'char __attribute__((ext_vector_type(2)))' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'char' part_of_explicit_cast{{$}} + // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 1{{$}} + char2 A = (char2)(1); + A++; +}