aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/CGClass.cpp2
-rw-r--r--lib/CodeGen/CGExpr.cpp27
-rw-r--r--lib/CodeGen/CGExprScalar.cpp10
-rw-r--r--lib/CodeGen/CodeGenFunction.h8
4 files changed, 42 insertions, 5 deletions
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 4e4acc8f12..d8474691bd 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -232,7 +232,7 @@ CodeGenFunction::GetAddressOfDerivedClass(llvm::Value *Value,
QualType DerivedTy =
getContext().getCanonicalType(getContext().getTagDeclType(Derived));
llvm::Type *DerivedPtrTy = ConvertType(DerivedTy)->getPointerTo();
-
+
llvm::Value *NonVirtualOffset =
CGM.GetNonVirtualBaseClassOffset(Derived, PathBegin, PathEnd);
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 41518fb11b..ba400b8a60 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -501,11 +501,22 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
return;
llvm::Value *Cond = 0;
+ llvm::BasicBlock *Done = 0;
if (SanOpts->Null) {
// The glvalue must not be an empty glvalue.
Cond = Builder.CreateICmpNE(
Address, llvm::Constant::getNullValue(Address->getType()));
+
+ if (TCK == TCK_DowncastPointer) {
+ // When performing a pointer downcast, it's OK if the value is null.
+ // Skip the remaining checks in that case.
+ Done = createBasicBlock("null");
+ llvm::BasicBlock *Rest = createBasicBlock("not.null");
+ Builder.CreateCondBr(Cond, Rest, Done);
+ EmitBlock(Rest);
+ Cond = 0;
+ }
}
if (SanOpts->ObjectSize && !Ty->isIncompleteType()) {
@@ -561,7 +572,8 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
// or call a non-static member function
CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
if (SanOpts->Vptr &&
- (TCK == TCK_MemberAccess || TCK == TCK_MemberCall) &&
+ (TCK == TCK_MemberAccess || TCK == TCK_MemberCall ||
+ TCK == TCK_DowncastPointer || TCK == TCK_DowncastReference) &&
RD && RD->hasDefinition() && RD->isDynamicClass()) {
// Compute a hash of the mangled name of the type.
//
@@ -611,6 +623,11 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
"dynamic_type_cache_miss", StaticData, DynamicData,
CRK_AlwaysRecoverable);
}
+
+ if (Done) {
+ Builder.CreateBr(Done);
+ EmitBlock(Done);
+ }
}
@@ -2638,7 +2655,13 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
cast<CXXRecordDecl>(DerivedClassTy->getDecl());
LValue LV = EmitLValue(E->getSubExpr());
-
+
+ // C++11 [expr.static.cast]p2: Behavior is undefined if a downcast is
+ // performed and the object is not of the derived type.
+ if (SanitizePerformTypeCheck)
+ EmitTypeCheck(TCK_DowncastReference, E->getExprLoc(),
+ LV.getAddress(), E->getType());
+
// Perform the base-to-derived conversion
llvm::Value *Derived =
GetAddressOfDerivedClass(LV.getAddress(), DerivedClassDecl,
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index 49494be901..7b86c04e8a 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -1220,7 +1220,15 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
const CXXRecordDecl *DerivedClassDecl = DestTy->getPointeeCXXRecordDecl();
assert(DerivedClassDecl && "BaseToDerived arg isn't a C++ object pointer!");
- return CGF.GetAddressOfDerivedClass(Visit(E), DerivedClassDecl,
+ llvm::Value *V = Visit(E);
+
+ // C++11 [expr.static.cast]p11: Behavior is undefined if a downcast is
+ // performed and the object is not of the derived type.
+ if (CGF.SanitizePerformTypeCheck)
+ CGF.EmitTypeCheck(CodeGenFunction::TCK_DowncastPointer, CE->getExprLoc(),
+ V, DestTy->getPointeeType());
+
+ return CGF.GetAddressOfDerivedClass(V, DerivedClassDecl,
CE->path_begin(), CE->path_end(),
ShouldNullCheckClassCastValue(CE));
}
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index ea5e8733d6..e85c23e217 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -1895,7 +1895,13 @@ public:
/// Must be an object within its lifetime.
TCK_MemberCall,
/// Checking the 'this' pointer for a constructor call.
- TCK_ConstructorCall
+ TCK_ConstructorCall,
+ /// Checking the operand of a static_cast to a derived pointer type. Must be
+ /// null or an object within its lifetime.
+ TCK_DowncastPointer,
+ /// Checking the operand of a static_cast to a derived reference type. Must
+ /// be an object within its lifetime.
+ TCK_DowncastReference
};
/// \brief Emit a check that \p V is the address of storage of the