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