Index: lib/CodeGen/CGClass.cpp =================================================================== --- lib/CodeGen/CGClass.cpp +++ lib/CodeGen/CGClass.cpp @@ -2068,11 +2068,10 @@ SourceLocation Loc) { const CXXRecordDecl *ClassDecl = D->getParent(); - // C++11 [class.mfct.non-static]p2: - // If a non-static member function of a class X is called for an object that - // is not of type X, or of a type derived from X, the behavior is undefined. - EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, Loc, - This.getPointer(), getContext().getRecordType(ClassDecl)); + PointerChecksRAII PC(this); + if (PC.shouldEmitChecks()) + EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, Loc, + This.getPointer(), getContext().getRecordType(ClassDecl)); if (D->isTrivial() && D->isDefaultConstructor()) { assert(Args.size() == 1 && "trivial default ctor with args"); Index: lib/CodeGen/CGExprCXX.cpp =================================================================== --- lib/CodeGen/CGExprCXX.cpp +++ lib/CodeGen/CGExprCXX.cpp @@ -1271,6 +1271,15 @@ Address NewPtr, llvm::Value *NumElements, llvm::Value *AllocSizeWithoutCookie) { ApplyDebugLocation DL(CGF, E); + + // Emit sanitizer checks for pointer value now, so that in the case of an + // array it was checked only once and not at each constructor call. + CodeGenFunction::PointerChecksRAII PC(&CGF); + if (PC.shouldEmitChecks()) + CGF.EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, + E->getAllocatedTypeSourceInfo()->getTypeLoc().getBeginLoc(), + NewPtr.getPointer(), ElementType); + if (E->isArray()) CGF.EmitNewArrayInitializer(E, ElementType, ElementTy, NewPtr, NumElements, AllocSizeWithoutCookie); Index: lib/CodeGen/CodeGenFunction.h =================================================================== --- lib/CodeGen/CodeGenFunction.h +++ lib/CodeGen/CodeGenFunction.h @@ -376,6 +376,25 @@ ~SanitizerScope(); }; + /// True if sanitizer checks for current pointer value are generated. + bool PointerChecksAreEmitted = false; + + /// RAII object to track generation of sanitizer pointer checks. + class PointerChecksRAII { + CodeGenFunction *CGF; + bool PrevValue; + public: + PointerChecksRAII(CodeGenFunction *CGF) + : CGF(CGF), PrevValue(CGF->PointerChecksAreEmitted) { + CGF->PointerChecksAreEmitted = true; + } + ~PointerChecksRAII() { + if (!PrevValue) + CGF->PointerChecksAreEmitted = false; + } + bool shouldEmitChecks() const { return !PrevValue; } + }; + /// In C++, whether we are code generating a thunk. This controls whether we /// should emit cleanups. bool CurFuncIsThunk = false; Index: test/CodeGenCXX/ubsan-new-checks.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/ubsan-new-checks.cpp @@ -0,0 +1,54 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++11 -S -emit-llvm -fsanitize=alignment %s -o - | FileCheck %s + +struct alignas(32) S1 { + int x; + S1(); +}; + +struct alignas(32) S2 { + int x; +}; + +typedef __attribute__((ext_vector_type(2), aligned(32))) float float32x2_t; + +S1 *func_01() { + // CHECK-LABEL: define {{.*}} @_Z7func_01v + // CHECK: and i64 %{{.*}}, 31, !nosanitize + // CHECK: icmp eq i64 %{{.*}}, 0, !nosanitize + // CHECK: call void @_ZN2S1C1Ev( + // CHECK-NOT: and i64 %{{.*}}, 31, !nosanitize + // CHECK-NOT: icmp eq i64 %{{.*}}, 0, !nosanitize + return new S1[20]; +} + +S2 *func_02() { + // CHECK-LABEL: define {{.*}} @_Z7func_02v + // CHECK: and i64 %{{.*}}, 31, !nosanitize + // CHECK: icmp eq i64 %{{.*}}, 0, !nosanitize + return new S2; +} + +S2 *func_03() { + // CHECK-LABEL: define {{.*}} @_Z7func_03v + // CHECK: and i64 %{{.*}}, 31, !nosanitize + // CHECK: icmp eq i64 %{{.*}}, 0, !nosanitize + // CHECK-NOT: and i64 %{{.*}}, 31, !nosanitize + // CHECK-NOT: icmp eq i64 %{{.*}}, 0, !nosanitize + return new S2[20]; +} + +float32x2_t *func_04() { + // CHECK-LABEL: define {{.*}} @_Z7func_04v + // CHECK: and i64 %{{.*}}, 31, !nosanitize + // CHECK: icmp eq i64 %{{.*}}, 0, !nosanitize + return new float32x2_t; +} + +float32x2_t *func_05() { + // CHECK-LABEL: define {{.*}} @_Z7func_05v + // CHECK: and i64 %{{.*}}, 31, !nosanitize + // CHECK: icmp eq i64 %{{.*}}, 0, !nosanitize + // CHECK-NOT: and i64 %{{.*}}, 31, !nosanitize + // CHECK-NOT: icmp eq i64 %{{.*}}, 0, !nosanitize + return new float32x2_t[20]; +}