Upgrade our copies of clang, llvm, lldb and compiler-rt to r311606 from
the upstream release_50 branch. As of this version, lib/msun's trig test should also work correctly again (see bug 220989 for more information). PR: 220989 MFC after: 2 months X-MFC-with: r321369
This commit is contained in:
parent
c41928d204
commit
b5e6330452
@ -18,11 +18,20 @@
|
||||
// }
|
||||
// }
|
||||
|
||||
#if defined(COMPILER_RT_ARMHF_TARGET)
|
||||
# define CONVERT_DCMP_ARGS_TO_DF2_ARGS \
|
||||
vmov d0, r0, r1 SEPARATOR \
|
||||
vmov d1, r2, r3
|
||||
#else
|
||||
# define CONVERT_DCMP_ARGS_TO_DF2_ARGS
|
||||
#endif
|
||||
|
||||
#define DEFINE_AEABI_DCMP(cond) \
|
||||
.syntax unified SEPARATOR \
|
||||
.p2align 2 SEPARATOR \
|
||||
DEFINE_COMPILERRT_FUNCTION(__aeabi_dcmp ## cond) \
|
||||
push { r4, lr } SEPARATOR \
|
||||
CONVERT_DCMP_ARGS_TO_DF2_ARGS SEPARATOR \
|
||||
bl SYMBOL_NAME(__ ## cond ## df2) SEPARATOR \
|
||||
cmp r0, #0 SEPARATOR \
|
||||
b ## cond 1f SEPARATOR \
|
||||
|
@ -18,11 +18,20 @@
|
||||
// }
|
||||
// }
|
||||
|
||||
#if defined(COMPILER_RT_ARMHF_TARGET)
|
||||
# define CONVERT_FCMP_ARGS_TO_SF2_ARGS \
|
||||
vmov s0, r0 SEPARATOR \
|
||||
vmov s1, r1
|
||||
#else
|
||||
# define CONVERT_FCMP_ARGS_TO_SF2_ARGS
|
||||
#endif
|
||||
|
||||
#define DEFINE_AEABI_FCMP(cond) \
|
||||
.syntax unified SEPARATOR \
|
||||
.p2align 2 SEPARATOR \
|
||||
DEFINE_COMPILERRT_FUNCTION(__aeabi_fcmp ## cond) \
|
||||
push { r4, lr } SEPARATOR \
|
||||
CONVERT_FCMP_ARGS_TO_SF2_ARGS SEPARATOR \
|
||||
bl SYMBOL_NAME(__ ## cond ## sf2) SEPARATOR \
|
||||
cmp r0, #0 SEPARATOR \
|
||||
b ## cond 1f SEPARATOR \
|
||||
|
@ -70,7 +70,7 @@ int SidelineThread::runSideline(void *Arg) {
|
||||
|
||||
// Set up a signal handler on an alternate stack for safety.
|
||||
InternalScopedBuffer<char> StackMap(SigAltStackSize);
|
||||
struct sigaltstack SigAltStack;
|
||||
stack_t SigAltStack;
|
||||
SigAltStack.ss_sp = StackMap.data();
|
||||
SigAltStack.ss_size = SigAltStackSize;
|
||||
SigAltStack.ss_flags = 0;
|
||||
|
@ -1,11 +1,11 @@
|
||||
//===- InstrProfilingNameVar.c - profile name variable setup --------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
/*===- InstrProfilingNameVar.c - profile name variable setup -------------===*\
|
||||
|*
|
||||
|* The LLVM Compiler Infrastructure
|
||||
|*
|
||||
|* This file is distributed under the University of Illinois Open Source
|
||||
|* License. See LICENSE.TXT for details.
|
||||
|*
|
||||
\*===----------------------------------------------------------------------===*/
|
||||
|
||||
#include "InstrProfiling.h"
|
||||
|
||||
|
@ -85,7 +85,10 @@ namespace ISD {
|
||||
|
||||
/// If N is a BUILD_VECTOR node whose elements are all the same constant or
|
||||
/// undefined, return true and return the constant value in \p SplatValue.
|
||||
bool isConstantSplatVector(const SDNode *N, APInt &SplatValue);
|
||||
/// This sets \p SplatValue to the smallest possible splat unless AllowShrink
|
||||
/// is set to false.
|
||||
bool isConstantSplatVector(const SDNode *N, APInt &SplatValue,
|
||||
bool AllowShrink = true);
|
||||
|
||||
/// Return true if the specified node is a BUILD_VECTOR where all of the
|
||||
/// elements are ~0 or undef.
|
||||
|
@ -627,6 +627,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
|
||||
SDValue ScalarizeVecOp_CONCAT_VECTORS(SDNode *N);
|
||||
SDValue ScalarizeVecOp_EXTRACT_VECTOR_ELT(SDNode *N);
|
||||
SDValue ScalarizeVecOp_VSELECT(SDNode *N);
|
||||
SDValue ScalarizeVecOp_VSETCC(SDNode *N);
|
||||
SDValue ScalarizeVecOp_STORE(StoreSDNode *N, unsigned OpNo);
|
||||
SDValue ScalarizeVecOp_FP_ROUND(SDNode *N, unsigned OpNo);
|
||||
|
||||
|
@ -484,6 +484,9 @@ bool DAGTypeLegalizer::ScalarizeVectorOperand(SDNode *N, unsigned OpNo) {
|
||||
case ISD::VSELECT:
|
||||
Res = ScalarizeVecOp_VSELECT(N);
|
||||
break;
|
||||
case ISD::SETCC:
|
||||
Res = ScalarizeVecOp_VSETCC(N);
|
||||
break;
|
||||
case ISD::STORE:
|
||||
Res = ScalarizeVecOp_STORE(cast<StoreSDNode>(N), OpNo);
|
||||
break;
|
||||
@ -560,6 +563,36 @@ SDValue DAGTypeLegalizer::ScalarizeVecOp_VSELECT(SDNode *N) {
|
||||
N->getOperand(2));
|
||||
}
|
||||
|
||||
/// If the operand is a vector that needs to be scalarized then the
|
||||
/// result must be v1i1, so just convert to a scalar SETCC and wrap
|
||||
/// with a scalar_to_vector since the res type is legal if we got here
|
||||
SDValue DAGTypeLegalizer::ScalarizeVecOp_VSETCC(SDNode *N) {
|
||||
assert(N->getValueType(0).isVector() &&
|
||||
N->getOperand(0).getValueType().isVector() &&
|
||||
"Operand types must be vectors");
|
||||
assert(N->getValueType(0) == MVT::v1i1 && "Expected v1i1 type");
|
||||
|
||||
EVT VT = N->getValueType(0);
|
||||
SDValue LHS = GetScalarizedVector(N->getOperand(0));
|
||||
SDValue RHS = GetScalarizedVector(N->getOperand(1));
|
||||
|
||||
EVT OpVT = N->getOperand(0).getValueType();
|
||||
EVT NVT = VT.getVectorElementType();
|
||||
SDLoc DL(N);
|
||||
// Turn it into a scalar SETCC.
|
||||
SDValue Res = DAG.getNode(ISD::SETCC, DL, MVT::i1, LHS, RHS,
|
||||
N->getOperand(2));
|
||||
|
||||
// Vectors may have a different boolean contents to scalars. Promote the
|
||||
// value appropriately.
|
||||
ISD::NodeType ExtendCode =
|
||||
TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
|
||||
|
||||
Res = DAG.getNode(ExtendCode, DL, NVT, Res);
|
||||
|
||||
return DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, VT, Res);
|
||||
}
|
||||
|
||||
/// If the value to store is a vector that needs to be scalarized, it must be
|
||||
/// <1 x ty>. Just store the element.
|
||||
SDValue DAGTypeLegalizer::ScalarizeVecOp_STORE(StoreSDNode *N, unsigned OpNo){
|
||||
|
@ -116,7 +116,8 @@ bool ConstantFPSDNode::isValueValidForType(EVT VT,
|
||||
// ISD Namespace
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
bool ISD::isConstantSplatVector(const SDNode *N, APInt &SplatVal) {
|
||||
bool ISD::isConstantSplatVector(const SDNode *N, APInt &SplatVal,
|
||||
bool AllowShrink) {
|
||||
auto *BV = dyn_cast<BuildVectorSDNode>(N);
|
||||
if (!BV)
|
||||
return false;
|
||||
@ -124,9 +125,11 @@ bool ISD::isConstantSplatVector(const SDNode *N, APInt &SplatVal) {
|
||||
APInt SplatUndef;
|
||||
unsigned SplatBitSize;
|
||||
bool HasUndefs;
|
||||
EVT EltVT = N->getValueType(0).getVectorElementType();
|
||||
return BV->isConstantSplat(SplatVal, SplatUndef, SplatBitSize, HasUndefs) &&
|
||||
EltVT.getSizeInBits() >= SplatBitSize;
|
||||
unsigned EltSize = N->getValueType(0).getVectorElementType().getSizeInBits();
|
||||
unsigned MinSplatBits = AllowShrink ? 0 : EltSize;
|
||||
return BV->isConstantSplat(SplatVal, SplatUndef, SplatBitSize, HasUndefs,
|
||||
MinSplatBits) &&
|
||||
EltSize >= SplatBitSize;
|
||||
}
|
||||
|
||||
// FIXME: AllOnes and AllZeros duplicate a lot of code. Could these be
|
||||
|
@ -2239,14 +2239,14 @@ bool llvm::UpgradeDebugInfo(Module &M) {
|
||||
}
|
||||
|
||||
bool llvm::UpgradeModuleFlags(Module &M) {
|
||||
const NamedMDNode *ModFlags = M.getModuleFlagsMetadata();
|
||||
NamedMDNode *ModFlags = M.getModuleFlagsMetadata();
|
||||
if (!ModFlags)
|
||||
return false;
|
||||
|
||||
bool HasObjCFlag = false, HasClassProperties = false;
|
||||
bool HasObjCFlag = false, HasClassProperties = false, Changed = false;
|
||||
for (unsigned I = 0, E = ModFlags->getNumOperands(); I != E; ++I) {
|
||||
MDNode *Op = ModFlags->getOperand(I);
|
||||
if (Op->getNumOperands() < 2)
|
||||
if (Op->getNumOperands() != 3)
|
||||
continue;
|
||||
MDString *ID = dyn_cast_or_null<MDString>(Op->getOperand(1));
|
||||
if (!ID)
|
||||
@ -2255,7 +2255,24 @@ bool llvm::UpgradeModuleFlags(Module &M) {
|
||||
HasObjCFlag = true;
|
||||
if (ID->getString() == "Objective-C Class Properties")
|
||||
HasClassProperties = true;
|
||||
// Upgrade PIC/PIE Module Flags. The module flag behavior for these two
|
||||
// field was Error and now they are Max.
|
||||
if (ID->getString() == "PIC Level" || ID->getString() == "PIE Level") {
|
||||
if (auto *Behavior =
|
||||
mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(0))) {
|
||||
if (Behavior->getLimitedValue() == Module::Error) {
|
||||
Type *Int32Ty = Type::getInt32Ty(M.getContext());
|
||||
Metadata *Ops[3] = {
|
||||
ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Module::Max)),
|
||||
MDString::get(M.getContext(), ID->getString()),
|
||||
Op->getOperand(2)};
|
||||
ModFlags->setOperand(I, MDNode::get(M.getContext(), Ops));
|
||||
Changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// "Objective-C Class Properties" is recently added for Objective-C. We
|
||||
// upgrade ObjC bitcodes to contain a "Objective-C Class Properties" module
|
||||
// flag of value 0, so we can correclty downgrade this flag when trying to
|
||||
@ -2264,9 +2281,10 @@ bool llvm::UpgradeModuleFlags(Module &M) {
|
||||
if (HasObjCFlag && !HasClassProperties) {
|
||||
M.addModuleFlag(llvm::Module::Override, "Objective-C Class Properties",
|
||||
(uint32_t)0);
|
||||
return true;
|
||||
Changed = true;
|
||||
}
|
||||
return false;
|
||||
|
||||
return Changed;
|
||||
}
|
||||
|
||||
static bool isOldLoopArgument(Metadata *MD) {
|
||||
|
@ -232,7 +232,13 @@ class Parser {
|
||||
for (;;) {
|
||||
read();
|
||||
if (Tok.K == Identifier && Tok.Value[0] == '@') {
|
||||
Tok.Value.drop_front().getAsInteger(10, E.Ordinal);
|
||||
if (Tok.Value.drop_front().getAsInteger(10, E.Ordinal)) {
|
||||
// Not an ordinal modifier at all, but the next export (fastcall
|
||||
// decorated) - complete the current one.
|
||||
unget();
|
||||
Info.Exports.push_back(E);
|
||||
return Error::success();
|
||||
}
|
||||
read();
|
||||
if (Tok.K == KwNoname) {
|
||||
E.Noname = true;
|
||||
|
@ -5901,6 +5901,9 @@ static bool isVUZPMask(ArrayRef<int> M, EVT VT, unsigned &WhichResult) {
|
||||
return false;
|
||||
|
||||
for (unsigned i = 0; i < M.size(); i += NumElts) {
|
||||
if (M.size() == NumElts * 2)
|
||||
WhichResult = i / NumElts;
|
||||
else
|
||||
WhichResult = M[i] == 0 ? 0 : 1;
|
||||
for (unsigned j = 0; j < NumElts; ++j) {
|
||||
if (M[i+j] >= 0 && (unsigned) M[i+j] != 2 * j + WhichResult)
|
||||
@ -5932,6 +5935,9 @@ static bool isVUZP_v_undef_Mask(ArrayRef<int> M, EVT VT, unsigned &WhichResult){
|
||||
|
||||
unsigned Half = NumElts / 2;
|
||||
for (unsigned i = 0; i < M.size(); i += NumElts) {
|
||||
if (M.size() == NumElts * 2)
|
||||
WhichResult = i / NumElts;
|
||||
else
|
||||
WhichResult = M[i] == 0 ? 0 : 1;
|
||||
for (unsigned j = 0; j < NumElts; j += Half) {
|
||||
unsigned Idx = WhichResult;
|
||||
@ -5972,6 +5978,9 @@ static bool isVZIPMask(ArrayRef<int> M, EVT VT, unsigned &WhichResult) {
|
||||
return false;
|
||||
|
||||
for (unsigned i = 0; i < M.size(); i += NumElts) {
|
||||
if (M.size() == NumElts * 2)
|
||||
WhichResult = i / NumElts;
|
||||
else
|
||||
WhichResult = M[i] == 0 ? 0 : 1;
|
||||
unsigned Idx = WhichResult * NumElts / 2;
|
||||
for (unsigned j = 0; j < NumElts; j += 2) {
|
||||
@ -6005,6 +6014,9 @@ static bool isVZIP_v_undef_Mask(ArrayRef<int> M, EVT VT, unsigned &WhichResult){
|
||||
return false;
|
||||
|
||||
for (unsigned i = 0; i < M.size(); i += NumElts) {
|
||||
if (M.size() == NumElts * 2)
|
||||
WhichResult = i / NumElts;
|
||||
else
|
||||
WhichResult = M[i] == 0 ? 0 : 1;
|
||||
unsigned Idx = WhichResult * NumElts / 2;
|
||||
for (unsigned j = 0; j < NumElts; j += 2) {
|
||||
@ -8793,6 +8805,8 @@ ARMTargetLowering::EmitLowered__chkstk(MachineInstr &MI,
|
||||
.addReg(ARM::R4, RegState::Implicit | RegState::Kill)
|
||||
.addReg(ARM::R4, RegState::Implicit | RegState::Define)
|
||||
.addReg(ARM::R12,
|
||||
RegState::Implicit | RegState::Define | RegState::Dead)
|
||||
.addReg(ARM::CPSR,
|
||||
RegState::Implicit | RegState::Define | RegState::Dead);
|
||||
break;
|
||||
case CodeModel::Large:
|
||||
@ -8808,6 +8822,8 @@ ARMTargetLowering::EmitLowered__chkstk(MachineInstr &MI,
|
||||
.addReg(ARM::R4, RegState::Implicit | RegState::Kill)
|
||||
.addReg(ARM::R4, RegState::Implicit | RegState::Define)
|
||||
.addReg(ARM::R12,
|
||||
RegState::Implicit | RegState::Define | RegState::Dead)
|
||||
.addReg(ARM::CPSR,
|
||||
RegState::Implicit | RegState::Define | RegState::Dead);
|
||||
break;
|
||||
}
|
||||
|
@ -29540,8 +29540,9 @@ static bool detectZextAbsDiff(const SDValue &Select, SDValue &Op0,
|
||||
// In SetLT case, The second operand of the comparison can be either 1 or 0.
|
||||
APInt SplatVal;
|
||||
if ((CC == ISD::SETLT) &&
|
||||
!((ISD::isConstantSplatVector(SetCC.getOperand(1).getNode(), SplatVal) &&
|
||||
SplatVal == 1) ||
|
||||
!((ISD::isConstantSplatVector(SetCC.getOperand(1).getNode(), SplatVal,
|
||||
/*AllowShrink*/false) &&
|
||||
SplatVal.isOneValue()) ||
|
||||
(ISD::isBuildVectorAllZeros(SetCC.getOperand(1).getNode()))))
|
||||
return false;
|
||||
|
||||
@ -30628,6 +30629,9 @@ static SDValue combineSelect(SDNode *N, SelectionDAG &DAG,
|
||||
// Byte blends are only available in AVX2
|
||||
if (VT == MVT::v32i8 && !Subtarget.hasAVX2())
|
||||
return SDValue();
|
||||
// There are no 512-bit blend instructions that use sign bits.
|
||||
if (VT.is512BitVector())
|
||||
return SDValue();
|
||||
|
||||
assert(BitWidth >= 8 && BitWidth <= 64 && "Invalid mask size");
|
||||
APInt DemandedMask(APInt::getSignMask(BitWidth));
|
||||
@ -32058,7 +32062,8 @@ static SDValue combineAndMaskToShift(SDNode *N, SelectionDAG &DAG,
|
||||
return SDValue();
|
||||
|
||||
APInt SplatVal;
|
||||
if (!ISD::isConstantSplatVector(Op1.getNode(), SplatVal) ||
|
||||
if (!ISD::isConstantSplatVector(Op1.getNode(), SplatVal,
|
||||
/*AllowShrink*/false) ||
|
||||
!SplatVal.isMask())
|
||||
return SDValue();
|
||||
|
||||
@ -32642,7 +32647,8 @@ static SDValue detectUSatPattern(SDValue In, EVT VT) {
|
||||
"Unexpected types for truncate operation");
|
||||
|
||||
APInt C;
|
||||
if (ISD::isConstantSplatVector(In.getOperand(1).getNode(), C)) {
|
||||
if (ISD::isConstantSplatVector(In.getOperand(1).getNode(), C,
|
||||
/*AllowShrink*/false)) {
|
||||
// C should be equal to UINT32_MAX / UINT16_MAX / UINT8_MAX according
|
||||
// the element size of the destination type.
|
||||
return C.isMask(VT.getScalarSizeInBits()) ? In.getOperand(0) :
|
||||
@ -35346,7 +35352,8 @@ static SDValue combineIncDecVector(SDNode *N, SelectionDAG &DAG) {
|
||||
|
||||
SDNode *N1 = N->getOperand(1).getNode();
|
||||
APInt SplatVal;
|
||||
if (!ISD::isConstantSplatVector(N1, SplatVal) || !SplatVal.isOneValue())
|
||||
if (!ISD::isConstantSplatVector(N1, SplatVal, /*AllowShrink*/false) ||
|
||||
!SplatVal.isOneValue())
|
||||
return SDValue();
|
||||
|
||||
SDValue AllOnesVec = getOnesVector(VT, DAG, SDLoc(N));
|
||||
|
@ -3619,7 +3619,7 @@ let Predicates = [HasVLX] in {
|
||||
def : Pat<(alignedstore256 (v4f64 (extract_subvector
|
||||
(v8f64 VR512:$src), (iPTR 0))), addr:$dst),
|
||||
(VMOVAPDZ256mr addr:$dst, (v4f64 (EXTRACT_SUBREG VR512:$src,sub_ymm)))>;
|
||||
def : Pat<(alignedstore (v8f32 (extract_subvector
|
||||
def : Pat<(alignedstore256 (v8f32 (extract_subvector
|
||||
(v16f32 VR512:$src), (iPTR 0))), addr:$dst),
|
||||
(VMOVAPSZ256mr addr:$dst, (v8f32 (EXTRACT_SUBREG VR512:$src,sub_ymm)))>;
|
||||
def : Pat<(alignedstore256 (v4i64 (extract_subvector
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -161,6 +161,22 @@ int llvm::dlltoolDriverMain(llvm::ArrayRef<const char *> ArgsArr) {
|
||||
if (Path.empty())
|
||||
Path = getImplibPath(Def->OutputFile);
|
||||
|
||||
if (Machine == IMAGE_FILE_MACHINE_I386 && Args.getLastArg(OPT_k)) {
|
||||
for (COFFShortExport& E : Def->Exports) {
|
||||
if (E.isWeak() || (!E.Name.empty() && E.Name[0] == '?'))
|
||||
continue;
|
||||
E.SymbolName = E.Name;
|
||||
// Trim off the trailing decoration. Symbols will always have a
|
||||
// starting prefix here (either _ for cdecl/stdcall, @ for fastcall
|
||||
// or ? for C++ functions). (Vectorcall functions also will end up having
|
||||
// a prefix here, even if they shouldn't.)
|
||||
E.Name = E.Name.substr(0, E.Name.find('@', 1));
|
||||
// By making sure E.SymbolName != E.Name for decorated symbols,
|
||||
// writeImportLibrary writes these symbols with the type
|
||||
// IMPORT_NAME_UNDECORATE.
|
||||
}
|
||||
}
|
||||
|
||||
if (writeImportLibrary(Def->OutputFile, Path, Def->Exports, Machine, true))
|
||||
return 1;
|
||||
return 0;
|
||||
|
@ -12,13 +12,13 @@ def D_long : JoinedOrSeparate<["--"], "dllname">, Alias<D>;
|
||||
def d: JoinedOrSeparate<["-"], "d">, HelpText<"Input .def File">;
|
||||
def d_long : JoinedOrSeparate<["--"], "input-def">, Alias<d>;
|
||||
|
||||
def k: Flag<["-"], "k">, HelpText<"Kill @n Symbol from export">;
|
||||
def k_alias: Flag<["--"], "kill-at">, Alias<k>;
|
||||
|
||||
//==============================================================================
|
||||
// The flags below do nothing. They are defined only for dlltool compatibility.
|
||||
//==============================================================================
|
||||
|
||||
def k: Flag<["-"], "k">, HelpText<"Kill @n Symbol from export">;
|
||||
def k_alias: Flag<["--"], "kill-at">, Alias<k>;
|
||||
|
||||
def S: JoinedOrSeparate<["-"], "S">, HelpText<"Assembler">;
|
||||
def S_alias: JoinedOrSeparate<["--"], "as">, Alias<S>;
|
||||
|
||||
|
@ -155,8 +155,7 @@ class LowerAtomicLegacyPass : public FunctionPass {
|
||||
}
|
||||
|
||||
bool runOnFunction(Function &F) override {
|
||||
if (skipFunction(F))
|
||||
return false;
|
||||
// Don't skip optnone functions; atomics still need to be lowered.
|
||||
FunctionAnalysisManager DummyFAM;
|
||||
auto PA = Impl.run(F, DummyFAM);
|
||||
return !PA.areAllPreserved();
|
||||
|
@ -1941,6 +1941,12 @@ Instruction *ReassociatePass::canonicalizeNegConstExpr(Instruction *I) {
|
||||
if (!User->isCommutative() && User->getOperand(1) != I)
|
||||
return nullptr;
|
||||
|
||||
// Don't canonicalize x + (-Constant * y) -> x - (Constant * y), if the
|
||||
// resulting subtract will be broken up later. This can get us into an
|
||||
// infinite loop during reassociation.
|
||||
if (UserOpcode == Instruction::FAdd && ShouldBreakUpSubtract(User))
|
||||
return nullptr;
|
||||
|
||||
// Change the sign of the constant.
|
||||
APFloat Val = CF->getValueAPF();
|
||||
Val.changeSign();
|
||||
|
@ -341,6 +341,7 @@ void PruningFunctionCloner::CloneBlock(const BasicBlock *BB,
|
||||
SimplifyInstruction(NewInst, BB->getModule()->getDataLayout())) {
|
||||
// On the off-chance that this simplifies to an instruction in the old
|
||||
// function, map it back into the new function.
|
||||
if (NewFunc != OldFunc)
|
||||
if (Value *MappedV = VMap.lookup(V))
|
||||
V = MappedV;
|
||||
|
||||
|
@ -375,6 +375,7 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// \brief These flags are \c true if a defaulted corresponding special
|
||||
/// member can't be fully analyzed without performing overload resolution.
|
||||
/// @{
|
||||
unsigned NeedOverloadResolutionForCopyConstructor : 1;
|
||||
unsigned NeedOverloadResolutionForMoveConstructor : 1;
|
||||
unsigned NeedOverloadResolutionForMoveAssignment : 1;
|
||||
unsigned NeedOverloadResolutionForDestructor : 1;
|
||||
@ -383,6 +384,7 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// \brief These flags are \c true if an implicit defaulted corresponding
|
||||
/// special member would be defined as deleted.
|
||||
/// @{
|
||||
unsigned DefaultedCopyConstructorIsDeleted : 1;
|
||||
unsigned DefaultedMoveConstructorIsDeleted : 1;
|
||||
unsigned DefaultedMoveAssignmentIsDeleted : 1;
|
||||
unsigned DefaultedDestructorIsDeleted : 1;
|
||||
@ -415,6 +417,12 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// constructor.
|
||||
unsigned HasDefaultedDefaultConstructor : 1;
|
||||
|
||||
/// \brief True if this class can be passed in a non-address-preserving
|
||||
/// fashion (such as in registers) according to the C++ language rules.
|
||||
/// This does not imply anything about how the ABI in use will actually
|
||||
/// pass an object of this class.
|
||||
unsigned CanPassInRegisters : 1;
|
||||
|
||||
/// \brief True if a defaulted default constructor for this class would
|
||||
/// be constexpr.
|
||||
unsigned DefaultedDefaultConstructorIsConstexpr : 1;
|
||||
@ -811,18 +819,50 @@ class CXXRecordDecl : public RecordDecl {
|
||||
return data().FirstFriend.isValid();
|
||||
}
|
||||
|
||||
/// \brief \c true if a defaulted copy constructor for this class would be
|
||||
/// deleted.
|
||||
bool defaultedCopyConstructorIsDeleted() const {
|
||||
assert((!needsOverloadResolutionForCopyConstructor() ||
|
||||
(data().DeclaredSpecialMembers & SMF_CopyConstructor)) &&
|
||||
"this property has not yet been computed by Sema");
|
||||
return data().DefaultedCopyConstructorIsDeleted;
|
||||
}
|
||||
|
||||
/// \brief \c true if a defaulted move constructor for this class would be
|
||||
/// deleted.
|
||||
bool defaultedMoveConstructorIsDeleted() const {
|
||||
assert((!needsOverloadResolutionForMoveConstructor() ||
|
||||
(data().DeclaredSpecialMembers & SMF_MoveConstructor)) &&
|
||||
"this property has not yet been computed by Sema");
|
||||
return data().DefaultedMoveConstructorIsDeleted;
|
||||
}
|
||||
|
||||
/// \brief \c true if a defaulted destructor for this class would be deleted.
|
||||
bool defaultedDestructorIsDeleted() const {
|
||||
return !data().DefaultedDestructorIsDeleted;
|
||||
}
|
||||
|
||||
/// \brief \c true if we know for sure that this class has a single,
|
||||
/// accessible, unambiguous copy constructor that is not deleted.
|
||||
bool hasSimpleCopyConstructor() const {
|
||||
return !hasUserDeclaredCopyConstructor() &&
|
||||
!data().DefaultedCopyConstructorIsDeleted;
|
||||
}
|
||||
|
||||
/// \brief \c true if we know for sure that this class has a single,
|
||||
/// accessible, unambiguous move constructor that is not deleted.
|
||||
bool hasSimpleMoveConstructor() const {
|
||||
return !hasUserDeclaredMoveConstructor() && hasMoveConstructor() &&
|
||||
!data().DefaultedMoveConstructorIsDeleted;
|
||||
}
|
||||
|
||||
/// \brief \c true if we know for sure that this class has a single,
|
||||
/// accessible, unambiguous move assignment operator that is not deleted.
|
||||
bool hasSimpleMoveAssignment() const {
|
||||
return !hasUserDeclaredMoveAssignment() && hasMoveAssignment() &&
|
||||
!data().DefaultedMoveAssignmentIsDeleted;
|
||||
}
|
||||
|
||||
/// \brief \c true if we know for sure that this class has an accessible
|
||||
/// destructor that is not deleted.
|
||||
bool hasSimpleDestructor() const {
|
||||
@ -878,7 +918,16 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// \brief Determine whether we need to eagerly declare a defaulted copy
|
||||
/// constructor for this class.
|
||||
bool needsOverloadResolutionForCopyConstructor() const {
|
||||
return data().HasMutableFields;
|
||||
// C++17 [class.copy.ctor]p6:
|
||||
// If the class definition declares a move constructor or move assignment
|
||||
// operator, the implicitly declared copy constructor is defined as
|
||||
// deleted.
|
||||
// In MSVC mode, sometimes a declared move assignment does not delete an
|
||||
// implicit copy constructor, so defer this choice to Sema.
|
||||
if (data().UserDeclaredSpecialMembers &
|
||||
(SMF_MoveConstructor | SMF_MoveAssignment))
|
||||
return true;
|
||||
return data().NeedOverloadResolutionForCopyConstructor;
|
||||
}
|
||||
|
||||
/// \brief Determine whether an implicit copy constructor for this type
|
||||
@ -919,7 +968,16 @@ class CXXRecordDecl : public RecordDecl {
|
||||
needsImplicitMoveConstructor();
|
||||
}
|
||||
|
||||
/// \brief Set that we attempted to declare an implicitly move
|
||||
/// \brief Set that we attempted to declare an implicit copy
|
||||
/// constructor, but overload resolution failed so we deleted it.
|
||||
void setImplicitCopyConstructorIsDeleted() {
|
||||
assert((data().DefaultedCopyConstructorIsDeleted ||
|
||||
needsOverloadResolutionForCopyConstructor()) &&
|
||||
"Copy constructor should not be deleted");
|
||||
data().DefaultedCopyConstructorIsDeleted = true;
|
||||
}
|
||||
|
||||
/// \brief Set that we attempted to declare an implicit move
|
||||
/// constructor, but overload resolution failed so we deleted it.
|
||||
void setImplicitMoveConstructorIsDeleted() {
|
||||
assert((data().DefaultedMoveConstructorIsDeleted ||
|
||||
@ -1316,6 +1374,18 @@ class CXXRecordDecl : public RecordDecl {
|
||||
return data().HasIrrelevantDestructor;
|
||||
}
|
||||
|
||||
/// \brief Determine whether this class has at least one trivial, non-deleted
|
||||
/// copy or move constructor.
|
||||
bool canPassInRegisters() const {
|
||||
return data().CanPassInRegisters;
|
||||
}
|
||||
|
||||
/// \brief Set that we can pass this RecordDecl in registers.
|
||||
// FIXME: This should be set as part of completeDefinition.
|
||||
void setCanPassInRegisters(bool CanPass) {
|
||||
data().CanPassInRegisters = CanPass;
|
||||
}
|
||||
|
||||
/// \brief Determine whether this class has a non-literal or/ volatile type
|
||||
/// non-static data member or base class.
|
||||
bool hasNonLiteralTypeFieldsOrBases() const {
|
||||
|
@ -1048,10 +1048,6 @@ class Preprocessor {
|
||||
/// which implicitly adds the builtin defines etc.
|
||||
void EnterMainSourceFile();
|
||||
|
||||
/// \brief After parser warm-up, initialize the conditional stack from
|
||||
/// the preamble.
|
||||
void replayPreambleConditionalStack();
|
||||
|
||||
/// \brief Inform the preprocessor callbacks that processing is complete.
|
||||
void EndSourceFile();
|
||||
|
||||
@ -2025,6 +2021,10 @@ class Preprocessor {
|
||||
}
|
||||
|
||||
private:
|
||||
/// \brief After processing predefined file, initialize the conditional stack from
|
||||
/// the preamble.
|
||||
void replayPreambleConditionalStack();
|
||||
|
||||
// Macro handling.
|
||||
void HandleDefineDirective(Token &Tok, bool ImmediatelyAfterTopLevelIfndef);
|
||||
void HandleUndefDirective();
|
||||
|
@ -956,12 +956,16 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To,
|
||||
ToData.HasUninitializedFields = FromData.HasUninitializedFields;
|
||||
ToData.HasInheritedConstructor = FromData.HasInheritedConstructor;
|
||||
ToData.HasInheritedAssignment = FromData.HasInheritedAssignment;
|
||||
ToData.NeedOverloadResolutionForCopyConstructor
|
||||
= FromData.NeedOverloadResolutionForCopyConstructor;
|
||||
ToData.NeedOverloadResolutionForMoveConstructor
|
||||
= FromData.NeedOverloadResolutionForMoveConstructor;
|
||||
ToData.NeedOverloadResolutionForMoveAssignment
|
||||
= FromData.NeedOverloadResolutionForMoveAssignment;
|
||||
ToData.NeedOverloadResolutionForDestructor
|
||||
= FromData.NeedOverloadResolutionForDestructor;
|
||||
ToData.DefaultedCopyConstructorIsDeleted
|
||||
= FromData.DefaultedCopyConstructorIsDeleted;
|
||||
ToData.DefaultedMoveConstructorIsDeleted
|
||||
= FromData.DefaultedMoveConstructorIsDeleted;
|
||||
ToData.DefaultedMoveAssignmentIsDeleted
|
||||
@ -973,6 +977,7 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To,
|
||||
= FromData.HasConstexprNonCopyMoveConstructor;
|
||||
ToData.HasDefaultedDefaultConstructor
|
||||
= FromData.HasDefaultedDefaultConstructor;
|
||||
ToData.CanPassInRegisters = FromData.CanPassInRegisters;
|
||||
ToData.DefaultedDefaultConstructorIsConstexpr
|
||||
= FromData.DefaultedDefaultConstructorIsConstexpr;
|
||||
ToData.HasConstexprDefaultConstructor
|
||||
|
@ -55,15 +55,18 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
|
||||
HasOnlyCMembers(true), HasInClassInitializer(false),
|
||||
HasUninitializedReferenceMember(false), HasUninitializedFields(false),
|
||||
HasInheritedConstructor(false), HasInheritedAssignment(false),
|
||||
NeedOverloadResolutionForCopyConstructor(false),
|
||||
NeedOverloadResolutionForMoveConstructor(false),
|
||||
NeedOverloadResolutionForMoveAssignment(false),
|
||||
NeedOverloadResolutionForDestructor(false),
|
||||
DefaultedCopyConstructorIsDeleted(false),
|
||||
DefaultedMoveConstructorIsDeleted(false),
|
||||
DefaultedMoveAssignmentIsDeleted(false),
|
||||
DefaultedDestructorIsDeleted(false), HasTrivialSpecialMembers(SMF_All),
|
||||
DeclaredNonTrivialSpecialMembers(0), HasIrrelevantDestructor(true),
|
||||
HasConstexprNonCopyMoveConstructor(false),
|
||||
HasDefaultedDefaultConstructor(false),
|
||||
CanPassInRegisters(true),
|
||||
DefaultedDefaultConstructorIsConstexpr(true),
|
||||
HasConstexprDefaultConstructor(false),
|
||||
HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false),
|
||||
@ -352,8 +355,10 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
|
||||
setHasVolatileMember(true);
|
||||
|
||||
// Keep track of the presence of mutable fields.
|
||||
if (BaseClassDecl->hasMutableFields())
|
||||
if (BaseClassDecl->hasMutableFields()) {
|
||||
data().HasMutableFields = true;
|
||||
data().NeedOverloadResolutionForCopyConstructor = true;
|
||||
}
|
||||
|
||||
if (BaseClassDecl->hasUninitializedReferenceMember())
|
||||
data().HasUninitializedReferenceMember = true;
|
||||
@ -406,6 +411,8 @@ void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) {
|
||||
// -- a direct or virtual base class B that cannot be copied/moved [...]
|
||||
// -- a non-static data member of class type M (or array thereof)
|
||||
// that cannot be copied or moved [...]
|
||||
if (!Subobj->hasSimpleCopyConstructor())
|
||||
data().NeedOverloadResolutionForCopyConstructor = true;
|
||||
if (!Subobj->hasSimpleMoveConstructor())
|
||||
data().NeedOverloadResolutionForMoveConstructor = true;
|
||||
|
||||
@ -426,6 +433,7 @@ void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) {
|
||||
// -- any non-static data member has a type with a destructor
|
||||
// that is deleted or inaccessible from the defaulted [ctor or dtor].
|
||||
if (!Subobj->hasSimpleDestructor()) {
|
||||
data().NeedOverloadResolutionForCopyConstructor = true;
|
||||
data().NeedOverloadResolutionForMoveConstructor = true;
|
||||
data().NeedOverloadResolutionForDestructor = true;
|
||||
}
|
||||
@ -711,8 +719,10 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
||||
data().IsStandardLayout = false;
|
||||
|
||||
// Keep track of the presence of mutable fields.
|
||||
if (Field->isMutable())
|
||||
if (Field->isMutable()) {
|
||||
data().HasMutableFields = true;
|
||||
data().NeedOverloadResolutionForCopyConstructor = true;
|
||||
}
|
||||
|
||||
// C++11 [class.union]p8, DR1460:
|
||||
// If X is a union, a non-static data member of X that is not an anonymous
|
||||
@ -756,6 +766,12 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
||||
// A standard-layout class is a class that:
|
||||
// -- has no non-static data members of type [...] reference,
|
||||
data().IsStandardLayout = false;
|
||||
|
||||
// C++1z [class.copy.ctor]p10:
|
||||
// A defaulted copy constructor for a class X is defined as deleted if X has:
|
||||
// -- a non-static data member of rvalue reference type
|
||||
if (T->isRValueReferenceType())
|
||||
data().DefaultedCopyConstructorIsDeleted = true;
|
||||
}
|
||||
|
||||
if (!Field->hasInClassInitializer() && !Field->isMutable()) {
|
||||
@ -809,6 +825,10 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
||||
// We may need to perform overload resolution to determine whether a
|
||||
// field can be moved if it's const or volatile qualified.
|
||||
if (T.getCVRQualifiers() & (Qualifiers::Const | Qualifiers::Volatile)) {
|
||||
// We need to care about 'const' for the copy constructor because an
|
||||
// implicit copy constructor might be declared with a non-const
|
||||
// parameter.
|
||||
data().NeedOverloadResolutionForCopyConstructor = true;
|
||||
data().NeedOverloadResolutionForMoveConstructor = true;
|
||||
data().NeedOverloadResolutionForMoveAssignment = true;
|
||||
}
|
||||
@ -819,6 +839,8 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
||||
// -- X is a union-like class that has a variant member with a
|
||||
// non-trivial [corresponding special member]
|
||||
if (isUnion()) {
|
||||
if (FieldRec->hasNonTrivialCopyConstructor())
|
||||
data().DefaultedCopyConstructorIsDeleted = true;
|
||||
if (FieldRec->hasNonTrivialMoveConstructor())
|
||||
data().DefaultedMoveConstructorIsDeleted = true;
|
||||
if (FieldRec->hasNonTrivialMoveAssignment())
|
||||
@ -830,6 +852,8 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
||||
// For an anonymous union member, our overload resolution will perform
|
||||
// overload resolution for its members.
|
||||
if (Field->isAnonymousStructOrUnion()) {
|
||||
data().NeedOverloadResolutionForCopyConstructor |=
|
||||
FieldRec->data().NeedOverloadResolutionForCopyConstructor;
|
||||
data().NeedOverloadResolutionForMoveConstructor |=
|
||||
FieldRec->data().NeedOverloadResolutionForMoveConstructor;
|
||||
data().NeedOverloadResolutionForMoveAssignment |=
|
||||
@ -915,8 +939,10 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
||||
}
|
||||
|
||||
// Keep track of the presence of mutable fields.
|
||||
if (FieldRec->hasMutableFields())
|
||||
if (FieldRec->hasMutableFields()) {
|
||||
data().HasMutableFields = true;
|
||||
data().NeedOverloadResolutionForCopyConstructor = true;
|
||||
}
|
||||
|
||||
// C++11 [class.copy]p13:
|
||||
// If the implicitly-defined constructor would satisfy the
|
||||
|
@ -30,38 +30,9 @@ void CGCXXABI::ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S) {
|
||||
}
|
||||
|
||||
bool CGCXXABI::canCopyArgument(const CXXRecordDecl *RD) const {
|
||||
// If RD has a non-trivial move or copy constructor, we cannot copy the
|
||||
// argument.
|
||||
if (RD->hasNonTrivialCopyConstructor() || RD->hasNonTrivialMoveConstructor())
|
||||
return false;
|
||||
|
||||
// If RD has a non-trivial destructor, we cannot copy the argument.
|
||||
if (RD->hasNonTrivialDestructor())
|
||||
return false;
|
||||
|
||||
// We can only copy the argument if there exists at least one trivial,
|
||||
// non-deleted copy or move constructor.
|
||||
// FIXME: This assumes that all lazily declared copy and move constructors are
|
||||
// not deleted. This assumption might not be true in some corner cases.
|
||||
bool CopyDeleted = false;
|
||||
bool MoveDeleted = false;
|
||||
for (const CXXConstructorDecl *CD : RD->ctors()) {
|
||||
if (CD->isCopyConstructor() || CD->isMoveConstructor()) {
|
||||
assert(CD->isTrivial());
|
||||
// We had at least one undeleted trivial copy or move ctor. Return
|
||||
// directly.
|
||||
if (!CD->isDeleted())
|
||||
return true;
|
||||
if (CD->isCopyConstructor())
|
||||
CopyDeleted = true;
|
||||
else
|
||||
MoveDeleted = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If all trivial copy and move constructors are deleted, we cannot copy the
|
||||
// argument.
|
||||
return !(CopyDeleted && MoveDeleted);
|
||||
return RD->canPassInRegisters();
|
||||
}
|
||||
|
||||
llvm::Constant *CGCXXABI::GetBogusMemberPointer(QualType T) {
|
||||
|
@ -63,11 +63,8 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
|
||||
bool classifyReturnType(CGFunctionInfo &FI) const override;
|
||||
|
||||
RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const override {
|
||||
// Structures with either a non-trivial destructor or a non-trivial
|
||||
// copy constructor are always indirect.
|
||||
// FIXME: Use canCopyArgument() when it is fixed to handle lazily declared
|
||||
// special members.
|
||||
if (RD->hasNonTrivialDestructor() || RD->hasNonTrivialCopyConstructor())
|
||||
// If C++ prohibits us from making a copy, pass by address.
|
||||
if (!canCopyArgument(RD))
|
||||
return RAA_Indirect;
|
||||
return RAA_Default;
|
||||
}
|
||||
@ -998,10 +995,8 @@ bool ItaniumCXXABI::classifyReturnType(CGFunctionInfo &FI) const {
|
||||
if (!RD)
|
||||
return false;
|
||||
|
||||
// Return indirectly if we have a non-trivial copy ctor or non-trivial dtor.
|
||||
// FIXME: Use canCopyArgument() when it is fixed to handle lazily declared
|
||||
// special members.
|
||||
if (RD->hasNonTrivialDestructor() || RD->hasNonTrivialCopyConstructor()) {
|
||||
// If C++ prohibits us from making a copy, return by address.
|
||||
if (!canCopyArgument(RD)) {
|
||||
auto Align = CGM.getContext().getTypeAlignInChars(FI.getReturnType());
|
||||
FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false);
|
||||
return true;
|
||||
|
@ -819,46 +819,44 @@ MicrosoftCXXABI::getRecordArgABI(const CXXRecordDecl *RD) const {
|
||||
return RAA_Default;
|
||||
|
||||
case llvm::Triple::x86_64:
|
||||
// Win64 passes objects with non-trivial copy ctors indirectly.
|
||||
if (RD->hasNonTrivialCopyConstructor())
|
||||
return RAA_Indirect;
|
||||
|
||||
// If an object has a destructor, we'd really like to pass it indirectly
|
||||
// If a class has a destructor, we'd really like to pass it indirectly
|
||||
// because it allows us to elide copies. Unfortunately, MSVC makes that
|
||||
// impossible for small types, which it will pass in a single register or
|
||||
// stack slot. Most objects with dtors are large-ish, so handle that early.
|
||||
// We can't call out all large objects as being indirect because there are
|
||||
// multiple x64 calling conventions and the C++ ABI code shouldn't dictate
|
||||
// how we pass large POD types.
|
||||
//
|
||||
// Note: This permits small classes with nontrivial destructors to be
|
||||
// passed in registers, which is non-conforming.
|
||||
if (RD->hasNonTrivialDestructor() &&
|
||||
getContext().getTypeSize(RD->getTypeForDecl()) > 64)
|
||||
return RAA_Indirect;
|
||||
|
||||
// If this is true, the implicit copy constructor that Sema would have
|
||||
// created would not be deleted. FIXME: We should provide a more direct way
|
||||
// for CodeGen to ask whether the constructor was deleted.
|
||||
if (!RD->hasUserDeclaredCopyConstructor() &&
|
||||
!RD->hasUserDeclaredMoveConstructor() &&
|
||||
!RD->needsOverloadResolutionForMoveConstructor() &&
|
||||
!RD->hasUserDeclaredMoveAssignment() &&
|
||||
!RD->needsOverloadResolutionForMoveAssignment())
|
||||
// If a class has at least one non-deleted, trivial copy constructor, it
|
||||
// is passed according to the C ABI. Otherwise, it is passed indirectly.
|
||||
//
|
||||
// Note: This permits classes with non-trivial copy or move ctors to be
|
||||
// passed in registers, so long as they *also* have a trivial copy ctor,
|
||||
// which is non-conforming.
|
||||
if (RD->needsImplicitCopyConstructor()) {
|
||||
// If the copy ctor has not yet been declared, we can read its triviality
|
||||
// off the AST.
|
||||
if (!RD->defaultedCopyConstructorIsDeleted() &&
|
||||
RD->hasTrivialCopyConstructor())
|
||||
return RAA_Default;
|
||||
|
||||
// Otherwise, Sema should have created an implicit copy constructor if
|
||||
// needed.
|
||||
assert(!RD->needsImplicitCopyConstructor());
|
||||
|
||||
// We have to make sure the trivial copy constructor isn't deleted.
|
||||
} else {
|
||||
// Otherwise, we need to find the copy constructor(s) and ask.
|
||||
for (const CXXConstructorDecl *CD : RD->ctors()) {
|
||||
if (CD->isCopyConstructor()) {
|
||||
assert(CD->isTrivial());
|
||||
// We had at least one undeleted trivial copy ctor. Return directly.
|
||||
if (!CD->isDeleted())
|
||||
// We had at least one nondeleted trivial copy ctor. Return directly.
|
||||
if (!CD->isDeleted() && CD->isTrivial())
|
||||
return RAA_Default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The trivial copy constructor was deleted. Return indirectly.
|
||||
// We have no trivial, non-deleted copy constructor.
|
||||
return RAA_Indirect;
|
||||
}
|
||||
|
||||
|
@ -1837,7 +1837,12 @@ Darwin::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
|
||||
}
|
||||
|
||||
bool MachO::IsUnwindTablesDefault(const ArgList &Args) const {
|
||||
return !UseSjLjExceptions(Args);
|
||||
// Unwind tables are not emitted if -fno-exceptions is supplied (except when
|
||||
// targeting x86_64).
|
||||
return getArch() == llvm::Triple::x86_64 ||
|
||||
(!UseSjLjExceptions(Args) &&
|
||||
Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,
|
||||
true));
|
||||
}
|
||||
|
||||
bool MachO::UseDwarfDebugFlags() const {
|
||||
|
@ -76,7 +76,7 @@ static bool getSystemRegistryString(const char *keyPath, const char *valueName,
|
||||
|
||||
// Check various environment variables to try and find a toolchain.
|
||||
static bool findVCToolChainViaEnvironment(std::string &Path,
|
||||
bool &IsVS2017OrNewer) {
|
||||
MSVCToolChain::ToolsetLayout &VSLayout) {
|
||||
// These variables are typically set by vcvarsall.bat
|
||||
// when launching a developer command prompt.
|
||||
if (llvm::Optional<std::string> VCToolsInstallDir =
|
||||
@ -84,7 +84,7 @@ static bool findVCToolChainViaEnvironment(std::string &Path,
|
||||
// This is only set by newer Visual Studios, and it leads straight to
|
||||
// the toolchain directory.
|
||||
Path = std::move(*VCToolsInstallDir);
|
||||
IsVS2017OrNewer = true;
|
||||
VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
|
||||
return true;
|
||||
}
|
||||
if (llvm::Optional<std::string> VCInstallDir =
|
||||
@ -94,7 +94,7 @@ static bool findVCToolChainViaEnvironment(std::string &Path,
|
||||
// so this check has to appear second.
|
||||
// In older Visual Studios, the VC directory is the toolchain.
|
||||
Path = std::move(*VCInstallDir);
|
||||
IsVS2017OrNewer = false;
|
||||
VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -134,9 +134,16 @@ static bool findVCToolChainViaEnvironment(std::string &Path,
|
||||
}
|
||||
if (IsBin) {
|
||||
llvm::StringRef ParentPath = llvm::sys::path::parent_path(TestPath);
|
||||
if (llvm::sys::path::filename(ParentPath) == "VC") {
|
||||
llvm::StringRef ParentFilename = llvm::sys::path::filename(ParentPath);
|
||||
if (ParentFilename == "VC") {
|
||||
Path = ParentPath;
|
||||
IsVS2017OrNewer = false;
|
||||
VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
|
||||
return true;
|
||||
}
|
||||
if (ParentFilename == "x86ret" || ParentFilename == "x86chk"
|
||||
|| ParentFilename == "amd64ret" || ParentFilename == "amd64chk") {
|
||||
Path = ParentPath;
|
||||
VSLayout = MSVCToolChain::ToolsetLayout::DevDivInternal;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -165,7 +172,7 @@ static bool findVCToolChainViaEnvironment(std::string &Path,
|
||||
ToolChainPath = llvm::sys::path::parent_path(ToolChainPath);
|
||||
|
||||
Path = ToolChainPath;
|
||||
IsVS2017OrNewer = true;
|
||||
VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -181,7 +188,7 @@ static bool findVCToolChainViaEnvironment(std::string &Path,
|
||||
// This is the preferred way to discover new Visual Studios, as they're no
|
||||
// longer listed in the registry.
|
||||
static bool findVCToolChainViaSetupConfig(std::string &Path,
|
||||
bool &IsVS2017OrNewer) {
|
||||
MSVCToolChain::ToolsetLayout &VSLayout) {
|
||||
#if !defined(USE_MSVC_SETUP_API)
|
||||
return false;
|
||||
#else
|
||||
@ -263,7 +270,7 @@ static bool findVCToolChainViaSetupConfig(std::string &Path,
|
||||
return false;
|
||||
|
||||
Path = ToolchainPath.str();
|
||||
IsVS2017OrNewer = true;
|
||||
VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
@ -272,7 +279,7 @@ static bool findVCToolChainViaSetupConfig(std::string &Path,
|
||||
// a toolchain path. VS2017 and newer don't get added to the registry.
|
||||
// So if we find something here, we know that it's an older version.
|
||||
static bool findVCToolChainViaRegistry(std::string &Path,
|
||||
bool &IsVS2017OrNewer) {
|
||||
MSVCToolChain::ToolsetLayout &VSLayout) {
|
||||
std::string VSInstallPath;
|
||||
if (getSystemRegistryString(R"(SOFTWARE\Microsoft\VisualStudio\$VERSION)",
|
||||
"InstallDir", VSInstallPath, nullptr) ||
|
||||
@ -284,7 +291,7 @@ static bool findVCToolChainViaRegistry(std::string &Path,
|
||||
llvm::sys::path::append(VCPath, "VC");
|
||||
|
||||
Path = VCPath.str();
|
||||
IsVS2017OrNewer = false;
|
||||
VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -475,6 +482,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
// native target bin directory.
|
||||
// e.g. when compiling for x86 on an x64 host, PATH should start with:
|
||||
// /bin/HostX64/x86;/bin/HostX64/x64
|
||||
// This doesn't attempt to handle ToolsetLayout::DevDivInternal.
|
||||
if (TC.getIsVS2017OrNewer() &&
|
||||
llvm::Triple(llvm::sys::getProcessTriple()).getArch() != TC.getArch()) {
|
||||
auto HostArch = llvm::Triple(llvm::sys::getProcessTriple()).getArch();
|
||||
@ -677,9 +685,9 @@ MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
|
||||
// what they want to use.
|
||||
// Failing that, just try to find the newest Visual Studio version we can
|
||||
// and use its default VC toolchain.
|
||||
findVCToolChainViaEnvironment(VCToolChainPath, IsVS2017OrNewer) ||
|
||||
findVCToolChainViaSetupConfig(VCToolChainPath, IsVS2017OrNewer) ||
|
||||
findVCToolChainViaRegistry(VCToolChainPath, IsVS2017OrNewer);
|
||||
findVCToolChainViaEnvironment(VCToolChainPath, VSLayout) ||
|
||||
findVCToolChainViaSetupConfig(VCToolChainPath, VSLayout) ||
|
||||
findVCToolChainViaRegistry(VCToolChainPath, VSLayout);
|
||||
}
|
||||
|
||||
Tool *MSVCToolChain::buildLinker() const {
|
||||
@ -766,6 +774,21 @@ static const char *llvmArchToLegacyVCArch(llvm::Triple::ArchType Arch) {
|
||||
}
|
||||
}
|
||||
|
||||
// Similar to the above function, but for DevDiv internal builds.
|
||||
static const char *llvmArchToDevDivInternalArch(llvm::Triple::ArchType Arch) {
|
||||
using ArchType = llvm::Triple::ArchType;
|
||||
switch (Arch) {
|
||||
case ArchType::x86:
|
||||
return "i386";
|
||||
case ArchType::x86_64:
|
||||
return "amd64";
|
||||
case ArchType::arm:
|
||||
return "arm";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// Get the path to a specific subdirectory in the current toolchain for
|
||||
// a given target architecture.
|
||||
// VS2017 changed the VC toolchain layout, so this should be used instead
|
||||
@ -773,26 +796,40 @@ static const char *llvmArchToLegacyVCArch(llvm::Triple::ArchType Arch) {
|
||||
std::string
|
||||
MSVCToolChain::getSubDirectoryPath(SubDirectoryType Type,
|
||||
llvm::Triple::ArchType TargetArch) const {
|
||||
const char *SubdirName;
|
||||
const char *IncludeName;
|
||||
switch (VSLayout) {
|
||||
case ToolsetLayout::OlderVS:
|
||||
SubdirName = llvmArchToLegacyVCArch(TargetArch);
|
||||
IncludeName = "include";
|
||||
break;
|
||||
case ToolsetLayout::VS2017OrNewer:
|
||||
SubdirName = llvmArchToWindowsSDKArch(TargetArch);
|
||||
IncludeName = "include";
|
||||
break;
|
||||
case ToolsetLayout::DevDivInternal:
|
||||
SubdirName = llvmArchToDevDivInternalArch(TargetArch);
|
||||
IncludeName = "inc";
|
||||
break;
|
||||
}
|
||||
|
||||
llvm::SmallString<256> Path(VCToolChainPath);
|
||||
switch (Type) {
|
||||
case SubDirectoryType::Bin:
|
||||
if (IsVS2017OrNewer) {
|
||||
bool HostIsX64 =
|
||||
if (VSLayout == ToolsetLayout::VS2017OrNewer) {
|
||||
const bool HostIsX64 =
|
||||
llvm::Triple(llvm::sys::getProcessTriple()).isArch64Bit();
|
||||
llvm::sys::path::append(Path, "bin", (HostIsX64 ? "HostX64" : "HostX86"),
|
||||
llvmArchToWindowsSDKArch(TargetArch));
|
||||
|
||||
} else {
|
||||
llvm::sys::path::append(Path, "bin", llvmArchToLegacyVCArch(TargetArch));
|
||||
const char *const HostName = HostIsX64 ? "HostX64" : "HostX86";
|
||||
llvm::sys::path::append(Path, "bin", HostName, SubdirName);
|
||||
} else { // OlderVS or DevDivInternal
|
||||
llvm::sys::path::append(Path, "bin", SubdirName);
|
||||
}
|
||||
break;
|
||||
case SubDirectoryType::Include:
|
||||
llvm::sys::path::append(Path, "include");
|
||||
llvm::sys::path::append(Path, IncludeName);
|
||||
break;
|
||||
case SubDirectoryType::Lib:
|
||||
llvm::sys::path::append(
|
||||
Path, "lib", IsVS2017OrNewer ? llvmArchToWindowsSDKArch(TargetArch)
|
||||
: llvmArchToLegacyVCArch(TargetArch));
|
||||
llvm::sys::path::append(Path, "lib", SubdirName);
|
||||
break;
|
||||
}
|
||||
return Path.str();
|
||||
|
@ -92,7 +92,12 @@ class LLVM_LIBRARY_VISIBILITY MSVCToolChain : public ToolChain {
|
||||
return getSubDirectoryPath(Type, getArch());
|
||||
}
|
||||
|
||||
bool getIsVS2017OrNewer() const { return IsVS2017OrNewer; }
|
||||
enum class ToolsetLayout {
|
||||
OlderVS,
|
||||
VS2017OrNewer,
|
||||
DevDivInternal,
|
||||
};
|
||||
bool getIsVS2017OrNewer() const { return VSLayout == ToolsetLayout::VS2017OrNewer; }
|
||||
|
||||
void
|
||||
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
|
||||
@ -130,7 +135,7 @@ class LLVM_LIBRARY_VISIBILITY MSVCToolChain : public ToolChain {
|
||||
Tool *buildAssembler() const override;
|
||||
private:
|
||||
std::string VCToolChainPath;
|
||||
bool IsVS2017OrNewer = false;
|
||||
ToolsetLayout VSLayout = ToolsetLayout::OlderVS;
|
||||
CudaInstallationDetector CudaInstallation;
|
||||
};
|
||||
|
||||
|
@ -472,9 +472,14 @@ void WhitespaceManager::alignTrailingComments() {
|
||||
continue;
|
||||
|
||||
unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
|
||||
unsigned ChangeMaxColumn = Style.ColumnLimit >= Changes[i].TokenLength
|
||||
? Style.ColumnLimit - Changes[i].TokenLength
|
||||
: ChangeMinColumn;
|
||||
unsigned ChangeMaxColumn;
|
||||
|
||||
if (Style.ColumnLimit == 0)
|
||||
ChangeMaxColumn = UINT_MAX;
|
||||
else if (Style.ColumnLimit >= Changes[i].TokenLength)
|
||||
ChangeMaxColumn = Style.ColumnLimit - Changes[i].TokenLength;
|
||||
else
|
||||
ChangeMaxColumn = ChangeMinColumn;
|
||||
|
||||
// If we don't create a replacement for this change, we have to consider
|
||||
// it to be immovable.
|
||||
|
@ -76,13 +76,7 @@ typedef intptr_t _sleb128_t;
|
||||
typedef uintptr_t _uleb128_t;
|
||||
|
||||
struct _Unwind_Context;
|
||||
#if defined(__arm__) && !(defined(__USING_SJLJ_EXCEPTIONS__) || defined(__ARM_DWARF_EH___))
|
||||
struct _Unwind_Control_Block;
|
||||
typedef struct _Unwind_Control_Block _Unwind_Exception; /* Alias */
|
||||
#else
|
||||
struct _Unwind_Exception;
|
||||
typedef struct _Unwind_Exception _Unwind_Exception;
|
||||
#endif
|
||||
typedef enum {
|
||||
_URC_NO_REASON = 0,
|
||||
#if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \
|
||||
@ -115,42 +109,8 @@ typedef enum {
|
||||
} _Unwind_Action;
|
||||
|
||||
typedef void (*_Unwind_Exception_Cleanup_Fn)(_Unwind_Reason_Code,
|
||||
_Unwind_Exception *);
|
||||
struct _Unwind_Exception *);
|
||||
|
||||
#if defined(__arm__) && !(defined(__USING_SJLJ_EXCEPTIONS__) || defined(__ARM_DWARF_EH___))
|
||||
typedef struct _Unwind_Control_Block _Unwind_Control_Block;
|
||||
typedef uint32_t _Unwind_EHT_Header;
|
||||
|
||||
struct _Unwind_Control_Block {
|
||||
uint64_t exception_class;
|
||||
void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block *);
|
||||
/* unwinder cache (private fields for the unwinder's use) */
|
||||
struct {
|
||||
uint32_t reserved1; /* forced unwind stop function, 0 if not forced */
|
||||
uint32_t reserved2; /* personality routine */
|
||||
uint32_t reserved3; /* callsite */
|
||||
uint32_t reserved4; /* forced unwind stop argument */
|
||||
uint32_t reserved5;
|
||||
} unwinder_cache;
|
||||
/* propagation barrier cache (valid after phase 1) */
|
||||
struct {
|
||||
uint32_t sp;
|
||||
uint32_t bitpattern[5];
|
||||
} barrier_cache;
|
||||
/* cleanup cache (preserved over cleanup) */
|
||||
struct {
|
||||
uint32_t bitpattern[4];
|
||||
} cleanup_cache;
|
||||
/* personality cache (for personality's benefit) */
|
||||
struct {
|
||||
uint32_t fnstart; /* function start address */
|
||||
_Unwind_EHT_Header *ehtp; /* pointer to EHT entry header word */
|
||||
uint32_t additional; /* additional data */
|
||||
uint32_t reserved1;
|
||||
} pr_cache;
|
||||
long long int : 0; /* force alignment of next item to 8-byte boundary */
|
||||
};
|
||||
#else
|
||||
struct _Unwind_Exception {
|
||||
_Unwind_Exception_Class exception_class;
|
||||
_Unwind_Exception_Cleanup_Fn exception_cleanup;
|
||||
@ -160,24 +120,23 @@ struct _Unwind_Exception {
|
||||
* aligned". GCC has interpreted this to mean "use the maximum useful
|
||||
* alignment for the target"; so do we. */
|
||||
} __attribute__((__aligned__));
|
||||
#endif
|
||||
|
||||
typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)(int, _Unwind_Action,
|
||||
_Unwind_Exception_Class,
|
||||
_Unwind_Exception *,
|
||||
struct _Unwind_Exception *,
|
||||
struct _Unwind_Context *,
|
||||
void *);
|
||||
|
||||
typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)(int, _Unwind_Action,
|
||||
_Unwind_Exception_Class,
|
||||
_Unwind_Exception *,
|
||||
typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)(
|
||||
int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *,
|
||||
struct _Unwind_Context *);
|
||||
typedef _Unwind_Personality_Fn __personality_routine;
|
||||
|
||||
typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn)(struct _Unwind_Context *,
|
||||
void *);
|
||||
|
||||
#if defined(__arm__) && !(defined(__USING_SJLJ_EXCEPTIONS__) || defined(__ARM_DWARF_EH___))
|
||||
#if defined(__arm__) && !defined(__APPLE__)
|
||||
|
||||
typedef enum {
|
||||
_UVRSC_CORE = 0, /* integer register */
|
||||
_UVRSC_VFP = 1, /* vfp */
|
||||
@ -199,12 +158,14 @@ typedef enum {
|
||||
_UVRSR_FAILED = 2
|
||||
} _Unwind_VRS_Result;
|
||||
|
||||
#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__ARM_DWARF_EH__)
|
||||
typedef uint32_t _Unwind_State;
|
||||
#define _US_VIRTUAL_UNWIND_FRAME ((_Unwind_State)0)
|
||||
#define _US_UNWIND_FRAME_STARTING ((_Unwind_State)1)
|
||||
#define _US_UNWIND_FRAME_RESUME ((_Unwind_State)2)
|
||||
#define _US_ACTION_MASK ((_Unwind_State)3)
|
||||
#define _US_FORCE_UNWIND ((_Unwind_State)8)
|
||||
#endif
|
||||
|
||||
_Unwind_VRS_Result _Unwind_VRS_Get(struct _Unwind_Context *__context,
|
||||
_Unwind_VRS_RegClass __regclass,
|
||||
@ -263,12 +224,13 @@ _Unwind_Ptr _Unwind_GetRegionStart(struct _Unwind_Context *);
|
||||
|
||||
/* DWARF EH functions; currently not available on Darwin/ARM */
|
||||
#if !defined(__APPLE__) || !defined(__arm__)
|
||||
_Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception *);
|
||||
_Unwind_Reason_Code _Unwind_ForcedUnwind(_Unwind_Exception *, _Unwind_Stop_Fn,
|
||||
void *);
|
||||
void _Unwind_DeleteException(_Unwind_Exception *);
|
||||
void _Unwind_Resume(_Unwind_Exception *);
|
||||
_Unwind_Reason_Code _Unwind_Resume_or_Rethrow(_Unwind_Exception *);
|
||||
|
||||
_Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception *);
|
||||
_Unwind_Reason_Code _Unwind_ForcedUnwind(struct _Unwind_Exception *,
|
||||
_Unwind_Stop_Fn, void *);
|
||||
void _Unwind_DeleteException(struct _Unwind_Exception *);
|
||||
void _Unwind_Resume(struct _Unwind_Exception *);
|
||||
_Unwind_Reason_Code _Unwind_Resume_or_Rethrow(struct _Unwind_Exception *);
|
||||
|
||||
#endif
|
||||
|
||||
@ -279,11 +241,11 @@ typedef struct SjLj_Function_Context *_Unwind_FunctionContext_t;
|
||||
|
||||
void _Unwind_SjLj_Register(_Unwind_FunctionContext_t);
|
||||
void _Unwind_SjLj_Unregister(_Unwind_FunctionContext_t);
|
||||
_Unwind_Reason_Code _Unwind_SjLj_RaiseException(_Unwind_Exception *);
|
||||
_Unwind_Reason_Code _Unwind_SjLj_ForcedUnwind(_Unwind_Exception *,
|
||||
_Unwind_Reason_Code _Unwind_SjLj_RaiseException(struct _Unwind_Exception *);
|
||||
_Unwind_Reason_Code _Unwind_SjLj_ForcedUnwind(struct _Unwind_Exception *,
|
||||
_Unwind_Stop_Fn, void *);
|
||||
void _Unwind_SjLj_Resume(_Unwind_Exception *);
|
||||
_Unwind_Reason_Code _Unwind_SjLj_Resume_or_Rethrow(_Unwind_Exception *);
|
||||
void _Unwind_SjLj_Resume(struct _Unwind_Exception *);
|
||||
_Unwind_Reason_Code _Unwind_SjLj_Resume_or_Rethrow(struct _Unwind_Exception *);
|
||||
|
||||
void *_Unwind_FindEnclosingFunction(void *);
|
||||
|
||||
|
@ -458,10 +458,16 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
|
||||
SourceMgr.setNumCreatedFIDsForFileID(CurPPLexer->getFileID(), NumFIDs);
|
||||
}
|
||||
|
||||
bool ExitedFromPredefinesFile = false;
|
||||
FileID ExitedFID;
|
||||
if (Callbacks && !isEndOfMacro && CurPPLexer)
|
||||
if (!isEndOfMacro && CurPPLexer) {
|
||||
ExitedFID = CurPPLexer->getFileID();
|
||||
|
||||
assert(PredefinesFileID.isValid() &&
|
||||
"HandleEndOfFile is called before PredefinesFileId is set");
|
||||
ExitedFromPredefinesFile = (PredefinesFileID == ExitedFID);
|
||||
}
|
||||
|
||||
if (LeavingSubmodule) {
|
||||
// We're done with this submodule.
|
||||
Module *M = LeaveSubmodule(/*ForPragma*/false);
|
||||
@ -489,6 +495,11 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
|
||||
PPCallbacks::ExitFile, FileType, ExitedFID);
|
||||
}
|
||||
|
||||
// Restore conditional stack from the preamble right after exiting from the
|
||||
// predefines file.
|
||||
if (ExitedFromPredefinesFile)
|
||||
replayPreambleConditionalStack();
|
||||
|
||||
// Client should lex another token unless we generated an EOM.
|
||||
return LeavingSubmodule;
|
||||
}
|
||||
|
@ -540,6 +540,8 @@ void Preprocessor::EnterMainSourceFile() {
|
||||
void Preprocessor::replayPreambleConditionalStack() {
|
||||
// Restore the conditional stack from the preamble, if there is one.
|
||||
if (PreambleConditionalStack.isReplaying()) {
|
||||
assert(CurPPLexer &&
|
||||
"CurPPLexer is null when calling replayPreambleConditionalStack.");
|
||||
CurPPLexer->setConditionalLevels(PreambleConditionalStack.getStack());
|
||||
PreambleConditionalStack.doneReplaying();
|
||||
}
|
||||
|
@ -516,8 +516,6 @@ void Parser::Initialize() {
|
||||
|
||||
// Prime the lexer look-ahead.
|
||||
ConsumeToken();
|
||||
|
||||
PP.replayPreambleConditionalStack();
|
||||
}
|
||||
|
||||
void Parser::LateTemplateParserCleanupCallback(void *P) {
|
||||
|
@ -5726,6 +5726,53 @@ static void DefineImplicitSpecialMember(Sema &S, CXXMethodDecl *MD,
|
||||
}
|
||||
}
|
||||
|
||||
/// Determine whether a type is permitted to be passed or returned in
|
||||
/// registers, per C++ [class.temporary]p3.
|
||||
static bool computeCanPassInRegisters(Sema &S, CXXRecordDecl *D) {
|
||||
if (D->isDependentType() || D->isInvalidDecl())
|
||||
return false;
|
||||
|
||||
// Per C++ [class.temporary]p3, the relevant condition is:
|
||||
// each copy constructor, move constructor, and destructor of X is
|
||||
// either trivial or deleted, and X has at least one non-deleted copy
|
||||
// or move constructor
|
||||
bool HasNonDeletedCopyOrMove = false;
|
||||
|
||||
if (D->needsImplicitCopyConstructor() &&
|
||||
!D->defaultedCopyConstructorIsDeleted()) {
|
||||
if (!D->hasTrivialCopyConstructor())
|
||||
return false;
|
||||
HasNonDeletedCopyOrMove = true;
|
||||
}
|
||||
|
||||
if (S.getLangOpts().CPlusPlus11 && D->needsImplicitMoveConstructor() &&
|
||||
!D->defaultedMoveConstructorIsDeleted()) {
|
||||
if (!D->hasTrivialMoveConstructor())
|
||||
return false;
|
||||
HasNonDeletedCopyOrMove = true;
|
||||
}
|
||||
|
||||
if (D->needsImplicitDestructor() && !D->defaultedDestructorIsDeleted() &&
|
||||
!D->hasTrivialDestructor())
|
||||
return false;
|
||||
|
||||
for (const CXXMethodDecl *MD : D->methods()) {
|
||||
if (MD->isDeleted())
|
||||
continue;
|
||||
|
||||
auto *CD = dyn_cast<CXXConstructorDecl>(MD);
|
||||
if (CD && CD->isCopyOrMoveConstructor())
|
||||
HasNonDeletedCopyOrMove = true;
|
||||
else if (!isa<CXXDestructorDecl>(MD))
|
||||
continue;
|
||||
|
||||
if (!MD->isTrivial())
|
||||
return false;
|
||||
}
|
||||
|
||||
return HasNonDeletedCopyOrMove;
|
||||
}
|
||||
|
||||
/// \brief Perform semantic checks on a class definition that has been
|
||||
/// completing, introducing implicitly-declared members, checking for
|
||||
/// abstract types, etc.
|
||||
@ -5870,6 +5917,8 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
|
||||
}
|
||||
|
||||
checkClassLevelDLLAttribute(Record);
|
||||
|
||||
Record->setCanPassInRegisters(computeCanPassInRegisters(*this, Record));
|
||||
}
|
||||
|
||||
/// Look up the special member function that would be called by a special
|
||||
@ -7496,8 +7545,7 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
|
||||
reinterpret_cast<Decl**>(FieldCollector->getCurFields()),
|
||||
FieldCollector->getCurNumFields()), LBrac, RBrac, AttrList);
|
||||
|
||||
CheckCompletedCXXClass(
|
||||
dyn_cast_or_null<CXXRecordDecl>(TagDecl));
|
||||
CheckCompletedCXXClass(dyn_cast_or_null<CXXRecordDecl>(TagDecl));
|
||||
}
|
||||
|
||||
/// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared
|
||||
@ -11929,8 +11977,10 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
|
||||
Scope *S = getScopeForContext(ClassDecl);
|
||||
CheckImplicitSpecialMemberDeclaration(S, CopyConstructor);
|
||||
|
||||
if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor))
|
||||
if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor)) {
|
||||
ClassDecl->setImplicitCopyConstructorIsDeleted();
|
||||
SetDeclDeleted(CopyConstructor, ClassLoc);
|
||||
}
|
||||
|
||||
if (S)
|
||||
PushOnScopeChains(CopyConstructor, S, false);
|
||||
|
@ -872,7 +872,7 @@ SelectPropertyForSynthesisFromProtocols(Sema &S, SourceLocation AtLoc,
|
||||
}
|
||||
|
||||
QualType RHSType = S.Context.getCanonicalType(Property->getType());
|
||||
unsigned OriginalAttributes = Property->getPropertyAttributes();
|
||||
unsigned OriginalAttributes = Property->getPropertyAttributesAsWritten();
|
||||
enum MismatchKind {
|
||||
IncompatibleType = 0,
|
||||
HasNoExpectedAttribute,
|
||||
@ -890,7 +890,7 @@ SelectPropertyForSynthesisFromProtocols(Sema &S, SourceLocation AtLoc,
|
||||
SmallVector<MismatchingProperty, 4> Mismatches;
|
||||
for (ObjCPropertyDecl *Prop : Properties) {
|
||||
// Verify the property attributes.
|
||||
unsigned Attr = Prop->getPropertyAttributes();
|
||||
unsigned Attr = Prop->getPropertyAttributesAsWritten();
|
||||
if (Attr != OriginalAttributes) {
|
||||
auto Diag = [&](bool OriginalHasAttribute, StringRef AttributeName) {
|
||||
MismatchKind Kind = OriginalHasAttribute ? HasNoExpectedAttribute
|
||||
|
@ -1559,9 +1559,11 @@ void ASTDeclReader::ReadCXXDefinitionData(
|
||||
Data.HasUninitializedFields = Record.readInt();
|
||||
Data.HasInheritedConstructor = Record.readInt();
|
||||
Data.HasInheritedAssignment = Record.readInt();
|
||||
Data.NeedOverloadResolutionForCopyConstructor = Record.readInt();
|
||||
Data.NeedOverloadResolutionForMoveConstructor = Record.readInt();
|
||||
Data.NeedOverloadResolutionForMoveAssignment = Record.readInt();
|
||||
Data.NeedOverloadResolutionForDestructor = Record.readInt();
|
||||
Data.DefaultedCopyConstructorIsDeleted = Record.readInt();
|
||||
Data.DefaultedMoveConstructorIsDeleted = Record.readInt();
|
||||
Data.DefaultedMoveAssignmentIsDeleted = Record.readInt();
|
||||
Data.DefaultedDestructorIsDeleted = Record.readInt();
|
||||
@ -1570,6 +1572,7 @@ void ASTDeclReader::ReadCXXDefinitionData(
|
||||
Data.HasIrrelevantDestructor = Record.readInt();
|
||||
Data.HasConstexprNonCopyMoveConstructor = Record.readInt();
|
||||
Data.HasDefaultedDefaultConstructor = Record.readInt();
|
||||
Data.CanPassInRegisters = Record.readInt();
|
||||
Data.DefaultedDefaultConstructorIsConstexpr = Record.readInt();
|
||||
Data.HasConstexprDefaultConstructor = Record.readInt();
|
||||
Data.HasNonLiteralTypeFieldsOrBases = Record.readInt();
|
||||
@ -1697,9 +1700,11 @@ void ASTDeclReader::MergeDefinitionData(
|
||||
MATCH_FIELD(HasUninitializedFields)
|
||||
MATCH_FIELD(HasInheritedConstructor)
|
||||
MATCH_FIELD(HasInheritedAssignment)
|
||||
MATCH_FIELD(NeedOverloadResolutionForCopyConstructor)
|
||||
MATCH_FIELD(NeedOverloadResolutionForMoveConstructor)
|
||||
MATCH_FIELD(NeedOverloadResolutionForMoveAssignment)
|
||||
MATCH_FIELD(NeedOverloadResolutionForDestructor)
|
||||
MATCH_FIELD(DefaultedCopyConstructorIsDeleted)
|
||||
MATCH_FIELD(DefaultedMoveConstructorIsDeleted)
|
||||
MATCH_FIELD(DefaultedMoveAssignmentIsDeleted)
|
||||
MATCH_FIELD(DefaultedDestructorIsDeleted)
|
||||
@ -1708,6 +1713,7 @@ void ASTDeclReader::MergeDefinitionData(
|
||||
MATCH_FIELD(HasIrrelevantDestructor)
|
||||
OR_FIELD(HasConstexprNonCopyMoveConstructor)
|
||||
OR_FIELD(HasDefaultedDefaultConstructor)
|
||||
MATCH_FIELD(CanPassInRegisters)
|
||||
MATCH_FIELD(DefaultedDefaultConstructorIsConstexpr)
|
||||
OR_FIELD(HasConstexprDefaultConstructor)
|
||||
MATCH_FIELD(HasNonLiteralTypeFieldsOrBases)
|
||||
|
@ -5874,9 +5874,11 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) {
|
||||
Record->push_back(Data.HasUninitializedFields);
|
||||
Record->push_back(Data.HasInheritedConstructor);
|
||||
Record->push_back(Data.HasInheritedAssignment);
|
||||
Record->push_back(Data.NeedOverloadResolutionForCopyConstructor);
|
||||
Record->push_back(Data.NeedOverloadResolutionForMoveConstructor);
|
||||
Record->push_back(Data.NeedOverloadResolutionForMoveAssignment);
|
||||
Record->push_back(Data.NeedOverloadResolutionForDestructor);
|
||||
Record->push_back(Data.DefaultedCopyConstructorIsDeleted);
|
||||
Record->push_back(Data.DefaultedMoveConstructorIsDeleted);
|
||||
Record->push_back(Data.DefaultedMoveAssignmentIsDeleted);
|
||||
Record->push_back(Data.DefaultedDestructorIsDeleted);
|
||||
@ -5885,6 +5887,7 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) {
|
||||
Record->push_back(Data.HasIrrelevantDestructor);
|
||||
Record->push_back(Data.HasConstexprNonCopyMoveConstructor);
|
||||
Record->push_back(Data.HasDefaultedDefaultConstructor);
|
||||
Record->push_back(Data.CanPassInRegisters);
|
||||
Record->push_back(Data.DefaultedDefaultConstructorIsConstexpr);
|
||||
Record->push_back(Data.HasConstexprDefaultConstructor);
|
||||
Record->push_back(Data.HasNonLiteralTypeFieldsOrBases);
|
||||
|
@ -409,6 +409,19 @@ class RegionStoreManager : public StoreManager {
|
||||
|
||||
// BindDefault is only used to initialize a region with a default value.
|
||||
StoreRef BindDefault(Store store, const MemRegion *R, SVal V) override {
|
||||
// FIXME: The offsets of empty bases can be tricky because of
|
||||
// of the so called "empty base class optimization".
|
||||
// If a base class has been optimized out
|
||||
// we should not try to create a binding, otherwise we should.
|
||||
// Unfortunately, at the moment ASTRecordLayout doesn't expose
|
||||
// the actual sizes of the empty bases
|
||||
// and trying to infer them from offsets/alignments
|
||||
// seems to be error-prone and non-trivial because of the trailing padding.
|
||||
// As a temporary mitigation we don't create bindings for empty bases.
|
||||
if (R->getKind() == MemRegion::CXXBaseObjectRegionKind &&
|
||||
cast<CXXBaseObjectRegion>(R)->getDecl()->isEmpty())
|
||||
return StoreRef(store, *this);
|
||||
|
||||
RegionBindingsRef B = getRegionBindings(store);
|
||||
assert(!B.lookup(R, BindingKey::Direct));
|
||||
|
||||
|
@ -36,8 +36,7 @@ struct GPR {
|
||||
struct FPR_i386 {
|
||||
uint16_t fctrl; // FPU Control Word (fcw)
|
||||
uint16_t fstat; // FPU Status Word (fsw)
|
||||
uint8_t ftag; // FPU Tag Word (ftw)
|
||||
uint8_t reserved_1; // Reserved
|
||||
uint16_t ftag; // FPU Tag Word (ftw)
|
||||
uint16_t fop; // Last Instruction Opcode (fop)
|
||||
union {
|
||||
struct {
|
||||
|
@ -257,8 +257,7 @@ struct XMMReg {
|
||||
struct FXSAVE {
|
||||
uint16_t fctrl; // FPU Control Word (fcw)
|
||||
uint16_t fstat; // FPU Status Word (fsw)
|
||||
uint8_t ftag; // FPU Tag Word (ftw)
|
||||
uint8_t reserved_1; // Reserved
|
||||
uint16_t ftag; // FPU Tag Word (ftw)
|
||||
uint16_t fop; // Last Instruction Opcode (fop)
|
||||
union {
|
||||
struct {
|
||||
|
@ -8,4 +8,4 @@
|
||||
|
||||
#define CLANG_VENDOR "FreeBSD "
|
||||
|
||||
#define SVN_REVISION "311219"
|
||||
#define SVN_REVISION "311606"
|
||||
|
@ -4,5 +4,5 @@
|
||||
#define LLD_VERSION_STRING "5.0.0"
|
||||
#define LLD_VERSION_MAJOR 5
|
||||
#define LLD_VERSION_MINOR 0
|
||||
#define LLD_REVISION_STRING "311219"
|
||||
#define LLD_REVISION_STRING "311606"
|
||||
#define LLD_REPOSITORY_STRING "FreeBSD"
|
||||
|
@ -1,2 +1,2 @@
|
||||
/* $FreeBSD$ */
|
||||
#define LLVM_REVISION "svn-r311219"
|
||||
#define LLVM_REVISION "svn-r311606"
|
||||
|
Loading…
Reference in New Issue
Block a user