// down to whether we know it's a complete object or not.
auto &Layout = CGF.getContext().getASTRecordLayout(MD->getParent());
if (MD->getParent()->getNumVBases() == 0 || // avoid vcall in common case
- MD->getParent()->hasAttr<FinalAttr>() ||
- !isThisCompleteObject(CGF.CurGD)) {
+ MD->getParent()->isEffectivelyFinal() ||
+ isThisCompleteObject(CGF.CurGD)) {
CGF.CXXABIThisAlignment = Layout.getAlignment();
} else {
CGF.CXXABIThisAlignment = Layout.getNonVirtualAlignment();
MD->getParent()->getLambdaCaptureDefault() == LCD_None)
SkippedChecks.set(SanitizerKind::Null, true);
- EmitTypeCheck(isa<CXXConstructorDecl>(MD) ? TCK_ConstructorCall
- : TCK_MemberCall,
- Loc, CXXABIThisValue, ThisTy,
- getContext().getTypeAlignInChars(ThisTy->getPointeeType()),
- SkippedChecks);
+ EmitTypeCheck(
+ isa<CXXConstructorDecl>(MD) ? TCK_ConstructorCall : TCK_MemberCall,
+ Loc, CXXABIThisValue, ThisTy, CXXABIThisAlignment, SkippedChecks);
}
}
// Note: C is laid out such that offsetof(C, B) + sizeof(B) extends outside
// the C object.
struct alignas(16) A { void *a1, *a2; };
- struct B : virtual A { void *b; };
- struct C : virtual A, virtual B {};
+ struct B : virtual A { void *b; void* g(); };
+ struct C : virtual A, virtual B { };
// CHECK-LABEL: define {{.*}} @_ZN15VBaseObjectSize1fERNS_1BE(
B &f(B &b) {
// Size check: check for nvsize(B) == 16 (do not require size(B) == 32)
// CHECK: and i64 [[PTRTOINT]], 7,
return b;
}
+
+ // CHECK-LABEL: define {{.*}} @_ZN15VBaseObjectSize1B1gEv(
+ void *B::g() {
+ // Ensure that the check on the "this" pointer also uses the proper
+ // alignment. We should be using nvalign(B) == 8, not 16.
+ // CHECK: [[PTRTOINT:%.+]] = ptrtoint {{.*}} to i64,
+ // CHECK: and i64 [[PTRTOINT]], 7
+ return nullptr;
+ }
}
namespace FunctionSanitizerVirtualCalls {