diff options
-rw-r--r-- | include/clang/AST/Expr.h | 4 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 2 | ||||
-rw-r--r-- | lib/Checker/GRExprEngine.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 8 | ||||
-rw-r--r-- | test/CodeGenCXX/member-expressions.cpp | 40 |
7 files changed, 56 insertions, 4 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 96436f511b..b21f41777a 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -1552,6 +1552,10 @@ public: /// CK_DerivedToBase - Derived to base class casts. CK_DerivedToBase, + /// CK_UncheckedDerivedToBase - Derived to base class casts that + /// assume that the derived pointer is not null. + CK_UncheckedDerivedToBase, + /// CK_Dynamic - Dynamic cast. CK_Dynamic, diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index a9b5f36a98..4cb7712e52 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -552,6 +552,8 @@ const char *CastExpr::getCastKindName() const { return "BaseToDerived"; case CastExpr::CK_DerivedToBase: return "DerivedToBase"; + case CastExpr::CK_UncheckedDerivedToBase: + return "UncheckedDerivedToBase"; case CastExpr::CK_Dynamic: return "Dynamic"; case CastExpr::CK_ToUnion: diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp index 1afe0917f1..04f8cc6142 100644 --- a/lib/Checker/GRExprEngine.cpp +++ b/lib/Checker/GRExprEngine.cpp @@ -2306,6 +2306,7 @@ void GRExprEngine::VisitCast(CastExpr *CastE, Expr *Ex, ExplodedNode *Pred, case CastExpr::CK_AnyPointerToObjCPointerCast: case CastExpr::CK_AnyPointerToBlockPointerCast: case CastExpr::CK_DerivedToBase: + case CastExpr::CK_UncheckedDerivedToBase: // Delegate to SValuator to process. for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) { ExplodedNode* N = *I; diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 2ddc08a4c4..027264f25b 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1637,6 +1637,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { case CastExpr::CK_AnyPointerToObjCPointerCast: return EmitLValue(E->getSubExpr()); + case CastExpr::CK_UncheckedDerivedToBase: case CastExpr::CK_DerivedToBase: { const RecordType *DerivedClassTy = E->getSubExpr()->getType()->getAs<RecordType>(); diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 1ef06ccf6f..42bf68ed52 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -769,6 +769,9 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) { static bool ShouldNullCheckClassCastValue(const CastExpr *CE) { const Expr *E = CE->getSubExpr(); + + if (CE->getCastKind() == CastExpr::CK_UncheckedDerivedToBase) + return false; if (isa<CXXThisExpr>(E)) { // We always assume that 'this' is never null. @@ -826,6 +829,7 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) { return CGF.GetAddressOfDerivedClass(Src, BaseClassDecl, DerivedClassDecl, NullCheckValue); } + case CastExpr::CK_UncheckedDerivedToBase: case CastExpr::CK_DerivedToBase: { const RecordType *DerivedClassTy = E->getType()->getAs<PointerType>()->getPointeeType()->getAs<RecordType>(); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index e232230db7..0980710b3d 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1461,7 +1461,7 @@ Sema::PerformObjectMemberConversion(Expr *&From, if (PointerConversions) QType = Context.getPointerType(QType); - ImpCastExprToType(From, QType, CastExpr::CK_DerivedToBase, + ImpCastExprToType(From, QType, CastExpr::CK_UncheckedDerivedToBase, /*isLvalue*/ !PointerConversions); FromType = QType; @@ -1497,7 +1497,7 @@ Sema::PerformObjectMemberConversion(Expr *&From, QualType UType = URecordType; if (PointerConversions) UType = Context.getPointerType(UType); - ImpCastExprToType(From, UType, CastExpr::CK_DerivedToBase, + ImpCastExprToType(From, UType, CastExpr::CK_UncheckedDerivedToBase, /*isLvalue*/ !PointerConversions); FromType = UType; FromRecordType = URecordType; @@ -1517,8 +1517,8 @@ Sema::PerformObjectMemberConversion(Expr *&From, // FIXME: isLvalue should be !PointerConversions here, but codegen // does very silly things. - ImpCastExprToType(From, DestType, CastExpr::CK_DerivedToBase, - /*isLvalue=*/ true); + ImpCastExprToType(From, DestType, CastExpr::CK_UncheckedDerivedToBase, + /*isLvalue=*/ !PointerConversions); return false; } diff --git a/test/CodeGenCXX/member-expressions.cpp b/test/CodeGenCXX/member-expressions.cpp index 720a9a70d0..d9fb3940b0 100644 --- a/test/CodeGenCXX/member-expressions.cpp +++ b/test/CodeGenCXX/member-expressions.cpp @@ -44,3 +44,43 @@ int f() { return A().foo(); } } + +namespace test4 { + struct A { + int x; + }; + struct B { + int x; + void foo(); + }; + struct C : A, B { + }; + + extern C *c_ptr; + + // CHECK: define i32 @_ZN5test44testEv() + int test() { + // CHECK: load {{.*}} @_ZN5test45c_ptrE + // CHECK-NEXT: bitcast + // CHECK-NEXT: getelementptr + // CHECK-NEXT: bitcast + // CHECK-NEXT: call void @_ZN5test41B3fooEv + c_ptr->B::foo(); + + // CHECK: load {{.*}} @_ZN5test45c_ptrE + // CHECK-NEXT: bitcast + // CHECK-NEXT: getelementptr + // CHECK-NEXT: bitcast + // CHECK-NEXT: getelementptr + // CHECK-NEXT: store i32 5 + c_ptr->B::x = 5; + + // CHECK: load {{.*}} @_ZN5test45c_ptrE + // CHECK-NEXT: bitcast + // CHECK-NEXT: getelementptr + // CHECK-NEXT: bitcast + // CHECK-NEXT: getelementptr + // CHECK-NEXT: load i32* + return c_ptr->B::x; + } +} |