Vendor import of llvm-project branch release/13.x llvmorg-13.0.0-rc4-0-gd7b669b3a303.
This commit is contained in:
parent
392ac508a0
commit
3f25e997d9
@ -298,8 +298,8 @@ class alignas(8) InitializedEntity {
|
||||
|
||||
/// Create the initialization entity for the result of a function.
|
||||
static InitializedEntity InitializeResult(SourceLocation ReturnLoc,
|
||||
QualType Type, bool NRVO) {
|
||||
return InitializedEntity(EK_Result, ReturnLoc, Type, NRVO);
|
||||
QualType Type) {
|
||||
return InitializedEntity(EK_Result, ReturnLoc, Type);
|
||||
}
|
||||
|
||||
static InitializedEntity InitializeStmtExprResult(SourceLocation ReturnLoc,
|
||||
@ -308,20 +308,20 @@ class alignas(8) InitializedEntity {
|
||||
}
|
||||
|
||||
static InitializedEntity InitializeBlock(SourceLocation BlockVarLoc,
|
||||
QualType Type, bool NRVO) {
|
||||
return InitializedEntity(EK_BlockElement, BlockVarLoc, Type, NRVO);
|
||||
QualType Type) {
|
||||
return InitializedEntity(EK_BlockElement, BlockVarLoc, Type);
|
||||
}
|
||||
|
||||
static InitializedEntity InitializeLambdaToBlock(SourceLocation BlockVarLoc,
|
||||
QualType Type, bool NRVO) {
|
||||
QualType Type) {
|
||||
return InitializedEntity(EK_LambdaToBlockConversionBlockElement,
|
||||
BlockVarLoc, Type, NRVO);
|
||||
BlockVarLoc, Type);
|
||||
}
|
||||
|
||||
/// Create the initialization entity for an exception object.
|
||||
static InitializedEntity InitializeException(SourceLocation ThrowLoc,
|
||||
QualType Type, bool NRVO) {
|
||||
return InitializedEntity(EK_Exception, ThrowLoc, Type, NRVO);
|
||||
QualType Type) {
|
||||
return InitializedEntity(EK_Exception, ThrowLoc, Type);
|
||||
}
|
||||
|
||||
/// Create the initialization entity for an object allocated via new.
|
||||
|
@ -9931,10 +9931,19 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E,
|
||||
return false;
|
||||
|
||||
// Avoid materializing a temporary for an elidable copy/move constructor.
|
||||
if (E->isElidable() && !ZeroInit)
|
||||
if (const MaterializeTemporaryExpr *ME
|
||||
= dyn_cast<MaterializeTemporaryExpr>(E->getArg(0)))
|
||||
if (E->isElidable() && !ZeroInit) {
|
||||
// FIXME: This only handles the simplest case, where the source object
|
||||
// is passed directly as the first argument to the constructor.
|
||||
// This should also handle stepping though implicit casts and
|
||||
// and conversion sequences which involve two steps, with a
|
||||
// conversion operator followed by a converting constructor.
|
||||
const Expr *SrcObj = E->getArg(0);
|
||||
assert(SrcObj->isTemporaryObject(Info.Ctx, FD->getParent()));
|
||||
assert(Info.Ctx.hasSameUnqualifiedType(E->getType(), SrcObj->getType()));
|
||||
if (const MaterializeTemporaryExpr *ME =
|
||||
dyn_cast<MaterializeTemporaryExpr>(SrcObj))
|
||||
return Visit(ME->getSubExpr());
|
||||
}
|
||||
|
||||
if (ZeroInit && !ZeroInitialization(E, T))
|
||||
return false;
|
||||
|
@ -1050,7 +1050,7 @@ class ThreadSafetyAnalyzer {
|
||||
const CFGBlock* PredBlock,
|
||||
const CFGBlock *CurrBlock);
|
||||
|
||||
bool join(const FactEntry &a, const FactEntry &b);
|
||||
bool join(const FactEntry &a, const FactEntry &b, bool CanModify);
|
||||
|
||||
void intersectAndWarn(FactSet &EntrySet, const FactSet &ExitSet,
|
||||
SourceLocation JoinLoc, LockErrorKind EntryLEK,
|
||||
@ -2188,25 +2188,28 @@ void BuildLockset::VisitDeclStmt(const DeclStmt *S) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Given two facts merging on a join point, decide whether to warn and which
|
||||
/// one to keep.
|
||||
/// Given two facts merging on a join point, possibly warn and decide whether to
|
||||
/// keep or replace.
|
||||
///
|
||||
/// \return false if we should keep \p A, true if we should keep \p B.
|
||||
bool ThreadSafetyAnalyzer::join(const FactEntry &A, const FactEntry &B) {
|
||||
/// \param CanModify Whether we can replace \p A by \p B.
|
||||
/// \return false if we should keep \p A, true if we should take \p B.
|
||||
bool ThreadSafetyAnalyzer::join(const FactEntry &A, const FactEntry &B,
|
||||
bool CanModify) {
|
||||
if (A.kind() != B.kind()) {
|
||||
// For managed capabilities, the destructor should unlock in the right mode
|
||||
// anyway. For asserted capabilities no unlocking is needed.
|
||||
if ((A.managed() || A.asserted()) && (B.managed() || B.asserted())) {
|
||||
// The shared capability subsumes the exclusive capability.
|
||||
return B.kind() == LK_Shared;
|
||||
} else {
|
||||
Handler.handleExclusiveAndShared("mutex", B.toString(), B.loc(), A.loc());
|
||||
// Take the exclusive capability to reduce further warnings.
|
||||
return B.kind() == LK_Exclusive;
|
||||
// The shared capability subsumes the exclusive capability, if possible.
|
||||
bool ShouldTakeB = B.kind() == LK_Shared;
|
||||
if (CanModify || !ShouldTakeB)
|
||||
return ShouldTakeB;
|
||||
}
|
||||
Handler.handleExclusiveAndShared("mutex", B.toString(), B.loc(), A.loc());
|
||||
// Take the exclusive capability to reduce further warnings.
|
||||
return CanModify && B.kind() == LK_Exclusive;
|
||||
} else {
|
||||
// The non-asserted capability is the one we want to track.
|
||||
return A.asserted() && !B.asserted();
|
||||
return CanModify && A.asserted() && !B.asserted();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2237,8 +2240,8 @@ void ThreadSafetyAnalyzer::intersectAndWarn(FactSet &EntrySet,
|
||||
|
||||
FactSet::iterator EntryIt = EntrySet.findLockIter(FactMan, ExitFact);
|
||||
if (EntryIt != EntrySet.end()) {
|
||||
if (join(FactMan[*EntryIt], ExitFact) &&
|
||||
EntryLEK == LEK_LockedSomePredecessors)
|
||||
if (join(FactMan[*EntryIt], ExitFact,
|
||||
EntryLEK != LEK_LockedSomeLoopIterations))
|
||||
*EntryIt = Fact;
|
||||
} else if (!ExitFact.managed()) {
|
||||
ExitFact.handleRemovalFromIntersection(ExitSet, FactMan, JoinLoc,
|
||||
|
@ -609,15 +609,18 @@ CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E,
|
||||
return;
|
||||
|
||||
// Elide the constructor if we're constructing from a temporary.
|
||||
// The temporary check is required because Sema sets this on NRVO
|
||||
// returns.
|
||||
if (getLangOpts().ElideConstructors && E->isElidable()) {
|
||||
assert(getContext().hasSameUnqualifiedType(E->getType(),
|
||||
E->getArg(0)->getType()));
|
||||
if (E->getArg(0)->isTemporaryObject(getContext(), CD->getParent())) {
|
||||
EmitAggExpr(E->getArg(0), Dest);
|
||||
return;
|
||||
}
|
||||
// FIXME: This only handles the simplest case, where the source object
|
||||
// is passed directly as the first argument to the constructor.
|
||||
// This should also handle stepping though implicit casts and
|
||||
// conversion sequences which involve two steps, with a
|
||||
// conversion operator followed by a converting constructor.
|
||||
const Expr *SrcObj = E->getArg(0);
|
||||
assert(SrcObj->isTemporaryObject(getContext(), CD->getParent()));
|
||||
assert(
|
||||
getContext().hasSameUnqualifiedType(E->getType(), SrcObj->getType()));
|
||||
EmitAggExpr(SrcObj, Dest);
|
||||
return;
|
||||
}
|
||||
|
||||
if (const ArrayType *arrayType
|
||||
|
@ -2010,7 +2010,7 @@ static void checkEscapingByref(VarDecl *VD, Sema &S) {
|
||||
Expr *VarRef =
|
||||
new (S.Context) DeclRefExpr(S.Context, VD, false, T, VK_LValue, Loc);
|
||||
ExprResult Result;
|
||||
auto IE = InitializedEntity::InitializeBlock(Loc, T, false);
|
||||
auto IE = InitializedEntity::InitializeBlock(Loc, T);
|
||||
if (S.getLangOpts().CPlusPlus2b) {
|
||||
auto *E = ImplicitCastExpr::Create(S.Context, T, CK_NoOp, VarRef, nullptr,
|
||||
VK_XValue, FPOptionsOverride());
|
||||
|
@ -1533,7 +1533,7 @@ bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() {
|
||||
if (GroType->isVoidType()) {
|
||||
// Trigger a nice error message.
|
||||
InitializedEntity Entity =
|
||||
InitializedEntity::InitializeResult(Loc, FnRetType, false);
|
||||
InitializedEntity::InitializeResult(Loc, FnRetType);
|
||||
S.PerformCopyInitialization(Entity, SourceLocation(), ReturnValue);
|
||||
noteMemberDeclaredHere(S, ReturnValue, Fn);
|
||||
return false;
|
||||
|
@ -15262,8 +15262,17 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
|
||||
// can be omitted by constructing the temporary object
|
||||
// directly into the target of the omitted copy/move
|
||||
if (ConstructKind == CXXConstructExpr::CK_Complete && Constructor &&
|
||||
// FIXME: Converting constructors should also be accepted.
|
||||
// But to fix this, the logic that digs down into a CXXConstructExpr
|
||||
// to find the source object needs to handle it.
|
||||
// Right now it assumes the source object is passed directly as the
|
||||
// first argument.
|
||||
Constructor->isCopyOrMoveConstructor() && hasOneRealArgument(ExprArgs)) {
|
||||
Expr *SubExpr = ExprArgs[0];
|
||||
// FIXME: Per above, this is also incorrect if we want to accept
|
||||
// converting constructors, as isTemporaryObject will
|
||||
// reject temporaries with different type from the
|
||||
// CXXRecord itself.
|
||||
Elidable = SubExpr->isTemporaryObject(
|
||||
Context, cast<CXXRecordDecl>(FoundDecl->getDeclContext()));
|
||||
}
|
||||
|
@ -15683,7 +15683,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
|
||||
if (!Result.isInvalid()) {
|
||||
Result = PerformCopyInitialization(
|
||||
InitializedEntity::InitializeBlock(Var->getLocation(),
|
||||
Cap.getCaptureType(), false),
|
||||
Cap.getCaptureType()),
|
||||
Loc, Result.get());
|
||||
}
|
||||
|
||||
|
@ -893,9 +893,8 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex,
|
||||
if (CheckCXXThrowOperand(OpLoc, ExceptionObjectTy, Ex))
|
||||
return ExprError();
|
||||
|
||||
InitializedEntity Entity = InitializedEntity::InitializeException(
|
||||
OpLoc, ExceptionObjectTy,
|
||||
/*NRVO=*/NRInfo.isCopyElidable());
|
||||
InitializedEntity Entity =
|
||||
InitializedEntity::InitializeException(OpLoc, ExceptionObjectTy);
|
||||
ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRInfo, Ex);
|
||||
if (Res.isInvalid())
|
||||
return ExprError();
|
||||
|
@ -1975,8 +1975,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
|
||||
CallOperator->markUsed(Context);
|
||||
|
||||
ExprResult Init = PerformCopyInitialization(
|
||||
InitializedEntity::InitializeLambdaToBlock(ConvLocation, Src->getType(),
|
||||
/*NRVO=*/false),
|
||||
InitializedEntity::InitializeLambdaToBlock(ConvLocation, Src->getType()),
|
||||
CurrentLocation, Src);
|
||||
if (!Init.isInvalid())
|
||||
Init = ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false);
|
||||
|
@ -1467,8 +1467,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
|
||||
LoadSelfExpr, true, true);
|
||||
ExprResult Res = PerformCopyInitialization(
|
||||
InitializedEntity::InitializeResult(PropertyDiagLoc,
|
||||
getterMethod->getReturnType(),
|
||||
/*NRVO=*/false),
|
||||
getterMethod->getReturnType()),
|
||||
PropertyDiagLoc, IvarRefExpr);
|
||||
if (!Res.isInvalid()) {
|
||||
Expr *ResExpr = Res.getAs<Expr>();
|
||||
|
@ -3653,8 +3653,8 @@ StmtResult Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc,
|
||||
|
||||
// In C++ the return statement is handled via a copy initialization.
|
||||
// the C version of which boils down to CheckSingleAssignmentConstraints.
|
||||
InitializedEntity Entity = InitializedEntity::InitializeResult(
|
||||
ReturnLoc, FnRetType, NRVOCandidate != nullptr);
|
||||
InitializedEntity Entity =
|
||||
InitializedEntity::InitializeResult(ReturnLoc, FnRetType);
|
||||
ExprResult Res = PerformMoveOrCopyInitialization(
|
||||
Entity, NRInfo, RetValExp, SupressSimplerImplicitMoves);
|
||||
if (Res.isInvalid()) {
|
||||
@ -4085,8 +4085,8 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
|
||||
// the C version of which boils down to CheckSingleAssignmentConstraints.
|
||||
if (!HasDependentReturnType && !RetValExp->isTypeDependent()) {
|
||||
// we have a non-void function with an expression, continue checking
|
||||
InitializedEntity Entity = InitializedEntity::InitializeResult(
|
||||
ReturnLoc, RetType, NRVOCandidate != nullptr);
|
||||
InitializedEntity Entity =
|
||||
InitializedEntity::InitializeResult(ReturnLoc, RetType);
|
||||
ExprResult Res = PerformMoveOrCopyInitialization(
|
||||
Entity, NRInfo, RetValExp, SupressSimplerImplicitMoves);
|
||||
if (Res.isInvalid()) {
|
||||
|
@ -1301,6 +1301,7 @@ static AArch64CC::CondCode changeICMPPredToAArch64CC(CmpInst::Predicate P) {
|
||||
static Register getTestBitReg(Register Reg, uint64_t &Bit, bool &Invert,
|
||||
MachineRegisterInfo &MRI) {
|
||||
assert(Reg.isValid() && "Expected valid register!");
|
||||
bool HasZext = false;
|
||||
while (MachineInstr *MI = getDefIgnoringCopies(Reg, MRI)) {
|
||||
unsigned Opc = MI->getOpcode();
|
||||
|
||||
@ -1314,6 +1315,9 @@ static Register getTestBitReg(Register Reg, uint64_t &Bit, bool &Invert,
|
||||
// on the truncated x is the same as the bit number on x.
|
||||
if (Opc == TargetOpcode::G_ANYEXT || Opc == TargetOpcode::G_ZEXT ||
|
||||
Opc == TargetOpcode::G_TRUNC) {
|
||||
if (Opc == TargetOpcode::G_ZEXT)
|
||||
HasZext = true;
|
||||
|
||||
Register NextReg = MI->getOperand(1).getReg();
|
||||
// Did we find something worth folding?
|
||||
if (!NextReg.isValid() || !MRI.hasOneNonDBGUse(NextReg))
|
||||
@ -1342,8 +1346,12 @@ static Register getTestBitReg(Register Reg, uint64_t &Bit, bool &Invert,
|
||||
std::swap(ConstantReg, TestReg);
|
||||
VRegAndVal = getConstantVRegValWithLookThrough(ConstantReg, MRI);
|
||||
}
|
||||
if (VRegAndVal)
|
||||
C = VRegAndVal->Value.getSExtValue();
|
||||
if (VRegAndVal) {
|
||||
if (HasZext)
|
||||
C = VRegAndVal->Value.getZExtValue();
|
||||
else
|
||||
C = VRegAndVal->Value.getSExtValue();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TargetOpcode::G_ASHR:
|
||||
|
@ -35823,7 +35823,7 @@ static SDValue combineX86ShuffleChain(ArrayRef<SDValue> Inputs, SDValue Root,
|
||||
|
||||
// See if the shuffle is a hidden identity shuffle - repeated args in HOPs
|
||||
// etc. can be simplified.
|
||||
if (VT1 == VT2 && VT1.getSizeInBits() == RootSizeInBits) {
|
||||
if (VT1 == VT2 && VT1.getSizeInBits() == RootSizeInBits && VT1.isVector()) {
|
||||
SmallVector<int> ScaledMask, IdentityMask;
|
||||
unsigned NumElts = VT1.getVectorNumElements();
|
||||
if (BaseMask.size() <= NumElts &&
|
||||
|
Loading…
Reference in New Issue
Block a user