Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -858,6 +858,7 @@ def fstruct_path_tbaa : Flag<["-"], "fstruct-path-tbaa">, Group; def fno_struct_path_tbaa : Flag<["-"], "fno-struct-path-tbaa">, Group; def fno_strict_enums : Flag<["-"], "fno-strict-enums">, Group; +def fno_strict_vptrs: Flag<["-"], "fno-strict-vptrs">, Group, Flags<[CC1Option]>; def fno_strict_overflow : Flag<["-"], "fno-strict-overflow">, Group; def fno_threadsafe_statics : Flag<["-"], "fno-threadsafe-statics">, Group, Flags<[CC1Option]>, HelpText<"Do not emit code to make initialization of local statics thread safe">; @@ -986,6 +987,7 @@ def fstrict_enums : Flag<["-"], "fstrict-enums">, Group, Flags<[CC1Option]>, HelpText<"Enable optimizations based on the strict definition of an enum's " "value range">; +def fstrict_vptrs: Flag<["-"], "fstrict-vptrs">, Group, Flags<[CC1Option]>; def fstrict_overflow : Flag<["-"], "fstrict-overflow">, Group; def fsyntax_only : Flag<["-"], "fsyntax-only">, Flags<[DriverOption,CoreOption,CC1Option]>, Group; Index: include/clang/Frontend/CodeGenOptions.def =================================================================== --- include/clang/Frontend/CodeGenOptions.def +++ include/clang/Frontend/CodeGenOptions.def @@ -132,6 +132,7 @@ CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled. CODEGENOPT(SoftFloat , 1, 0) ///< -soft-float. CODEGENOPT(StrictEnums , 1, 0) ///< Optimize based on strict enum definition. +CODEGENOPT(StrictVPtrs , 1, 0) CODEGENOPT(TimePasses , 1, 0) ///< Set when -ftime-report is enabled. CODEGENOPT(UnitAtATime , 1, 1) ///< Unused. For mirroring GCC optimization ///< selection. Index: lib/CodeGen/CGClass.cpp =================================================================== --- lib/CodeGen/CGClass.cpp +++ lib/CodeGen/CGClass.cpp @@ -1253,10 +1253,11 @@ CGM.getCXXABI().EmitCtorCompleteObjectHandler(*this, ClassDecl); assert(BaseCtorContinueBB); } - + bool BaseVPtrsInitialized = false; // Virtual base initializers first. for (; B != E && (*B)->isBaseInitializer() && (*B)->isBaseVirtual(); B++) { EmitBaseInitializer(*this, ClassDecl, *B, CtorType); + BaseVPtrsInitialized = true; } if (BaseCtorContinueBB) { @@ -1269,8 +1270,14 @@ for (; B != E && (*B)->isBaseInitializer(); B++) { assert(!(*B)->isBaseVirtual()); EmitBaseInitializer(*this, ClassDecl, *B, CtorType); + BaseVPtrsInitialized = true; } + // Pointer to this requires to be passed through invariant.group.barrier + // only if we've initilized any base vptrs. + if (CGM.getCodeGenOpts().StrictVPtrs && BaseVPtrsInitialized) + CXXThisValue = Builder.CreateInvariantGroupBarrier(LoadCXXThis()); + InitializeVTablePointers(ClassDecl); // And finally, initialize class members. @@ -1476,8 +1483,13 @@ EnterDtorCleanups(Dtor, Dtor_Base); // Initialize the vtable pointers before entering the body. - if (!CanSkipVTablePointerInitialization(getContext(), Dtor)) - InitializeVTablePointers(Dtor->getParent()); + if (!CanSkipVTablePointerInitialization(getContext(), Dtor)) { + // Inserting llvm.invariant.group.barrier intrinsic before base vptrs + // initialization to stop propagating previous vptr value. + if (CGM.getCodeGenOpts().StrictVPtrs) + CXXThisValue = Builder.CreateInvariantGroupBarrier(LoadCXXThis()); + InitializeVTablePointers(Dtor->getParent()); + } if (isTryBody) EmitStmt(cast(Body)->getTryBlock()); Index: lib/CodeGen/CGExprCXX.cpp =================================================================== --- lib/CodeGen/CGExprCXX.cpp +++ lib/CodeGen/CGExprCXX.cpp @@ -1354,6 +1354,11 @@ llvm::Type *elementPtrTy = elementTy->getPointerTo(AS); llvm::Value *result = Builder.CreateBitCast(allocation, elementPtrTy); + // Passing pointer through invariant.group.barrier to avoid propagation of + // vptrs information which may be included in previous type. + if (CGM.getCodeGenOpts().StrictVPtrs) + result = Builder.CreateInvariantGroupBarrier(result); + EmitNewInitializer(*this, E, allocType, elementTy, result, numElements, allocSizeWithoutCookie); if (E->isArray()) { Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -3368,6 +3368,9 @@ if (Args.hasFlag(options::OPT_fstrict_enums, options::OPT_fno_strict_enums, false)) CmdArgs.push_back("-fstrict-enums"); + if (Args.hasFlag(options::OPT_fstrict_vptrs, options::OPT_fno_strict_vptrs, + false)) + CmdArgs.push_back("-fstrict-vptrs"); if (!Args.hasFlag(options::OPT_foptimize_sibling_calls, options::OPT_fno_optimize_sibling_calls)) CmdArgs.push_back("-mdisable-tail-calls"); Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -493,6 +493,7 @@ Opts.NoDwarfDirectoryAsm = Args.hasArg(OPT_fno_dwarf_directory_asm); Opts.SoftFloat = Args.hasArg(OPT_msoft_float); Opts.StrictEnums = Args.hasArg(OPT_fstrict_enums); + Opts.StrictVPtrs = Args.hasArg(OPT_fstrict_vptrs); Opts.UnsafeFPMath = Args.hasArg(OPT_menable_unsafe_fp_math) || Args.hasArg(OPT_cl_unsafe_math_optimizations) || Args.hasArg(OPT_cl_fast_relaxed_math); Index: test/CodeGenCXX/virtual-base-ctor.cpp =================================================================== --- test/CodeGenCXX/virtual-base-ctor.cpp +++ test/CodeGenCXX/virtual-base-ctor.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - -O2 | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - -O2 -fstrict-vptrs | FileCheck %s struct B; extern B x;