summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CGClass.cpp33
-rw-r--r--clang/lib/CodeGen/CGExprCXX.cpp8
-rw-r--r--clang/lib/Driver/Tools.cpp4
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp1
4 files changed, 43 insertions, 3 deletions
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index 6c9f404eab2..4c46d56590b 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -1344,6 +1344,13 @@ namespace {
}
+static bool isInitializerOfDynamicClass(const CXXCtorInitializer *BaseInit) {
+ const Type *BaseType = BaseInit->getBaseClass();
+ const auto *BaseClassDecl =
+ cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl());
+ return BaseClassDecl->isDynamicClass();
+}
+
/// EmitCtorPrologue - This routine generates necessary code to initialize
/// base classes and non-static data members belonging to this constructor.
void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
@@ -1367,9 +1374,13 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
assert(BaseCtorContinueBB);
}
+ bool BaseVPtrsInitialized = false;
// Virtual base initializers first.
for (; B != E && (*B)->isBaseInitializer() && (*B)->isBaseVirtual(); B++) {
+ CXXCtorInitializer *BaseInit = *B;
EmitBaseInitializer(*this, ClassDecl, *B, CtorType);
+ BaseVPtrsInitialized |= BaseInitializerUsesThis(getContext(),
+ BaseInit->getInit());
}
if (BaseCtorContinueBB) {
@@ -1382,8 +1393,15 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
for (; B != E && (*B)->isBaseInitializer(); B++) {
assert(!(*B)->isBaseVirtual());
EmitBaseInitializer(*this, ClassDecl, *B, CtorType);
+ BaseVPtrsInitialized |= isInitializerOfDynamicClass(*B);
}
+ // Pointer to this requires to be passed through invariant.group.barrier
+ // only if we've initialized any base vptrs.
+ if (CGM.getCodeGenOpts().StrictVTablePointers &&
+ CGM.getCodeGenOpts().OptimizationLevel > 0 && BaseVPtrsInitialized)
+ CXXThisValue = Builder.CreateInvariantGroupBarrier(LoadCXXThis());
+
InitializeVTablePointers(ClassDecl);
// And finally, initialize class members.
@@ -1468,11 +1486,14 @@ FieldHasTrivialDestructorBody(ASTContext &Context,
/// any vtable pointers before calling this destructor.
static bool CanSkipVTablePointerInitialization(CodeGenFunction &CGF,
const CXXDestructorDecl *Dtor) {
+ const CXXRecordDecl *ClassDecl = Dtor->getParent();
+ if (!ClassDecl->isDynamicClass())
+ return true;
+
if (!Dtor->hasTrivialBody())
return false;
// Check the fields.
- const CXXRecordDecl *ClassDecl = Dtor->getParent();
for (const auto *Field : ClassDecl->fields())
if (!FieldHasTrivialDestructorBody(CGF.getContext(), Field))
return false;
@@ -1543,8 +1564,14 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
EnterDtorCleanups(Dtor, Dtor_Base);
// Initialize the vtable pointers before entering the body.
- if (!CanSkipVTablePointerInitialization(*this, Dtor))
- InitializeVTablePointers(Dtor->getParent());
+ if (!CanSkipVTablePointerInitialization(*this, Dtor)) {
+ // Insert the llvm.invariant.group.barrier intrinsic before initializing
+ // the vptrs to cancel any previous assumptions we might have made.
+ if (CGM.getCodeGenOpts().StrictVTablePointers &&
+ CGM.getCodeGenOpts().OptimizationLevel > 0)
+ CXXThisValue = Builder.CreateInvariantGroupBarrier(LoadCXXThis());
+ InitializeVTablePointers(Dtor->getParent());
+ }
if (isTryBody)
EmitStmt(cast<CXXTryStmt>(Body)->getTryBlock());
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index 8b060ce2874..1952282a07e 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -1381,6 +1381,14 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
llvm::Type *elementTy = ConvertTypeForMem(allocType);
Address result = Builder.CreateElementBitCast(allocation, elementTy);
+ // Passing pointer through invariant.group.barrier to avoid propagation of
+ // vptrs information which may be included in previous type.
+ if (CGM.getCodeGenOpts().StrictVTablePointers &&
+ CGM.getCodeGenOpts().OptimizationLevel > 0 &&
+ allocator->isReservedGlobalPlacementOperator())
+ result = Address(Builder.CreateInvariantGroupBarrier(result.getPointer()),
+ result.getAlignment());
+
EmitNewInitializer(*this, E, allocType, elementTy, result, numElements,
allocSizeWithoutCookie);
if (E->isArray()) {
diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp
index db29be1367c..755ea1b9b3a 100644
--- a/clang/lib/Driver/Tools.cpp
+++ b/clang/lib/Driver/Tools.cpp
@@ -3443,6 +3443,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasFlag(options::OPT_fstrict_enums, options::OPT_fno_strict_enums,
false))
CmdArgs.push_back("-fstrict-enums");
+ if (Args.hasFlag(options::OPT_fstrict_vtable_pointers,
+ options::OPT_fno_strict_vtable_pointers,
+ false))
+ CmdArgs.push_back("-fstrict-vtable-pointers");
if (!Args.hasFlag(options::OPT_foptimize_sibling_calls,
options::OPT_fno_optimize_sibling_calls))
CmdArgs.push_back("-mdisable-tail-calls");
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 7caa7095969..81a12caecee 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -494,6 +494,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.NoDwarfDirectoryAsm = Args.hasArg(OPT_fno_dwarf_directory_asm);
Opts.SoftFloat = Args.hasArg(OPT_msoft_float);
Opts.StrictEnums = Args.hasArg(OPT_fstrict_enums);
+ Opts.StrictVTablePointers = Args.hasArg(OPT_fstrict_vtable_pointers);
Opts.UnsafeFPMath = Args.hasArg(OPT_menable_unsafe_fp_math) ||
Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
Args.hasArg(OPT_cl_fast_relaxed_math);
OpenPOWER on IntegriCloud