Merge llvm, clang, compiler-rt, libc++, lld and lldb release_40 branch

r293807, and update build glue.
This commit is contained in:
Dimitry Andric 2017-02-01 21:57:07 +00:00
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/clang400-import/; revision=313067
46 changed files with 663 additions and 401 deletions

View File

@ -559,7 +559,6 @@ public:
#endif
template <class _Fp>
inline _LIBCPP_INLINE_VISIBILITY
void
__call_once_proxy(void* __vp)
{

View File

@ -480,6 +480,12 @@ class AsmPrinter : public MachineFunctionPass {
/// Get the value for DW_AT_APPLE_isa. Zero if no isa encoding specified.
virtual unsigned getISAEncoding() { return 0; }
/// Emit the directive and value for debug thread local expression
///
/// \p Value - The value to emit.
/// \p Size - The size of the integer (in bytes) to emit.
virtual void EmitDebugValue(const MCExpr *Value, unsigned Size) const;
//===------------------------------------------------------------------===//
// Dwarf Lowering Routines
//===------------------------------------------------------------------===//

View File

@ -305,7 +305,7 @@ class SelectionDAGISel : public MachineFunctionPass {
std::vector<unsigned> OpcodeOffset;
void UpdateChains(SDNode *NodeToMatch, SDValue InputChain,
const SmallVectorImpl<SDNode *> &ChainNodesMatched,
SmallVectorImpl<SDNode *> &ChainNodesMatched,
bool isMorphNodeTo);
};

View File

@ -567,6 +567,15 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
OutStreamer->AddBlankLine();
}
/// Emit the directive and value for debug thread local expression
///
/// \p Value - The value to emit.
/// \p Size - The size of the integer (in bytes) to emit.
void AsmPrinter::EmitDebugValue(const MCExpr *Value,
unsigned Size) const {
OutStreamer->EmitValue(Value, Size);
}
/// EmitFunctionHeader - This method emits the header for the current
/// function.
void AsmPrinter::EmitFunctionHeader() {

View File

@ -484,7 +484,7 @@ void DIEInteger::print(raw_ostream &O) const {
/// EmitValue - Emit expression value.
///
void DIEExpr::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {
AP->OutStreamer->EmitValue(Expr, SizeOf(AP, Form));
AP->EmitDebugValue(Expr, SizeOf(AP, Form));
}
/// SizeOf - Determine size of expression value in bytes.

View File

@ -174,7 +174,7 @@ static bool isDeInterleaveMask(ArrayRef<int> Mask, unsigned &Factor,
/// I.e. <0, LaneLen, ... , LaneLen*(Factor - 1), 1, LaneLen + 1, ...>
/// E.g. For a Factor of 2 (LaneLen=4): <0, 4, 1, 5, 2, 6, 3, 7>
static bool isReInterleaveMask(ArrayRef<int> Mask, unsigned &Factor,
unsigned MaxFactor) {
unsigned MaxFactor, unsigned OpNumElts) {
unsigned NumElts = Mask.size();
if (NumElts < 4)
return false;
@ -246,6 +246,9 @@ static bool isReInterleaveMask(ArrayRef<int> Mask, unsigned &Factor,
if (StartMask < 0)
break;
// We must stay within the vectors; This case can happen with undefs.
if (StartMask + LaneLen > OpNumElts*2)
break;
}
// Found an interleaved mask of current factor.
@ -406,7 +409,8 @@ bool InterleavedAccess::lowerInterleavedStore(
// Check if the shufflevector is RE-interleave shuffle.
unsigned Factor;
if (!isReInterleaveMask(SVI->getShuffleMask(), Factor, MaxFactor))
unsigned OpNumElts = SVI->getOperand(0)->getType()->getVectorNumElements();
if (!isReInterleaveMask(SVI->getShuffleMask(), Factor, MaxFactor, OpNumElts))
return false;
DEBUG(dbgs() << "IA: Found an interleaved store: " << *SI << "\n");

View File

@ -2248,7 +2248,7 @@ GetVBR(uint64_t Val, const unsigned char *MatcherTable, unsigned &Idx) {
/// to use the new results.
void SelectionDAGISel::UpdateChains(
SDNode *NodeToMatch, SDValue InputChain,
const SmallVectorImpl<SDNode *> &ChainNodesMatched, bool isMorphNodeTo) {
SmallVectorImpl<SDNode *> &ChainNodesMatched, bool isMorphNodeTo) {
SmallVector<SDNode*, 4> NowDeadNodes;
// Now that all the normal results are replaced, we replace the chain and
@ -2260,6 +2260,11 @@ void SelectionDAGISel::UpdateChains(
// Replace all the chain results with the final chain we ended up with.
for (unsigned i = 0, e = ChainNodesMatched.size(); i != e; ++i) {
SDNode *ChainNode = ChainNodesMatched[i];
// If ChainNode is null, it's because we replaced it on a previous
// iteration and we cleared it out of the map. Just skip it.
if (!ChainNode)
continue;
assert(ChainNode->getOpcode() != ISD::DELETED_NODE &&
"Deleted node left in chain");
@ -2272,6 +2277,11 @@ void SelectionDAGISel::UpdateChains(
if (ChainVal.getValueType() == MVT::Glue)
ChainVal = ChainVal.getValue(ChainVal->getNumValues()-2);
assert(ChainVal.getValueType() == MVT::Other && "Not a chain?");
SelectionDAG::DAGNodeDeletedListener NDL(
*CurDAG, [&](SDNode *N, SDNode *E) {
std::replace(ChainNodesMatched.begin(), ChainNodesMatched.end(), N,
static_cast<SDNode *>(nullptr));
});
CurDAG->ReplaceAllUsesOfValueWith(ChainVal, InputChain);
// If the node became dead and we haven't already seen it, delete it.

View File

@ -142,7 +142,8 @@ static bool canGoAfterDWARF(const MCSectionMachO &MSec) {
if (SegName == "__TEXT" && SecName == "__eh_frame")
return true;
if (SegName == "__DATA" && SecName == "__nl_symbol_ptr")
if (SegName == "__DATA" && (SecName == "__nl_symbol_ptr" ||
SecName == "__thread_ptr"))
return true;
return false;

View File

@ -413,6 +413,7 @@ class MipsAsmParser : public MCTargetAsmParser {
Match_RequiresDifferentOperands,
Match_RequiresNoZeroRegister,
Match_RequiresSameSrcAndDst,
Match_NoFCCRegisterForCurrentISA,
Match_NonZeroOperandForSync,
#define GET_OPERAND_DIAGNOSTIC_TYPES
#include "MipsGenAsmMatcher.inc"
@ -1461,8 +1462,6 @@ class MipsOperand : public MCParsedAsmOperand {
bool isFCCAsmReg() const {
if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
return false;
if (!AsmParser.hasEightFccRegisters())
return RegIdx.Index == 0;
return RegIdx.Index <= 7;
}
bool isACCAsmReg() const {
@ -4053,6 +4052,7 @@ MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
return Match_RequiresSameSrcAndDst;
}
}
unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
switch (Inst.getOpcode()) {
// As described by the MIPSR6 spec, daui must not use the zero operand for
@ -4131,9 +4131,15 @@ unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
return Match_RequiresDifferentOperands;
return Match_Success;
default:
return Match_Success;
}
uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
if ((TSFlags & MipsII::HasFCCRegOperand) &&
(Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
return Match_NoFCCRegisterForCurrentISA;
return Match_Success;
}
static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
@ -4191,6 +4197,9 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return Error(IDLoc, "invalid operand ($zero) for instruction");
case Match_RequiresSameSrcAndDst:
return Error(IDLoc, "source and destination must match");
case Match_NoFCCRegisterForCurrentISA:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"non-zero fcc register doesn't exist in current ISA level");
case Match_Immz:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
case Match_UImm1_0:

View File

@ -123,7 +123,9 @@ namespace MipsII {
HasForbiddenSlot = 1 << 5,
/// IsPCRelativeLoad - A Load instruction with implicit source register
/// ($pc) with explicit offset and destination register
IsPCRelativeLoad = 1 << 6
IsPCRelativeLoad = 1 << 6,
/// HasFCCRegOperand - Instruction uses an $fcc<x> register.
HasFCCRegOperand = 1 << 7
};
}

View File

@ -27,9 +27,20 @@ def SUXC1_MM : MMRel, SWXC1_FT<"suxc1", AFGR64Opnd, II_SUXC1>,
SWXC1_FM_MM<0x188>, INSN_MIPS5_32R2_NOT_32R6_64R6;
def FCMP_S32_MM : MMRel, CEQS_FT<"s", FGR32, II_C_CC_S, MipsFPCmp>,
CEQS_FM_MM<0>;
CEQS_FM_MM<0> {
// FIXME: This is a required to work around the fact that these instructions
// only use $fcc0. Ideally, MipsFPCmp nodes could be removed and the
// fcc register set is used directly.
bits<3> fcc = 0;
}
def FCMP_D32_MM : MMRel, CEQS_FT<"d", AFGR64, II_C_CC_D, MipsFPCmp>,
CEQS_FM_MM<1>;
CEQS_FM_MM<1> {
// FIXME: This is a required to work around the fact that these instructions
// only use $fcc0. Ideally, MipsFPCmp nodes could be removed and the
// fcc register set is used directly.
bits<3> fcc = 0;
}
def BC1F_MM : MMRel, BC1F_FT<"bc1f", brtarget_mm, II_BC1F, MIPS_BRANCH_F>,
BC1F_FM_MM<0x1c>, ISA_MIPS1_NOT_32R6_64R6;
@ -164,6 +175,98 @@ let AdditionalPredicates = [InMicroMips] in {
def SWC1_MM : MMRel, SW_FT<"swc1", FGR32Opnd, mem_mm_16, II_SWC1, store>,
LW_FM_MM<0x26>;
}
multiclass C_COND_MM<string TypeStr, RegisterOperand RC, bits<2> fmt,
InstrItinClass itin> {
def C_F_#NAME#_MM : MMRel, C_COND_FT<"f", TypeStr, RC, itin>,
C_COND_FM_MM<fmt, 0> {
let BaseOpcode = "c.f."#NAME;
let isCommutable = 1;
}
def C_UN_#NAME#_MM : MMRel, C_COND_FT<"un", TypeStr, RC, itin>,
C_COND_FM_MM<fmt, 1> {
let BaseOpcode = "c.un."#NAME;
let isCommutable = 1;
}
def C_EQ_#NAME#_MM : MMRel, C_COND_FT<"eq", TypeStr, RC, itin>,
C_COND_FM_MM<fmt, 2> {
let BaseOpcode = "c.eq."#NAME;
let isCommutable = 1;
}
def C_UEQ_#NAME#_MM : MMRel, C_COND_FT<"ueq", TypeStr, RC, itin>,
C_COND_FM_MM<fmt, 3> {
let BaseOpcode = "c.ueq."#NAME;
let isCommutable = 1;
}
def C_OLT_#NAME#_MM : MMRel, C_COND_FT<"olt", TypeStr, RC, itin>,
C_COND_FM_MM<fmt, 4> {
let BaseOpcode = "c.olt."#NAME;
}
def C_ULT_#NAME#_MM : MMRel, C_COND_FT<"ult", TypeStr, RC, itin>,
C_COND_FM_MM<fmt, 5> {
let BaseOpcode = "c.ult."#NAME;
}
def C_OLE_#NAME#_MM : MMRel, C_COND_FT<"ole", TypeStr, RC, itin>,
C_COND_FM_MM<fmt, 6> {
let BaseOpcode = "c.ole."#NAME;
}
def C_ULE_#NAME#_MM : MMRel, C_COND_FT<"ule", TypeStr, RC, itin>,
C_COND_FM_MM<fmt, 7> {
let BaseOpcode = "c.ule."#NAME;
}
def C_SF_#NAME#_MM : MMRel, C_COND_FT<"sf", TypeStr, RC, itin>,
C_COND_FM_MM<fmt, 8> {
let BaseOpcode = "c.sf."#NAME;
let isCommutable = 1;
}
def C_NGLE_#NAME#_MM : MMRel, C_COND_FT<"ngle", TypeStr, RC, itin>,
C_COND_FM_MM<fmt, 9> {
let BaseOpcode = "c.ngle."#NAME;
}
def C_SEQ_#NAME#_MM : MMRel, C_COND_FT<"seq", TypeStr, RC, itin>,
C_COND_FM_MM<fmt, 10> {
let BaseOpcode = "c.seq."#NAME;
let isCommutable = 1;
}
def C_NGL_#NAME#_MM : MMRel, C_COND_FT<"ngl", TypeStr, RC, itin>,
C_COND_FM_MM<fmt, 11> {
let BaseOpcode = "c.ngl."#NAME;
}
def C_LT_#NAME#_MM : MMRel, C_COND_FT<"lt", TypeStr, RC, itin>,
C_COND_FM_MM<fmt, 12> {
let BaseOpcode = "c.lt."#NAME;
}
def C_NGE_#NAME#_MM : MMRel, C_COND_FT<"nge", TypeStr, RC, itin>,
C_COND_FM_MM<fmt, 13> {
let BaseOpcode = "c.nge."#NAME;
}
def C_LE_#NAME#_MM : MMRel, C_COND_FT<"le", TypeStr, RC, itin>,
C_COND_FM_MM<fmt, 14> {
let BaseOpcode = "c.le."#NAME;
}
def C_NGT_#NAME#_MM : MMRel, C_COND_FT<"ngt", TypeStr, RC, itin>,
C_COND_FM_MM<fmt, 15> {
let BaseOpcode = "c.ngt."#NAME;
}
}
defm S : C_COND_MM<"s", FGR32Opnd, 0b00, II_C_CC_S>,
ISA_MIPS1_NOT_32R6_64R6;
defm D32 : C_COND_MM<"d", AFGR64Opnd, 0b01, II_C_CC_D>,
ISA_MIPS1_NOT_32R6_64R6, FGR_32;
let DecoderNamespace = "Mips64" in
defm D64 : C_COND_MM<"d", FGR64Opnd, 0b01, II_C_CC_D>,
ISA_MIPS1_NOT_32R6_64R6, FGR_64;
defm S_MM : C_COND_ALIASES<"s", FGR32Opnd>, HARDFLOAT,
ISA_MIPS1_NOT_32R6_64R6;
defm D32_MM : C_COND_ALIASES<"d", AFGR64Opnd>, HARDFLOAT,
ISA_MIPS1_NOT_32R6_64R6, FGR_32;
defm D64_MM : C_COND_ALIASES<"d", FGR64Opnd>, HARDFLOAT,
ISA_MIPS1_NOT_32R6_64R6, FGR_64;
defm : BC1_ALIASES<BC1T_MM, "bc1t", BC1F_MM, "bc1f">,
ISA_MIPS1_NOT_32R6_64R6, HARDFLOAT;
}
//===----------------------------------------------------------------------===//

View File

@ -766,6 +766,7 @@ class SWXC1_FM_MM<bits<9> funct> : MMArch {
class CEQS_FM_MM<bits<2> fmt> : MMArch {
bits<5> fs;
bits<5> ft;
bits<3> fcc;
bits<4> cond;
bits<32> Inst;
@ -773,13 +774,17 @@ class CEQS_FM_MM<bits<2> fmt> : MMArch {
let Inst{31-26} = 0x15;
let Inst{25-21} = ft;
let Inst{20-16} = fs;
let Inst{15-13} = 0x0; // cc
let Inst{15-13} = fcc;
let Inst{12} = 0;
let Inst{11-10} = fmt;
let Inst{9-6} = cond;
let Inst{5-0} = 0x3c;
}
class C_COND_FM_MM<bits <2> fmt, bits<4> c> : CEQS_FM_MM<fmt> {
let cond = c;
}
class BC1F_FM_MM<bits<5> tf> : MMArch {
bits<16> offset;

View File

@ -1037,6 +1037,22 @@ void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
// TODO: implement
}
// Emit .dtprelword or .dtpreldword directive
// and value for debug thread local expression.
void MipsAsmPrinter::EmitDebugValue(const MCExpr *Value,
unsigned Size) const {
switch (Size) {
case 4:
OutStreamer->EmitDTPRel32Value(Value);
break;
case 8:
OutStreamer->EmitDTPRel64Value(Value);
break;
default:
llvm_unreachable("Unexpected size of expression value.");
}
}
// Align all targets of indirect branches on bundle size. Used only if target
// is NaCl.
void MipsAsmPrinter::NaClAlignIndirectJumpTargets(MachineFunction &MF) {

View File

@ -140,6 +140,7 @@ class LLVM_LIBRARY_VISIBILITY MipsAsmPrinter : public AsmPrinter {
void EmitStartOfAsmFile(Module &M) override;
void EmitEndOfAsmFile(Module &M) override;
void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS);
void EmitDebugValue(const MCExpr *Value, unsigned Size) const override;
};
}

View File

@ -698,8 +698,8 @@ bool MipsFastISel::emitCmp(unsigned ResultReg, const CmpInst *CI) {
unsigned RegWithOne = createResultReg(&Mips::GPR32RegClass);
emitInst(Mips::ADDiu, RegWithZero).addReg(Mips::ZERO).addImm(0);
emitInst(Mips::ADDiu, RegWithOne).addReg(Mips::ZERO).addImm(1);
emitInst(Opc).addReg(LeftReg).addReg(RightReg).addReg(
Mips::FCC0, RegState::ImplicitDefine);
emitInst(Opc).addReg(Mips::FCC0, RegState::Define).addReg(LeftReg)
.addReg(RightReg);
emitInst(CondMovOpc, ResultReg)
.addReg(RegWithOne)
.addReg(Mips::FCC0)

View File

@ -219,6 +219,7 @@ class BC1F_FT<string opstr, DAGOperand opnd, InstrItinClass Itin,
let isTerminator = 1;
let hasDelaySlot = DelaySlot;
let Defs = [AT];
let hasFCCRegOperand = 1;
}
class CEQS_FT<string typestr, RegisterClass RC, InstrItinClass Itin,
@ -229,41 +230,106 @@ class CEQS_FT<string typestr, RegisterClass RC, InstrItinClass Itin,
!strconcat("c.$cond.", typestr)>, HARDFLOAT {
let Defs = [FCC0];
let isCodeGenOnly = 1;
let hasFCCRegOperand = 1;
}
// Note: MIPS-IV introduced $fcc1-$fcc7 and renamed FCSR31[23] $fcc0. Rather
// duplicating the instruction definition for MIPS1 - MIPS3, we expand
// c.cond.ft if necessary, and reject it after constructing the
// instruction if the ISA doesn't support it.
class C_COND_FT<string CondStr, string Typestr, RegisterOperand RC,
InstrItinClass itin> :
InstSE<(outs), (ins RC:$fs, RC:$ft),
!strconcat("c.", CondStr, ".", Typestr, "\t$fs, $ft"), [], itin,
FrmFR>, HARDFLOAT;
InstSE<(outs FCCRegsOpnd:$fcc), (ins RC:$fs, RC:$ft),
!strconcat("c.", CondStr, ".", Typestr, "\t$fcc, $fs, $ft"), [], itin,
FrmFR>, HARDFLOAT {
let isCompare = 1;
let hasFCCRegOperand = 1;
}
multiclass C_COND_M<string TypeStr, RegisterOperand RC, bits<5> fmt,
InstrItinClass itin> {
def C_F_#NAME : C_COND_FT<"f", TypeStr, RC, itin>, C_COND_FM<fmt, 0>;
def C_UN_#NAME : C_COND_FT<"un", TypeStr, RC, itin>, C_COND_FM<fmt, 1>;
def C_EQ_#NAME : C_COND_FT<"eq", TypeStr, RC, itin>, C_COND_FM<fmt, 2>;
def C_UEQ_#NAME : C_COND_FT<"ueq", TypeStr, RC, itin>, C_COND_FM<fmt, 3>;
def C_OLT_#NAME : C_COND_FT<"olt", TypeStr, RC, itin>, C_COND_FM<fmt, 4>;
def C_ULT_#NAME : C_COND_FT<"ult", TypeStr, RC, itin>, C_COND_FM<fmt, 5>;
def C_OLE_#NAME : C_COND_FT<"ole", TypeStr, RC, itin>, C_COND_FM<fmt, 6>;
def C_ULE_#NAME : C_COND_FT<"ule", TypeStr, RC, itin>, C_COND_FM<fmt, 7>;
def C_SF_#NAME : C_COND_FT<"sf", TypeStr, RC, itin>, C_COND_FM<fmt, 8>;
def C_NGLE_#NAME : C_COND_FT<"ngle", TypeStr, RC, itin>, C_COND_FM<fmt, 9>;
def C_SEQ_#NAME : C_COND_FT<"seq", TypeStr, RC, itin>, C_COND_FM<fmt, 10>;
def C_NGL_#NAME : C_COND_FT<"ngl", TypeStr, RC, itin>, C_COND_FM<fmt, 11>;
def C_LT_#NAME : C_COND_FT<"lt", TypeStr, RC, itin>, C_COND_FM<fmt, 12>;
def C_NGE_#NAME : C_COND_FT<"nge", TypeStr, RC, itin>, C_COND_FM<fmt, 13>;
def C_LE_#NAME : C_COND_FT<"le", TypeStr, RC, itin>, C_COND_FM<fmt, 14>;
def C_NGT_#NAME : C_COND_FT<"ngt", TypeStr, RC, itin>, C_COND_FM<fmt, 15>;
def C_F_#NAME : MMRel, C_COND_FT<"f", TypeStr, RC, itin>,
C_COND_FM<fmt, 0> {
let BaseOpcode = "c.f."#NAME;
let isCommutable = 1;
}
def C_UN_#NAME : MMRel, C_COND_FT<"un", TypeStr, RC, itin>,
C_COND_FM<fmt, 1> {
let BaseOpcode = "c.un."#NAME;
let isCommutable = 1;
}
def C_EQ_#NAME : MMRel, C_COND_FT<"eq", TypeStr, RC, itin>,
C_COND_FM<fmt, 2> {
let BaseOpcode = "c.eq."#NAME;
let isCommutable = 1;
}
def C_UEQ_#NAME : MMRel, C_COND_FT<"ueq", TypeStr, RC, itin>,
C_COND_FM<fmt, 3> {
let BaseOpcode = "c.ueq."#NAME;
let isCommutable = 1;
}
def C_OLT_#NAME : MMRel, C_COND_FT<"olt", TypeStr, RC, itin>,
C_COND_FM<fmt, 4> {
let BaseOpcode = "c.olt."#NAME;
}
def C_ULT_#NAME : MMRel, C_COND_FT<"ult", TypeStr, RC, itin>,
C_COND_FM<fmt, 5> {
let BaseOpcode = "c.ult."#NAME;
}
def C_OLE_#NAME : MMRel, C_COND_FT<"ole", TypeStr, RC, itin>,
C_COND_FM<fmt, 6> {
let BaseOpcode = "c.ole."#NAME;
}
def C_ULE_#NAME : MMRel, C_COND_FT<"ule", TypeStr, RC, itin>,
C_COND_FM<fmt, 7> {
let BaseOpcode = "c.ule."#NAME;
}
def C_SF_#NAME : MMRel, C_COND_FT<"sf", TypeStr, RC, itin>,
C_COND_FM<fmt, 8> {
let BaseOpcode = "c.sf."#NAME;
let isCommutable = 1;
}
def C_NGLE_#NAME : MMRel, C_COND_FT<"ngle", TypeStr, RC, itin>,
C_COND_FM<fmt, 9> {
let BaseOpcode = "c.ngle."#NAME;
}
def C_SEQ_#NAME : MMRel, C_COND_FT<"seq", TypeStr, RC, itin>,
C_COND_FM<fmt, 10> {
let BaseOpcode = "c.seq."#NAME;
let isCommutable = 1;
}
def C_NGL_#NAME : MMRel, C_COND_FT<"ngl", TypeStr, RC, itin>,
C_COND_FM<fmt, 11> {
let BaseOpcode = "c.ngl."#NAME;
}
def C_LT_#NAME : MMRel, C_COND_FT<"lt", TypeStr, RC, itin>,
C_COND_FM<fmt, 12> {
let BaseOpcode = "c.lt."#NAME;
}
def C_NGE_#NAME : MMRel, C_COND_FT<"nge", TypeStr, RC, itin>,
C_COND_FM<fmt, 13> {
let BaseOpcode = "c.nge."#NAME;
}
def C_LE_#NAME : MMRel, C_COND_FT<"le", TypeStr, RC, itin>,
C_COND_FM<fmt, 14> {
let BaseOpcode = "c.le."#NAME;
}
def C_NGT_#NAME : MMRel, C_COND_FT<"ngt", TypeStr, RC, itin>,
C_COND_FM<fmt, 15> {
let BaseOpcode = "c.ngt."#NAME;
}
}
let AdditionalPredicates = [NotInMicroMips] in {
defm S : C_COND_M<"s", FGR32Opnd, 16, II_C_CC_S>, ISA_MIPS1_NOT_32R6_64R6;
defm D32 : C_COND_M<"d", AFGR64Opnd, 17, II_C_CC_D>, ISA_MIPS1_NOT_32R6_64R6,
FGR_32;
let DecoderNamespace = "Mips64" in
defm D64 : C_COND_M<"d", FGR64Opnd, 17, II_C_CC_D>, ISA_MIPS1_NOT_32R6_64R6,
FGR_64;
}
//===----------------------------------------------------------------------===//
// Floating Point Instructions
//===----------------------------------------------------------------------===//
@ -549,13 +615,29 @@ def BC1TL : MMRel, BC1F_FT<"bc1tl", brtarget, II_BC1TL, MIPS_BRANCH_T, 0>,
/// Floating Point Compare
let AdditionalPredicates = [NotInMicroMips] in {
def FCMP_S32 : MMRel, CEQS_FT<"s", FGR32, II_C_CC_S, MipsFPCmp>, CEQS_FM<16>,
ISA_MIPS1_NOT_32R6_64R6;
ISA_MIPS1_NOT_32R6_64R6 {
// FIXME: This is a required to work around the fact that these instructions
// only use $fcc0. Ideally, MipsFPCmp nodes could be removed and the
// fcc register set is used directly.
bits<3> fcc = 0;
}
def FCMP_D32 : MMRel, CEQS_FT<"d", AFGR64, II_C_CC_D, MipsFPCmp>, CEQS_FM<17>,
ISA_MIPS1_NOT_32R6_64R6, FGR_32;
ISA_MIPS1_NOT_32R6_64R6, FGR_32 {
// FIXME: This is a required to work around the fact that these instructions
// only use $fcc0. Ideally, MipsFPCmp nodes could be removed and the
// fcc register set is used directly.
bits<3> fcc = 0;
}
}
let DecoderNamespace = "Mips64" in
def FCMP_D64 : CEQS_FT<"d", FGR64, II_C_CC_D, MipsFPCmp>, CEQS_FM<17>,
ISA_MIPS1_NOT_32R6_64R6, FGR_64;
ISA_MIPS1_NOT_32R6_64R6, FGR_64 {
// FIXME: This is a required to work around the fact that thiese instructions
// only use $fcc0. Ideally, MipsFPCmp nodes could be removed and the
// fcc register set is used directly.
bits<3> fcc = 0;
}
//===----------------------------------------------------------------------===//
// Floating Point Pseudo-Instructions
@ -602,15 +684,6 @@ def PseudoTRUNC_W_D : MipsAsmPseudoInst<(outs FGR32Opnd:$fd),
//===----------------------------------------------------------------------===//
// InstAliases.
//===----------------------------------------------------------------------===//
def : MipsInstAlias<"bc1t $offset", (BC1T FCC0, brtarget:$offset)>,
ISA_MIPS1_NOT_32R6_64R6, HARDFLOAT;
def : MipsInstAlias<"bc1tl $offset", (BC1TL FCC0, brtarget:$offset)>,
ISA_MIPS2_NOT_32R6_64R6, HARDFLOAT;
def : MipsInstAlias<"bc1f $offset", (BC1F FCC0, brtarget:$offset)>,
ISA_MIPS1_NOT_32R6_64R6, HARDFLOAT;
def : MipsInstAlias<"bc1fl $offset", (BC1FL FCC0, brtarget:$offset)>,
ISA_MIPS2_NOT_32R6_64R6, HARDFLOAT;
def : MipsInstAlias
<"s.s $fd, $addr", (SWC1 FGR32Opnd:$fd, mem_simm16:$addr), 0>,
ISA_MIPS2, HARDFLOAT;
@ -630,6 +703,80 @@ def : MipsInstAlias
def : MipsInstAlias
<"l.d $fd, $addr", (LDC164 FGR64Opnd:$fd, mem_simm16:$addr), 0>,
FGR_64, ISA_MIPS2, HARDFLOAT;
multiclass C_COND_ALIASES<string TypeStr, RegisterOperand RC> {
def : MipsInstAlias<!strconcat("c.f.", TypeStr, " $fs, $ft"),
(!cast<Instruction>("C_F_"#NAME) FCC0,
RC:$fs, RC:$ft), 1>;
def : MipsInstAlias<!strconcat("c.un.", TypeStr, " $fs, $ft"),
(!cast<Instruction>("C_UN_"#NAME) FCC0,
RC:$fs, RC:$ft), 1>;
def : MipsInstAlias<!strconcat("c.eq.", TypeStr, " $fs, $ft"),
(!cast<Instruction>("C_EQ_"#NAME) FCC0,
RC:$fs, RC:$ft), 1>;
def : MipsInstAlias<!strconcat("c.ueq.", TypeStr, " $fs, $ft"),
(!cast<Instruction>("C_UEQ_"#NAME) FCC0,
RC:$fs, RC:$ft), 1>;
def : MipsInstAlias<!strconcat("c.olt.", TypeStr, " $fs, $ft"),
(!cast<Instruction>("C_OLT_"#NAME) FCC0,
RC:$fs, RC:$ft), 1>;
def : MipsInstAlias<!strconcat("c.ult.", TypeStr, " $fs, $ft"),
(!cast<Instruction>("C_ULT_"#NAME) FCC0,
RC:$fs, RC:$ft), 1>;
def : MipsInstAlias<!strconcat("c.ole.", TypeStr, " $fs, $ft"),
(!cast<Instruction>("C_OLE_"#NAME) FCC0,
RC:$fs, RC:$ft), 1>;
def : MipsInstAlias<!strconcat("c.ule.", TypeStr, " $fs, $ft"),
(!cast<Instruction>("C_ULE_"#NAME) FCC0,
RC:$fs, RC:$ft), 1>;
def : MipsInstAlias<!strconcat("c.sf.", TypeStr, " $fs, $ft"),
(!cast<Instruction>("C_SF_"#NAME) FCC0,
RC:$fs, RC:$ft), 1>;
def : MipsInstAlias<!strconcat("c.ngle.", TypeStr, " $fs, $ft"),
(!cast<Instruction>("C_NGLE_"#NAME) FCC0,
RC:$fs, RC:$ft), 1>;
def : MipsInstAlias<!strconcat("c.seq.", TypeStr, " $fs, $ft"),
(!cast<Instruction>("C_SEQ_"#NAME) FCC0,
RC:$fs, RC:$ft), 1>;
def : MipsInstAlias<!strconcat("c.ngl.", TypeStr, " $fs, $ft"),
(!cast<Instruction>("C_NGL_"#NAME) FCC0,
RC:$fs, RC:$ft), 1>;
def : MipsInstAlias<!strconcat("c.lt.", TypeStr, " $fs, $ft"),
(!cast<Instruction>("C_LT_"#NAME) FCC0,
RC:$fs, RC:$ft), 1>;
def : MipsInstAlias<!strconcat("c.nge.", TypeStr, " $fs, $ft"),
(!cast<Instruction>("C_NGE_"#NAME) FCC0,
RC:$fs, RC:$ft), 1>;
def : MipsInstAlias<!strconcat("c.le.", TypeStr, " $fs, $ft"),
(!cast<Instruction>("C_LE_"#NAME) FCC0,
RC:$fs, RC:$ft), 1>;
def : MipsInstAlias<!strconcat("c.ngt.", TypeStr, " $fs, $ft"),
(!cast<Instruction>("C_NGT_"#NAME) FCC0,
RC:$fs, RC:$ft), 1>;
}
multiclass BC1_ALIASES<Instruction BCTrue, string BCTrueString,
Instruction BCFalse, string BCFalseString> {
def : MipsInstAlias<!strconcat(BCTrueString, " $offset"),
(BCTrue FCC0, brtarget:$offset), 1>;
def : MipsInstAlias<!strconcat(BCFalseString, " $offset"),
(BCFalse FCC0, brtarget:$offset), 1>;
}
let AdditionalPredicates = [NotInMicroMips] in {
defm S : C_COND_ALIASES<"s", FGR32Opnd>, HARDFLOAT,
ISA_MIPS1_NOT_32R6_64R6;
defm D32 : C_COND_ALIASES<"d", AFGR64Opnd>, HARDFLOAT,
ISA_MIPS1_NOT_32R6_64R6, FGR_32;
defm D64 : C_COND_ALIASES<"d", FGR64Opnd>, HARDFLOAT,
ISA_MIPS1_NOT_32R6_64R6, FGR_64;
defm : BC1_ALIASES<BC1T, "bc1t", BC1F, "bc1f">, ISA_MIPS1_NOT_32R6_64R6,
HARDFLOAT;
defm : BC1_ALIASES<BC1TL, "bc1tl", BC1FL, "bc1fl">, ISA_MIPS2_NOT_32R6_64R6,
HARDFLOAT;
}
//===----------------------------------------------------------------------===//
// Floating Point Patterns
//===----------------------------------------------------------------------===//

View File

@ -101,12 +101,15 @@ class MipsInst<dag outs, dag ins, string asmstr, list<dag> pattern,
bit IsPCRelativeLoad = 0; // Load instruction with implicit source register
// ($pc) and with explicit offset and destination
// register
bit hasFCCRegOperand = 0; // Instruction uses $fcc<X> register and is
// present in MIPS-I to MIPS-III.
// TSFlags layout should be kept in sync with MipsInstrInfo.h.
// TSFlags layout should be kept in sync with MCTargetDesc/MipsBaseInfo.h.
let TSFlags{3-0} = FormBits;
let TSFlags{4} = isCTI;
let TSFlags{5} = hasForbiddenSlot;
let TSFlags{6} = IsPCRelativeLoad;
let TSFlags{7} = hasFCCRegOperand;
let DecoderNamespace = "Mips";
@ -829,6 +832,7 @@ class BC1F_FM<bit nd, bit tf> : StdArch {
class CEQS_FM<bits<5> fmt> : StdArch {
bits<5> fs;
bits<5> ft;
bits<3> fcc;
bits<4> cond;
bits<32> Inst;
@ -837,7 +841,7 @@ class CEQS_FM<bits<5> fmt> : StdArch {
let Inst{25-21} = fmt;
let Inst{20-16} = ft;
let Inst{15-11} = fs;
let Inst{10-8} = 0; // cc
let Inst{10-8} = fcc;
let Inst{7-4} = 0x3;
let Inst{3-0} = cond;
}

View File

@ -148,3 +148,11 @@ MCSection *MipsTargetObjectFile::getSectionForConstant(const DataLayout &DL,
// Otherwise, we work the same as ELF.
return TargetLoweringObjectFileELF::getSectionForConstant(DL, Kind, C, Align);
}
const MCExpr *
MipsTargetObjectFile::getDebugThreadLocalSymbol(const MCSymbol *Sym) const {
const MCExpr *Expr =
MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
return MCBinaryExpr::createAdd(
Expr, MCConstantExpr::create(0x8000, getContext()), getContext());
}

View File

@ -42,6 +42,8 @@ class MipsTargetMachine;
MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind,
const Constant *C,
unsigned &Align) const override;
/// Describe a TLS variable address within debug info.
const MCExpr *getDebugThreadLocalSymbol(const MCSymbol *Sym) const override;
};
} // end namespace llvm

View File

@ -1508,8 +1508,14 @@ def DCBTST : DCB_Form_hint<246, (outs), (ins u5imm:$TH, memrr:$dst),
PPC970_DGroup_Single;
} // hasSideEffects = 0
def ICBLC : XForm_icbt<31, 230, (outs), (ins u4imm:$CT, memrr:$src),
"icblc $CT, $src", IIC_LdStStore>, Requires<[HasICBT]>;
def ICBLQ : XForm_icbt<31, 198, (outs), (ins u4imm:$CT, memrr:$src),
"icblq. $CT, $src", IIC_LdStLoad>, Requires<[HasICBT]>;
def ICBT : XForm_icbt<31, 22, (outs), (ins u4imm:$CT, memrr:$src),
"icbt $CT, $src", IIC_LdStLoad>, Requires<[HasICBT]>;
def ICBTLS : XForm_icbt<31, 486, (outs), (ins u4imm:$CT, memrr:$src),
"icbtls $CT, $src", IIC_LdStLoad>, Requires<[HasICBT]>;
def : Pat<(int_ppc_dcbt xoaddr:$dst),
(DCBT 0, xoaddr:$dst)>;
@ -2381,6 +2387,13 @@ def MTSPR : XFXForm_1<31, 467, (outs), (ins i32imm:$SPR, gprc:$RT),
def MFTB : XFXForm_1<31, 371, (outs gprc:$RT), (ins i32imm:$SPR),
"mftb $RT, $SPR", IIC_SprMFTB>;
def MFPMR : XFXForm_1<31, 334, (outs gprc:$RT), (ins i32imm:$SPR),
"mfpmr $RT, $SPR", IIC_SprMFPMR>;
def MTPMR : XFXForm_1<31, 462, (outs), (ins i32imm:$SPR, gprc:$RT),
"mtpmr $SPR, $RT", IIC_SprMTPMR>;
// A pseudo-instruction used to implement the read of the 64-bit cycle counter
// on a 32-bit target.
let hasSideEffects = 1, usesCustomInserter = 1 in

View File

@ -118,6 +118,8 @@ def IIC_SprTLBIE : InstrItinClass;
def IIC_SprABORT : InstrItinClass;
def IIC_SprMSGSYNC : InstrItinClass;
def IIC_SprSTOP : InstrItinClass;
def IIC_SprMFPMR : InstrItinClass;
def IIC_SprMTPMR : InstrItinClass;
//===----------------------------------------------------------------------===//
// Processor instruction itineraries.

View File

@ -249,6 +249,10 @@ def PPCE500mcItineraries : ProcessorItineraries<
InstrStage<5, [E500_SFX0]>],
[8, 1],
[E500_GPR_Bypass, E500_CR_Bypass]>,
InstrItinData<IIC_SprMFPMR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>,
InstrStage<4, [E500_SFX0]>],
[7, 1], // Latency = 4, Repeat rate = 4
[E500_GPR_Bypass, E500_GPR_Bypass]>,
InstrItinData<IIC_SprMFMSR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>,
InstrStage<4, [E500_SFX0]>],
[7, 1], // Latency = 4, Repeat rate = 4
@ -257,6 +261,10 @@ def PPCE500mcItineraries : ProcessorItineraries<
InstrStage<1, [E500_SFX0, E500_SFX1]>],
[4, 1], // Latency = 1, Repeat rate = 1
[E500_GPR_Bypass, E500_CR_Bypass]>,
InstrItinData<IIC_SprMTPMR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>,
InstrStage<1, [E500_SFX0]>],
[4, 1], // Latency = 1, Repeat rate = 1
[E500_CR_Bypass, E500_GPR_Bypass]>,
InstrItinData<IIC_SprMFTB, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>,
InstrStage<4, [E500_SFX0]>],
[7, 1], // Latency = 4, Repeat rate = 4

View File

@ -313,20 +313,24 @@ def PPCE5500Itineraries : ProcessorItineraries<
InstrStage<5, [E5500_CFX_0]>],
[9, 2], // Latency = 5, Repeat rate = 5
[E5500_GPR_Bypass, E5500_CR_Bypass]>,
InstrItinData<IIC_SprMFMSR, [InstrStage<1, [E5500_DIS0, E5500_DIS1], 0>,
InstrStage<4, [E5500_SFX0]>],
InstrItinData<IIC_SprMFPMR, [InstrStage<1, [E5500_DIS0, E5500_DIS1], 0>,
InstrStage<4, [E5500_CFX_0]>],
[8, 2], // Latency = 4, Repeat rate = 4
[E5500_GPR_Bypass, E5500_GPR_Bypass]>,
InstrItinData<IIC_SprMFSPR, [InstrStage<1, [E5500_DIS0, E5500_DIS1], 0>,
InstrStage<1, [E5500_CFX_0]>],
[5], // Latency = 1, Repeat rate = 1
[E5500_GPR_Bypass]>,
InstrItinData<IIC_SprMTPMR, [InstrStage<1, [E5500_DIS0, E5500_DIS1], 0>,
InstrStage<1, [E5500_CFX_0]>],
[5], // Latency = 1, Repeat rate = 1
[E5500_GPR_Bypass]>,
InstrItinData<IIC_SprMFTB, [InstrStage<1, [E5500_DIS0, E5500_DIS1], 0>,
InstrStage<4, [E5500_CFX_0]>],
[8, 2], // Latency = 4, Repeat rate = 4
[NoBypass, E5500_GPR_Bypass]>,
InstrItinData<IIC_SprMTSPR, [InstrStage<1, [E5500_DIS0, E5500_DIS1], 0>,
InstrStage<1, [E5500_SFX0, E5500_SFX1]>],
InstrStage<1, [E5500_CFX_0]>],
[5], // Latency = 1, Repeat rate = 1
[E5500_GPR_Bypass]>,
InstrItinData<IIC_FPGeneral, [InstrStage<1, [E5500_DIS0, E5500_DIS1], 0>,

View File

@ -884,6 +884,10 @@ static Instruction *transformToIndexedCompare(GEPOperator *GEPLHS, Value *RHS,
if (!GEPLHS->hasAllConstantIndices())
return nullptr;
// Make sure the pointers have the same type.
if (GEPLHS->getType() != RHS->getType())
return nullptr;
Value *PtrBase, *Index;
std::tie(PtrBase, Index) = getAsConstantIndexedAddress(GEPLHS, DL);

View File

@ -502,7 +502,8 @@ static Instruction *combineLoadToOperationType(InstCombiner &IC, LoadInst &LI) {
!DL.isNonIntegralPointerType(Ty)) {
if (all_of(LI.users(), [&LI](User *U) {
auto *SI = dyn_cast<StoreInst>(U);
return SI && SI->getPointerOperand() != &LI;
return SI && SI->getPointerOperand() != &LI &&
!SI->getPointerOperand()->isSwiftError();
})) {
LoadInst *NewLoad = combineLoadToNewType(
IC, LI,

View File

@ -1705,7 +1705,10 @@ static bool runIPSCCP(Module &M, const DataLayout &DL,
// If this is an exact definition of this function, then we can propagate
// information about its result into callsites of it.
if (F.hasExactDefinition())
// Don't touch naked functions. They may contain asm returning a
// value we don't see, so we may end up interprocedurally propagating
// the return value incorrectly.
if (F.hasExactDefinition() && !F.hasFnAttribute(Attribute::Naked))
Solver.AddTrackedFunction(&F);
// If this function only has direct calls that we can see, we can track its

View File

@ -3827,13 +3827,13 @@ class AttributedType : public Type, public llvm::FoldingSetNode {
friend class ASTContext; // creates these
AttributedType(QualType canon, Kind attrKind,
QualType modified, QualType equivalent)
: Type(Attributed, canon, canon->isDependentType(),
canon->isInstantiationDependentType(),
canon->isVariablyModifiedType(),
canon->containsUnexpandedParameterPack()),
ModifiedType(modified), EquivalentType(equivalent) {
AttributedType(QualType canon, Kind attrKind, QualType modified,
QualType equivalent)
: Type(Attributed, canon, equivalent->isDependentType(),
equivalent->isInstantiationDependentType(),
equivalent->isVariablyModifiedType(),
equivalent->containsUnexpandedParameterPack()),
ModifiedType(modified), EquivalentType(equivalent) {
AttributedTypeBits.AttrKind = attrKind;
}

View File

@ -3373,7 +3373,8 @@ def note_ovl_candidate_has_pass_object_size_params: Note<
"candidate address cannot be taken because parameter %0 has "
"pass_object_size attribute">;
def err_diagnose_if_succeeded : Error<"%0">;
def warn_diagnose_if_succeeded : Warning<"%0">, InGroup<UserDefinedWarnings>;
def warn_diagnose_if_succeeded : Warning<"%0">, InGroup<UserDefinedWarnings>,
ShowInSystemHeader;
def note_ovl_candidate_disabled_by_function_cond_attr : Note<
"candidate disabled: %0">;
def note_ovl_candidate_disabled_by_extension : Note<

View File

@ -675,26 +675,6 @@ namespace clang {
/// to be used while performing partial ordering of function templates.
unsigned ExplicitCallArguments;
/// The number of diagnose_if attributes that this overload triggered.
/// If any of the triggered attributes are errors, this won't count
/// diagnose_if warnings.
unsigned NumTriggeredDiagnoseIfs = 0;
/// Basically a TinyPtrVector<DiagnoseIfAttr *> that doesn't own the vector:
/// If NumTriggeredDiagnoseIfs is 0 or 1, this is a DiagnoseIfAttr *,
/// otherwise it's a pointer to an array of `NumTriggeredDiagnoseIfs`
/// DiagnoseIfAttr *s.
llvm::PointerUnion<DiagnoseIfAttr *, DiagnoseIfAttr **> DiagnoseIfInfo;
/// Gets an ArrayRef for the data at DiagnoseIfInfo. Note that this may give
/// you a pointer into DiagnoseIfInfo.
ArrayRef<DiagnoseIfAttr *> getDiagnoseIfInfo() const {
auto *Ptr = NumTriggeredDiagnoseIfs <= 1
? DiagnoseIfInfo.getAddrOfPtr1()
: DiagnoseIfInfo.get<DiagnoseIfAttr **>();
return {Ptr, NumTriggeredDiagnoseIfs};
}
union {
DeductionFailureInfo DeductionFailure;
@ -759,9 +739,8 @@ namespace clang {
SmallVector<OverloadCandidate, 16> Candidates;
llvm::SmallPtrSet<Decl *, 16> Functions;
// Allocator for ConversionSequenceLists and DiagnoseIfAttr* arrays.
// We store the first few of each of these inline to avoid allocation for
// small sets.
// Allocator for ConversionSequenceLists. We store the first few of these
// inline to avoid allocation for small sets.
llvm::BumpPtrAllocator SlabAllocator;
SourceLocation Loc;
@ -776,6 +755,8 @@ namespace clang {
/// from the slab allocator.
/// FIXME: It would probably be nice to have a SmallBumpPtrAllocator
/// instead.
/// FIXME: Now that this only allocates ImplicitConversionSequences, do we
/// want to un-generalize this?
template <typename T>
T *slabAllocate(unsigned N) {
// It's simpler if this doesn't need to consider alignment.
@ -809,11 +790,6 @@ namespace clang {
SourceLocation getLocation() const { return Loc; }
CandidateSetKind getKind() const { return Kind; }
/// Make a DiagnoseIfAttr* array in a block of memory that will live for
/// as long as this OverloadCandidateSet. Returns a pointer to the start
/// of that array.
DiagnoseIfAttr **addDiagnoseIfComplaints(ArrayRef<DiagnoseIfAttr *> CA);
/// \brief Determine when this overload candidate will be new to the
/// overload set.
bool isNewCandidate(Decl *F) {

View File

@ -2532,14 +2532,14 @@ class Sema {
void AddMethodCandidate(DeclAccessPair FoundDecl,
QualType ObjectType,
Expr::Classification ObjectClassification,
Expr *ThisArg, ArrayRef<Expr *> Args,
ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversion = false);
void AddMethodCandidate(CXXMethodDecl *Method,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext, QualType ObjectType,
Expr::Classification ObjectClassification,
Expr *ThisArg, ArrayRef<Expr *> Args,
ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false,
bool PartialOverloading = false,
@ -2550,7 +2550,6 @@ class Sema {
TemplateArgumentListInfo *ExplicitTemplateArgs,
QualType ObjectType,
Expr::Classification ObjectClassification,
Expr *ThisArg,
ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false,
@ -2624,37 +2623,27 @@ class Sema {
EnableIfAttr *CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
bool MissingImplicitThis = false);
/// Check the diagnose_if attributes on the given function. Returns the
/// first succesful fatal attribute, or null if calling Function(Args) isn't
/// an error.
/// Emit diagnostics for the diagnose_if attributes on Function, ignoring any
/// non-ArgDependent DiagnoseIfAttrs.
///
/// This only considers ArgDependent DiagnoseIfAttrs.
/// Argument-dependent diagnose_if attributes should be checked each time a
/// function is used as a direct callee of a function call.
///
/// This will populate Nonfatal with all non-error DiagnoseIfAttrs that
/// succeed. If this function returns non-null, the contents of Nonfatal are
/// unspecified.
DiagnoseIfAttr *
checkArgDependentDiagnoseIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
SmallVectorImpl<DiagnoseIfAttr *> &Nonfatal,
bool MissingImplicitThis = false,
Expr *ThisArg = nullptr);
/// Returns true if any errors were emitted.
bool diagnoseArgDependentDiagnoseIfAttrs(const FunctionDecl *Function,
const Expr *ThisArg,
ArrayRef<const Expr *> Args,
SourceLocation Loc);
/// Check the diagnose_if expressions on the given function. Returns the
/// first succesful fatal attribute, or null if using Function isn't
/// an error.
/// Emit diagnostics for the diagnose_if attributes on Function, ignoring any
/// ArgDependent DiagnoseIfAttrs.
///
/// This ignores all ArgDependent DiagnoseIfAttrs.
/// Argument-independent diagnose_if attributes should be checked on every use
/// of a function.
///
/// This will populate Nonfatal with all non-error DiagnoseIfAttrs that
/// succeed. If this function returns non-null, the contents of Nonfatal are
/// unspecified.
DiagnoseIfAttr *
checkArgIndependentDiagnoseIf(FunctionDecl *Function,
SmallVectorImpl<DiagnoseIfAttr *> &Nonfatal);
/// Emits the diagnostic contained in the given DiagnoseIfAttr at Loc. Also
/// emits a note about the location of said attribute.
void emitDiagnoseIfDiagnostic(SourceLocation Loc, const DiagnoseIfAttr *DIA);
/// Returns true if any errors were emitted.
bool diagnoseArgIndependentDiagnoseIfAttrs(const FunctionDecl *Function,
SourceLocation Loc);
/// Returns whether the given function's address can be taken or not,
/// optionally emitting a diagnostic if the address can't be taken.
@ -9914,8 +9903,8 @@ class Sema {
SourceLocation Loc);
void checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
ArrayRef<const Expr *> Args, bool IsMemberFunction,
SourceLocation Loc, SourceRange Range,
const Expr *ThisArg, ArrayRef<const Expr *> Args,
bool IsMemberFunction, SourceLocation Loc, SourceRange Range,
VariadicCallType CallType);
bool CheckObjCString(Expr *Arg);

View File

@ -2362,7 +2362,14 @@ static unsigned getBaseIndex(const CXXRecordDecl *Derived,
/// Extract the value of a character from a string literal.
static APSInt extractStringLiteralCharacter(EvalInfo &Info, const Expr *Lit,
uint64_t Index) {
// FIXME: Support ObjCEncodeExpr, MakeStringConstant
// FIXME: Support MakeStringConstant
if (const auto *ObjCEnc = dyn_cast<ObjCEncodeExpr>(Lit)) {
std::string Str;
Info.Ctx.getObjCEncodingForType(ObjCEnc->getEncodedType(), Str);
assert(Index <= Str.size() && "Index too large");
return APSInt::getUnsigned(Str.c_str()[Index]);
}
if (auto PE = dyn_cast<PredefinedExpr>(Lit))
Lit = PE->getFunctionName();
const StringLiteral *S = cast<StringLiteral>(Lit);

View File

@ -737,7 +737,7 @@ CodeGenTypes::getCGRecordLayout(const RecordDecl *RD) {
}
bool CodeGenTypes::isPointerZeroInitializable(QualType T) {
assert (T->isAnyPointerType() && "Invalid type");
assert((T->isAnyPointerType() || T->isBlockPointerType()) && "Invalid type");
return isZeroInitializable(T);
}

View File

@ -2426,11 +2426,12 @@ static void CheckNonNullArguments(Sema &S,
}
/// Handles the checks for format strings, non-POD arguments to vararg
/// functions, and NULL arguments passed to non-NULL parameters.
/// functions, NULL arguments passed to non-NULL parameters, and diagnose_if
/// attributes.
void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
ArrayRef<const Expr *> Args, bool IsMemberFunction,
SourceLocation Loc, SourceRange Range,
VariadicCallType CallType) {
const Expr *ThisArg, ArrayRef<const Expr *> Args,
bool IsMemberFunction, SourceLocation Loc,
SourceRange Range, VariadicCallType CallType) {
// FIXME: We should check as much as we can in the template definition.
if (CurContext->isDependentContext())
return;
@ -2477,6 +2478,9 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
CheckArgumentWithTypeTag(I, Args.data());
}
}
if (FD)
diagnoseArgDependentDiagnoseIfAttrs(FD, ThisArg, Args, Loc);
}
/// CheckConstructorCall - Check a constructor call for correctness and safety
@ -2487,8 +2491,8 @@ void Sema::CheckConstructorCall(FunctionDecl *FDecl,
SourceLocation Loc) {
VariadicCallType CallType =
Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply;
checkCall(FDecl, Proto, Args, /*IsMemberFunction=*/true, Loc, SourceRange(),
CallType);
checkCall(FDecl, Proto, /*ThisArg=*/nullptr, Args, /*IsMemberFunction=*/true,
Loc, SourceRange(), CallType);
}
/// CheckFunctionCall - Check a direct function call for various correctness
@ -2503,14 +2507,20 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
TheCall->getCallee());
Expr** Args = TheCall->getArgs();
unsigned NumArgs = TheCall->getNumArgs();
Expr *ImplicitThis = nullptr;
if (IsMemberOperatorCall) {
// If this is a call to a member operator, hide the first argument
// from checkCall.
// FIXME: Our choice of AST representation here is less than ideal.
ImplicitThis = Args[0];
++Args;
--NumArgs;
}
checkCall(FDecl, Proto, llvm::makeArrayRef(Args, NumArgs),
} else if (IsMemberFunction)
ImplicitThis =
cast<CXXMemberCallExpr>(TheCall)->getImplicitObjectArgument();
checkCall(FDecl, Proto, ImplicitThis, llvm::makeArrayRef(Args, NumArgs),
IsMemberFunction, TheCall->getRParenLoc(),
TheCall->getCallee()->getSourceRange(), CallType);
@ -2546,8 +2556,8 @@ bool Sema::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation lbrac,
VariadicCallType CallType =
Method->isVariadic() ? VariadicMethod : VariadicDoesNotApply;
checkCall(Method, nullptr, Args,
/*IsMemberFunction=*/false, lbrac, Method->getSourceRange(),
checkCall(Method, nullptr, /*ThisArg=*/nullptr, Args,
/*IsMemberFunction=*/false, lbrac, Method->getSourceRange(),
CallType);
return false;
@ -2576,7 +2586,7 @@ bool Sema::CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall,
CallType = VariadicFunction;
}
checkCall(NDecl, Proto,
checkCall(NDecl, Proto, /*ThisArg=*/nullptr,
llvm::makeArrayRef(TheCall->getArgs(), TheCall->getNumArgs()),
/*IsMemberFunction=*/false, TheCall->getRParenLoc(),
TheCall->getCallee()->getSourceRange(), CallType);
@ -2589,7 +2599,7 @@ bool Sema::CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall,
bool Sema::CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto) {
VariadicCallType CallType = getVariadicCallType(/*FDecl=*/nullptr, Proto,
TheCall->getCallee());
checkCall(/*FDecl=*/nullptr, Proto,
checkCall(/*FDecl=*/nullptr, Proto, /*ThisArg=*/nullptr,
llvm::makeArrayRef(TheCall->getArgs(), TheCall->getNumArgs()),
/*IsMemberFunction=*/false, TheCall->getRParenLoc(),
TheCall->getCallee()->getSourceRange(), CallType);

View File

@ -342,7 +342,6 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
}
// See if this is a deleted function.
SmallVector<DiagnoseIfAttr *, 4> DiagnoseIfWarnings;
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->isDeleted()) {
auto *Ctor = dyn_cast<CXXConstructorDecl>(FD);
@ -365,11 +364,8 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
if (getLangOpts().CUDA && !CheckCUDACall(Loc, FD))
return true;
if (const DiagnoseIfAttr *A =
checkArgIndependentDiagnoseIf(FD, DiagnoseIfWarnings)) {
emitDiagnoseIfDiagnostic(Loc, A);
if (diagnoseArgIndependentDiagnoseIfAttrs(FD, Loc))
return true;
}
}
// [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
@ -385,9 +381,6 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
return true;
}
for (const auto *W : DiagnoseIfWarnings)
emitDiagnoseIfDiagnostic(Loc, W);
DiagnoseAvailabilityOfDecl(*this, D, Loc, UnknownObjCClass,
ObjCPropertyAccess);
@ -5189,16 +5182,6 @@ static void checkDirectCallValidity(Sema &S, const Expr *Fn,
<< Attr->getCond()->getSourceRange() << Attr->getMessage();
return;
}
SmallVector<DiagnoseIfAttr *, 4> Nonfatal;
if (const DiagnoseIfAttr *Attr = S.checkArgDependentDiagnoseIf(
Callee, ArgExprs, Nonfatal, /*MissingImplicitThis=*/true)) {
S.emitDiagnoseIfDiagnostic(Fn->getLocStart(), Attr);
return;
}
for (const auto *W : Nonfatal)
S.emitDiagnoseIfDiagnostic(Fn->getLocStart(), W);
}
/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.

View File

@ -6712,6 +6712,11 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl,
CXXMemberCallExpr *CE =
new (Context) CXXMemberCallExpr(Context, ME, None, ResultType, VK,
Exp.get()->getLocEnd());
if (CheckFunctionCall(Method, CE,
Method->getType()->castAs<FunctionProtoType>()))
return ExprError();
return CE;
}

View File

@ -2960,7 +2960,6 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,
if (CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(Cand->getUnderlyingDecl())) {
if (SM == CXXCopyAssignment || SM == CXXMoveAssignment)
AddMethodCandidate(M, Cand, RD, ThisTy, Classification,
/*ThisArg=*/nullptr,
llvm::makeArrayRef(&Arg, NumArgs), OCS, true);
else if (CtorInfo)
AddOverloadCandidate(CtorInfo.Constructor, CtorInfo.FoundDecl,
@ -2973,7 +2972,7 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,
if (SM == CXXCopyAssignment || SM == CXXMoveAssignment)
AddMethodTemplateCandidate(
Tmpl, Cand, RD, nullptr, ThisTy, Classification,
/*ThisArg=*/nullptr, llvm::makeArrayRef(&Arg, NumArgs), OCS, true);
llvm::makeArrayRef(&Arg, NumArgs), OCS, true);
else if (CtorInfo)
AddTemplateOverloadCandidate(
CtorInfo.ConstructorTmpl, CtorInfo.FoundDecl, nullptr,

View File

@ -839,20 +839,12 @@ void OverloadCandidateSet::destroyCandidates() {
void OverloadCandidateSet::clear() {
destroyCandidates();
// DiagnoseIfAttrs are just pointers, so we don't need to destroy them.
SlabAllocator.Reset();
NumInlineBytesUsed = 0;
Candidates.clear();
Functions.clear();
}
DiagnoseIfAttr **
OverloadCandidateSet::addDiagnoseIfComplaints(ArrayRef<DiagnoseIfAttr *> CA) {
auto *DIA = slabAllocate<DiagnoseIfAttr *>(CA.size());
std::uninitialized_copy(CA.begin(), CA.end(), DIA);
return DIA;
}
namespace {
class UnbridgedCastsSet {
struct Entry {
@ -5831,28 +5823,6 @@ static bool IsAcceptableNonMemberOperatorCandidate(ASTContext &Context,
return false;
}
static void initDiagnoseIfComplaint(Sema &S, OverloadCandidateSet &CandidateSet,
OverloadCandidate &Candidate,
FunctionDecl *Function,
ArrayRef<Expr *> Args,
bool MissingImplicitThis = false,
Expr *ExplicitThis = nullptr) {
SmallVector<DiagnoseIfAttr *, 8> Results;
if (DiagnoseIfAttr *DIA = S.checkArgDependentDiagnoseIf(
Function, Args, Results, MissingImplicitThis, ExplicitThis)) {
Results.clear();
Results.push_back(DIA);
}
Candidate.NumTriggeredDiagnoseIfs = Results.size();
if (Results.empty())
Candidate.DiagnoseIfInfo = nullptr;
else if (Results.size() == 1)
Candidate.DiagnoseIfInfo = Results[0];
else
Candidate.DiagnoseIfInfo = CandidateSet.addDiagnoseIfComplaints(Results);
}
/// AddOverloadCandidate - Adds the given function to the set of
/// candidate functions, using the given function call arguments. If
/// @p SuppressUserConversions, then don't allow user-defined
@ -5886,10 +5856,9 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
// object argument (C++ [over.call.func]p3), and the acting context
// is irrelevant.
AddMethodCandidate(Method, FoundDecl, Method->getParent(), QualType(),
Expr::Classification::makeSimpleLValue(),
/*ThisArg=*/nullptr, Args, CandidateSet,
SuppressUserConversions, PartialOverloading,
EarlyConversions);
Expr::Classification::makeSimpleLValue(), Args,
CandidateSet, SuppressUserConversions,
PartialOverloading, EarlyConversions);
return;
}
// We treat a constructor like a non-member function, since its object
@ -6050,8 +6019,6 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
Candidate.FailureKind = ovl_fail_ext_disabled;
return;
}
initDiagnoseIfComplaint(*this, CandidateSet, Candidate, Function, Args);
}
ObjCMethodDecl *
@ -6260,85 +6227,73 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
return nullptr;
}
static bool gatherDiagnoseIfAttrs(FunctionDecl *Function, bool ArgDependent,
SmallVectorImpl<DiagnoseIfAttr *> &Errors,
SmallVectorImpl<DiagnoseIfAttr *> &Nonfatal) {
for (auto *DIA : Function->specific_attrs<DiagnoseIfAttr>())
if (ArgDependent == DIA->getArgDependent()) {
if (DIA->isError())
Errors.push_back(DIA);
else
Nonfatal.push_back(DIA);
}
return !Errors.empty() || !Nonfatal.empty();
}
template <typename CheckFn>
static DiagnoseIfAttr *
checkDiagnoseIfAttrsWith(const SmallVectorImpl<DiagnoseIfAttr *> &Errors,
SmallVectorImpl<DiagnoseIfAttr *> &Nonfatal,
CheckFn &&IsSuccessful) {
static bool diagnoseDiagnoseIfAttrsWith(Sema &S, const FunctionDecl *FD,
bool ArgDependent, SourceLocation Loc,
CheckFn &&IsSuccessful) {
SmallVector<const DiagnoseIfAttr *, 8> Attrs;
for (const auto *DIA : FD->specific_attrs<DiagnoseIfAttr>()) {
if (ArgDependent == DIA->getArgDependent())
Attrs.push_back(DIA);
}
// Common case: No diagnose_if attributes, so we can quit early.
if (Attrs.empty())
return false;
auto WarningBegin = std::stable_partition(
Attrs.begin(), Attrs.end(),
[](const DiagnoseIfAttr *DIA) { return DIA->isError(); });
// Note that diagnose_if attributes are late-parsed, so they appear in the
// correct order (unlike enable_if attributes).
auto ErrAttr = llvm::find_if(Errors, IsSuccessful);
if (ErrAttr != Errors.end())
return *ErrAttr;
auto ErrAttr = llvm::find_if(llvm::make_range(Attrs.begin(), WarningBegin),
IsSuccessful);
if (ErrAttr != WarningBegin) {
const DiagnoseIfAttr *DIA = *ErrAttr;
S.Diag(Loc, diag::err_diagnose_if_succeeded) << DIA->getMessage();
S.Diag(DIA->getLocation(), diag::note_from_diagnose_if)
<< DIA->getParent() << DIA->getCond()->getSourceRange();
return true;
}
llvm::erase_if(Nonfatal, [&](DiagnoseIfAttr *A) { return !IsSuccessful(A); });
return nullptr;
for (const auto *DIA : llvm::make_range(WarningBegin, Attrs.end()))
if (IsSuccessful(DIA)) {
S.Diag(Loc, diag::warn_diagnose_if_succeeded) << DIA->getMessage();
S.Diag(DIA->getLocation(), diag::note_from_diagnose_if)
<< DIA->getParent() << DIA->getCond()->getSourceRange();
}
return false;
}
DiagnoseIfAttr *
Sema::checkArgDependentDiagnoseIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
SmallVectorImpl<DiagnoseIfAttr *> &Nonfatal,
bool MissingImplicitThis,
Expr *ThisArg) {
SmallVector<DiagnoseIfAttr *, 4> Errors;
if (!gatherDiagnoseIfAttrs(Function, /*ArgDependent=*/true, Errors, Nonfatal))
return nullptr;
SFINAETrap Trap(*this);
SmallVector<Expr *, 16> ConvertedArgs;
Expr *ConvertedThis;
if (!convertArgsForAvailabilityChecks(*this, Function, ThisArg, Args, Trap,
MissingImplicitThis, ConvertedThis,
ConvertedArgs))
return nullptr;
return checkDiagnoseIfAttrsWith(Errors, Nonfatal, [&](DiagnoseIfAttr *DIA) {
APValue Result;
// It's sane to use the same ConvertedArgs for any redecl of this function,
// since EvaluateWithSubstitution only cares about the position of each
// argument in the arg list, not the ParmVarDecl* it maps to.
if (!DIA->getCond()->EvaluateWithSubstitution(
Result, Context, DIA->getParent(), ConvertedArgs, ConvertedThis))
return false;
return Result.isInt() && Result.getInt().getBoolValue();
});
bool Sema::diagnoseArgDependentDiagnoseIfAttrs(const FunctionDecl *Function,
const Expr *ThisArg,
ArrayRef<const Expr *> Args,
SourceLocation Loc) {
return diagnoseDiagnoseIfAttrsWith(
*this, Function, /*ArgDependent=*/true, Loc,
[&](const DiagnoseIfAttr *DIA) {
APValue Result;
// It's sane to use the same Args for any redecl of this function, since
// EvaluateWithSubstitution only cares about the position of each
// argument in the arg list, not the ParmVarDecl* it maps to.
if (!DIA->getCond()->EvaluateWithSubstitution(
Result, Context, DIA->getParent(), Args, ThisArg))
return false;
return Result.isInt() && Result.getInt().getBoolValue();
});
}
DiagnoseIfAttr *Sema::checkArgIndependentDiagnoseIf(
FunctionDecl *Function, SmallVectorImpl<DiagnoseIfAttr *> &Nonfatal) {
SmallVector<DiagnoseIfAttr *, 4> Errors;
if (!gatherDiagnoseIfAttrs(Function, /*ArgDependent=*/false, Errors,
Nonfatal))
return nullptr;
return checkDiagnoseIfAttrsWith(Errors, Nonfatal, [&](DiagnoseIfAttr *DIA) {
bool Result;
return DIA->getCond()->EvaluateAsBooleanCondition(Result, Context) &&
Result;
});
}
void Sema::emitDiagnoseIfDiagnostic(SourceLocation Loc,
const DiagnoseIfAttr *DIA) {
auto Code = DIA->isError() ? diag::err_diagnose_if_succeeded
: diag::warn_diagnose_if_succeeded;
Diag(Loc, Code) << DIA->getMessage();
Diag(DIA->getLocation(), diag::note_from_diagnose_if)
<< DIA->getParent() << DIA->getCond()->getSourceRange();
bool Sema::diagnoseArgIndependentDiagnoseIfAttrs(const FunctionDecl *Function,
SourceLocation Loc) {
return diagnoseDiagnoseIfAttrsWith(
*this, Function, /*ArgDependent=*/false, Loc,
[&](const DiagnoseIfAttr *DIA) {
bool Result;
return DIA->getCond()->EvaluateAsBooleanCondition(Result, Context) &&
Result;
});
}
/// \brief Add all of the function declarations in the given function set to
@ -6356,8 +6311,8 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(),
cast<CXXMethodDecl>(FD)->getParent(),
Args[0]->getType(), Args[0]->Classify(Context),
Args[0], Args.slice(1), CandidateSet,
SuppressUserConversions, PartialOverloading);
Args.slice(1), CandidateSet, SuppressUserConversions,
PartialOverloading);
else
AddOverloadCandidate(FD, F.getPair(), Args, CandidateSet,
SuppressUserConversions, PartialOverloading);
@ -6369,7 +6324,7 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
FunTmpl, F.getPair(),
cast<CXXRecordDecl>(FunTmpl->getDeclContext()),
ExplicitTemplateArgs, Args[0]->getType(),
Args[0]->Classify(Context), Args[0], Args.slice(1), CandidateSet,
Args[0]->Classify(Context), Args.slice(1), CandidateSet,
SuppressUserConversions, PartialOverloading);
else
AddTemplateOverloadCandidate(FunTmpl, F.getPair(),
@ -6385,7 +6340,6 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
void Sema::AddMethodCandidate(DeclAccessPair FoundDecl,
QualType ObjectType,
Expr::Classification ObjectClassification,
Expr *ThisArg,
ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions) {
@ -6399,15 +6353,13 @@ void Sema::AddMethodCandidate(DeclAccessPair FoundDecl,
assert(isa<CXXMethodDecl>(TD->getTemplatedDecl()) &&
"Expected a member function template");
AddMethodTemplateCandidate(TD, FoundDecl, ActingContext,
/*ExplicitArgs*/ nullptr,
ObjectType, ObjectClassification,
ThisArg, Args, CandidateSet,
/*ExplicitArgs*/ nullptr, ObjectType,
ObjectClassification, Args, CandidateSet,
SuppressUserConversions);
} else {
AddMethodCandidate(cast<CXXMethodDecl>(Decl), FoundDecl, ActingContext,
ObjectType, ObjectClassification,
ThisArg, Args,
CandidateSet, SuppressUserConversions);
ObjectType, ObjectClassification, Args, CandidateSet,
SuppressUserConversions);
}
}
@ -6422,7 +6374,7 @@ void
Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext, QualType ObjectType,
Expr::Classification ObjectClassification,
Expr *ThisArg, ArrayRef<Expr *> Args,
ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet,
bool SuppressUserConversions,
bool PartialOverloading,
@ -6544,9 +6496,6 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
Candidate.DeductionFailure.Data = FailedAttr;
return;
}
initDiagnoseIfComplaint(*this, CandidateSet, Candidate, Method, Args,
/*MissingImplicitThis=*/!ThisArg, ThisArg);
}
/// \brief Add a C++ member function template as a candidate to the candidate
@ -6559,7 +6508,6 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
TemplateArgumentListInfo *ExplicitTemplateArgs,
QualType ObjectType,
Expr::Classification ObjectClassification,
Expr *ThisArg,
ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions,
@ -6613,9 +6561,9 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
assert(isa<CXXMethodDecl>(Specialization) &&
"Specialization is not a member function?");
AddMethodCandidate(cast<CXXMethodDecl>(Specialization), FoundDecl,
ActingContext, ObjectType, ObjectClassification,
/*ThisArg=*/ThisArg, Args, CandidateSet,
SuppressUserConversions, PartialOverloading, Conversions);
ActingContext, ObjectType, ObjectClassification, Args,
CandidateSet, SuppressUserConversions, PartialOverloading,
Conversions);
}
/// \brief Add a C++ function template specialization as a candidate
@ -6942,8 +6890,6 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
Candidate.DeductionFailure.Data = FailedAttr;
return;
}
initDiagnoseIfComplaint(*this, CandidateSet, Candidate, Conversion, None, false, From);
}
/// \brief Adds a conversion function template specialization
@ -7096,8 +7042,6 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
Candidate.DeductionFailure.Data = FailedAttr;
return;
}
initDiagnoseIfComplaint(*this, CandidateSet, Candidate, Conversion, None);
}
/// \brief Add overload candidates for overloaded operators that are
@ -7146,7 +7090,7 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op,
Oper != OperEnd;
++Oper)
AddMethodCandidate(Oper.getPair(), Args[0]->getType(),
Args[0]->Classify(Context), Args[0], Args.slice(1),
Args[0]->Classify(Context), Args.slice(1),
CandidateSet, /*SuppressUserConversions=*/false);
}
}
@ -9178,17 +9122,6 @@ void Sema::diagnoseEquivalentInternalLinkageDeclarations(
}
}
static bool isCandidateUnavailableDueToDiagnoseIf(const OverloadCandidate &OC) {
ArrayRef<DiagnoseIfAttr *> Info = OC.getDiagnoseIfInfo();
if (!Info.empty() && Info[0]->isError())
return true;
assert(llvm::all_of(Info,
[](const DiagnoseIfAttr *A) { return !A->isError(); }) &&
"DiagnoseIf info shouldn't have mixed warnings and errors.");
return false;
}
/// \brief Computes the best viable function (C++ 13.3.3)
/// within an overload candidate set.
///
@ -9267,19 +9200,13 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
// Best is the best viable function.
if (Best->Function &&
(Best->Function->isDeleted() ||
S.isFunctionConsideredUnavailable(Best->Function) ||
isCandidateUnavailableDueToDiagnoseIf(*Best)))
S.isFunctionConsideredUnavailable(Best->Function)))
return OR_Deleted;
if (!EquivalentCands.empty())
S.diagnoseEquivalentInternalLinkageDeclarations(Loc, Best->Function,
EquivalentCands);
for (const auto *W : Best->getDiagnoseIfInfo()) {
assert(W->isWarning() && "Errors should've been caught earlier!");
S.emitDiagnoseIfDiagnostic(Loc, W);
}
return OR_Success;
}
@ -10162,14 +10089,6 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
if (isCandidateUnavailableDueToDiagnoseIf(*Cand)) {
auto *A = Cand->DiagnoseIfInfo.get<DiagnoseIfAttr *>();
assert(A->isError() && "Non-error diagnose_if disables a candidate?");
S.Diag(Cand->Function->getLocation(),
diag::note_ovl_candidate_disabled_by_function_cond_attr)
<< A->getCond()->getSourceRange() << A->getMessage();
return;
}
// We don't really have anything else to say about viable candidates.
S.NoteOverloadCandidate(Cand->FoundDecl, Fn);
@ -12113,6 +12032,10 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall, FnDecl))
return ExprError();
if (CheckFunctionCall(FnDecl, TheCall,
FnDecl->getType()->castAs<FunctionProtoType>()))
return ExprError();
return MaybeBindToTemporary(TheCall);
} else {
// We matched a built-in operator. Convert the arguments, then
@ -12343,16 +12266,20 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
return ExprError();
ArrayRef<const Expr *> ArgsArray(Args, 2);
const Expr *ImplicitThis = nullptr;
// Cut off the implicit 'this'.
if (isa<CXXMethodDecl>(FnDecl))
if (isa<CXXMethodDecl>(FnDecl)) {
ImplicitThis = ArgsArray[0];
ArgsArray = ArgsArray.slice(1);
}
// Check for a self move.
if (Op == OO_Equal)
DiagnoseSelfMove(Args[0], Args[1], OpLoc);
checkCall(FnDecl, nullptr, ArgsArray, isa<CXXMethodDecl>(FnDecl), OpLoc,
TheCall->getSourceRange(), VariadicDoesNotApply);
checkCall(FnDecl, nullptr, ImplicitThis, ArgsArray,
isa<CXXMethodDecl>(FnDecl), OpLoc, TheCall->getSourceRange(),
VariadicDoesNotApply);
return MaybeBindToTemporary(TheCall);
} else {
@ -12561,6 +12488,10 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
if (CheckCallReturnType(FnDecl->getReturnType(), LLoc, TheCall, FnDecl))
return ExprError();
if (CheckFunctionCall(Method, TheCall,
Method->getType()->castAs<FunctionProtoType>()))
return ExprError();
return MaybeBindToTemporary(TheCall);
} else {
// We matched a built-in operator. Convert the arguments, then
@ -12727,16 +12658,6 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
TemplateArgs = &TemplateArgsBuffer;
}
// Poor-programmer's Lazy<Expr *>; isImplicitAccess requires stripping
// parens/casts, which would be nice to avoid potentially doing multiple
// times.
llvm::Optional<Expr *> UnresolvedBase;
auto GetUnresolvedBase = [&] {
if (!UnresolvedBase.hasValue())
UnresolvedBase =
UnresExpr->isImplicitAccess() ? nullptr : UnresExpr->getBase();
return *UnresolvedBase;
};
for (UnresolvedMemberExpr::decls_iterator I = UnresExpr->decls_begin(),
E = UnresExpr->decls_end(); I != E; ++I) {
@ -12757,14 +12678,12 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
continue;
AddMethodCandidate(Method, I.getPair(), ActingDC, ObjectType,
ObjectClassification,
/*ThisArg=*/GetUnresolvedBase(), Args, CandidateSet,
ObjectClassification, Args, CandidateSet,
/*SuppressUserConversions=*/false);
} else {
AddMethodTemplateCandidate(
cast<FunctionTemplateDecl>(Func), I.getPair(), ActingDC,
TemplateArgs, ObjectType, ObjectClassification,
/*ThisArg=*/GetUnresolvedBase(), Args, CandidateSet,
TemplateArgs, ObjectType, ObjectClassification, Args, CandidateSet,
/*SuppressUsedConversions=*/false);
}
}
@ -12882,16 +12801,6 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
<< Attr->getCond()->getSourceRange() << Attr->getMessage();
return ExprError();
}
SmallVector<DiagnoseIfAttr *, 4> Nonfatal;
if (const DiagnoseIfAttr *Attr = checkArgDependentDiagnoseIf(
Method, Args, Nonfatal, false, MemE->getBase())) {
emitDiagnoseIfDiagnostic(MemE->getMemberLoc(), Attr);
return ExprError();
}
for (const auto *Attr : Nonfatal)
emitDiagnoseIfDiagnostic(MemE->getMemberLoc(), Attr);
}
if ((isa<CXXConstructorDecl>(CurContext) ||
@ -12970,9 +12879,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
Oper != OperEnd; ++Oper) {
AddMethodCandidate(Oper.getPair(), Object.get()->getType(),
Object.get()->Classify(Context),
Object.get(), Args, CandidateSet,
/*SuppressUserConversions=*/ false);
Object.get()->Classify(Context), Args, CandidateSet,
/*SuppressUserConversions=*/false);
}
// C++ [over.call.object]p2:
@ -13247,8 +13155,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
Oper != OperEnd; ++Oper) {
AddMethodCandidate(Oper.getPair(), Base->getType(), Base->Classify(Context),
Base, None, CandidateSet,
/*SuppressUserConversions=*/false);
None, CandidateSet, /*SuppressUserConversions=*/false);
}
bool HadMultipleCandidates = (CandidateSet.size() > 1);
@ -13322,7 +13229,11 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
Base, ResultTy, VK, OpLoc, false);
if (CheckCallReturnType(Method->getReturnType(), OpLoc, TheCall, Method))
return ExprError();
return ExprError();
if (CheckFunctionCall(Method, TheCall,
Method->getType()->castAs<FunctionProtoType>()))
return ExprError();
return MaybeBindToTemporary(TheCall);
}

View File

@ -4996,8 +4996,12 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
NamedDecl *Result = nullptr;
// FIXME: If the name is a dependent name, this lookup won't necessarily
// find it. Does that ever matter?
if (D->getDeclName()) {
DeclContext::lookup_result Found = ParentDC->lookup(D->getDeclName());
if (auto Name = D->getDeclName()) {
DeclarationNameInfo NameInfo(Name, D->getLocation());
Name = SubstDeclarationNameInfo(NameInfo, TemplateArgs).getName();
if (!Name)
return nullptr;
DeclContext::lookup_result Found = ParentDC->lookup(Name);
Result = findInstantiationOf(Context, D, Found.begin(), Found.end());
} else {
// Since we don't have a name for the entity we're looking for,

View File

@ -8818,12 +8818,18 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
// base (and therefore couldn't do the check) and a
// nested-name-qualifier (and therefore could do the lookup).
NamedDecl *FirstQualifierInScope = nullptr;
DeclarationNameInfo MemberNameInfo = E->getMemberNameInfo();
if (MemberNameInfo.getName()) {
MemberNameInfo = getDerived().TransformDeclarationNameInfo(MemberNameInfo);
if (!MemberNameInfo.getName())
return ExprError();
}
return getDerived().RebuildMemberExpr(Base.get(), FakeOperatorLoc,
E->isArrow(),
QualifierLoc,
TemplateKWLoc,
E->getMemberNameInfo(),
MemberNameInfo,
Member,
FoundDecl,
(E->hasExplicitTemplateArgs()

View File

@ -180,10 +180,6 @@ template <class ELFT> class ObjectFile : public ELFFileBase<ELFT> {
// R_MIPS_GPREL16 / R_MIPS_GPREL32 relocations.
uint32_t MipsGp0 = 0;
// The number is the offset in the string table. It will be used as the
// st_name of the symbol.
std::vector<std::pair<const DefinedRegular<ELFT> *, unsigned>> KeptLocalSyms;
// Name of source file obtained from STT_FILE symbol value,
// or empty string if there is no such symbol in object file
// symbol table.

View File

@ -246,7 +246,8 @@ void InputSection<ELFT>::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) {
if (Config->Rela)
P->r_addend = getAddend<ELFT>(Rel);
P->r_offset = RelocatedSection->getOffset(Rel.r_offset);
P->setSymbolAndType(Body.DynsymIndex, Type, Config->Mips64EL);
P->setSymbolAndType(In<ELFT>::SymTab->getSymbolIndex(&Body), Type,
Config->Mips64EL);
}
}

View File

@ -1065,22 +1065,21 @@ template <class ELFT> void SymbolTableSection<ELFT>::finalize() {
this->OutSec->Info = this->Info = NumLocals + 1;
this->OutSec->Entsize = this->Entsize;
if (Config->Relocatable) {
size_t I = NumLocals;
for (const SymbolTableEntry &S : Symbols)
S.Symbol->DynsymIndex = ++I;
if (Config->Relocatable)
return;
if (!StrTabSec.isDynamic()) {
auto GlobBegin = Symbols.begin() + NumLocals;
auto It = std::stable_partition(
GlobBegin, Symbols.end(), [](const SymbolTableEntry &S) {
return S.Symbol->symbol()->computeBinding() == STB_LOCAL;
});
// update sh_info with number of Global symbols output with computed
// binding of STB_LOCAL
this->OutSec->Info = this->Info = 1 + It - Symbols.begin();
return;
}
if (!StrTabSec.isDynamic()) {
std::stable_sort(
Symbols.begin(), Symbols.end(),
[](const SymbolTableEntry &L, const SymbolTableEntry &R) {
return L.Symbol->symbol()->computeBinding() == STB_LOCAL &&
R.Symbol->symbol()->computeBinding() != STB_LOCAL;
});
return;
}
if (In<ELFT>::GnuHashTab)
// NB: It also sorts Symbols to meet the GNU hash table requirements.
In<ELFT>::GnuHashTab->addSymbols(Symbols);
@ -1094,10 +1093,25 @@ template <class ELFT> void SymbolTableSection<ELFT>::finalize() {
S.Symbol->DynsymIndex = ++I;
}
template <class ELFT> void SymbolTableSection<ELFT>::addSymbol(SymbolBody *B) {
template <class ELFT> void SymbolTableSection<ELFT>::addGlobal(SymbolBody *B) {
Symbols.push_back({B, StrTabSec.addString(B->getName(), false)});
}
template <class ELFT> void SymbolTableSection<ELFT>::addLocal(SymbolBody *B) {
assert(!StrTabSec.isDynamic());
++NumLocals;
Symbols.push_back({B, StrTabSec.addString(B->getName())});
}
template <class ELFT>
size_t SymbolTableSection<ELFT>::getSymbolIndex(SymbolBody *Body) {
auto I = llvm::find_if(
Symbols, [&](const SymbolTableEntry &E) { return E.Symbol == Body; });
if (I == Symbols.end())
return 0;
return I - Symbols.begin() + 1;
}
template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
Buf += sizeof(Elf_Sym);
@ -1113,26 +1127,24 @@ template <class ELFT>
void SymbolTableSection<ELFT>::writeLocalSymbols(uint8_t *&Buf) {
// Iterate over all input object files to copy their local symbols
// to the output symbol table pointed by Buf.
for (ObjectFile<ELFT> *File : Symtab<ELFT>::X->getObjectFiles()) {
for (const std::pair<const DefinedRegular<ELFT> *, size_t> &P :
File->KeptLocalSyms) {
const DefinedRegular<ELFT> &Body = *P.first;
InputSectionBase<ELFT> *Section = Body.Section;
auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
if (!Section) {
ESym->st_shndx = SHN_ABS;
ESym->st_value = Body.Value;
} else {
const OutputSectionBase *OutSec = Section->OutSec;
ESym->st_shndx = OutSec->SectionIndex;
ESym->st_value = OutSec->Addr + Section->getOffset(Body);
}
ESym->st_name = P.second;
ESym->st_size = Body.template getSize<ELFT>();
ESym->setBindingAndType(STB_LOCAL, Body.Type);
Buf += sizeof(*ESym);
for (auto I = Symbols.begin(); I != Symbols.begin() + NumLocals; ++I) {
const DefinedRegular<ELFT> &Body = *cast<DefinedRegular<ELFT>>(I->Symbol);
InputSectionBase<ELFT> *Section = Body.Section;
auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
if (!Section) {
ESym->st_shndx = SHN_ABS;
ESym->st_value = Body.Value;
} else {
const OutputSectionBase *OutSec = Section->OutSec;
ESym->st_shndx = OutSec->SectionIndex;
ESym->st_value = OutSec->Addr + Section->getOffset(Body);
}
ESym->st_name = I->StrTabOffset;
ESym->st_size = Body.template getSize<ELFT>();
ESym->setBindingAndType(STB_LOCAL, Body.Type);
Buf += sizeof(*ESym);
}
}
@ -1141,7 +1153,9 @@ void SymbolTableSection<ELFT>::writeGlobalSymbols(uint8_t *Buf) {
// Write the internal symbol table contents to the output symbol table
// pointed by Buf.
auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
for (const SymbolTableEntry &S : Symbols) {
for (auto I = Symbols.begin() + NumLocals; I != Symbols.end(); ++I) {
const SymbolTableEntry &S = *I;
SymbolBody *Body = S.Symbol;
size_t StrOff = S.StrTabOffset;

View File

@ -366,23 +366,26 @@ class SymbolTableSection final : public SyntheticSection<ELFT> {
void finalize() override;
void writeTo(uint8_t *Buf) override;
size_t getSize() const override { return getNumSymbols() * sizeof(Elf_Sym); }
void addSymbol(SymbolBody *Body);
void addGlobal(SymbolBody *Body);
void addLocal(SymbolBody *Body);
StringTableSection<ELFT> &getStrTabSec() const { return StrTabSec; }
unsigned getNumSymbols() const { return NumLocals + Symbols.size() + 1; }
unsigned getNumSymbols() const { return Symbols.size() + 1; }
size_t getSymbolIndex(SymbolBody *Body);
ArrayRef<SymbolTableEntry> getSymbols() const { return Symbols; }
static const OutputSectionBase *getOutputSection(SymbolBody *Sym);
unsigned NumLocals = 0;
StringTableSection<ELFT> &StrTabSec;
private:
void writeLocalSymbols(uint8_t *&Buf);
void writeGlobalSymbols(uint8_t *Buf);
// A vector of symbols and their string table offsets.
std::vector<SymbolTableEntry> Symbols;
StringTableSection<ELFT> &StrTabSec;
unsigned NumLocals = 0;
};
// Outputs GNU Hash section. For detailed explanation see:

View File

@ -455,11 +455,7 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
InputSectionBase<ELFT> *Sec = DR->Section;
if (!shouldKeepInSymtab<ELFT>(Sec, B->getName(), *B))
continue;
++In<ELFT>::SymTab->NumLocals;
if (Config->Relocatable)
B->DynsymIndex = In<ELFT>::SymTab->NumLocals;
F->KeptLocalSyms.push_back(std::make_pair(
DR, In<ELFT>::SymTab->StrTabSec.addString(B->getName())));
In<ELFT>::SymTab->addLocal(B);
}
}
}
@ -1024,10 +1020,10 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
if (!includeInSymtab<ELFT>(*Body))
continue;
if (In<ELFT>::SymTab)
In<ELFT>::SymTab->addSymbol(Body);
In<ELFT>::SymTab->addGlobal(Body);
if (In<ELFT>::DynSymTab && S->includeInDynsym()) {
In<ELFT>::DynSymTab->addSymbol(Body);
In<ELFT>::DynSymTab->addGlobal(Body);
if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(Body))
if (SS->file()->isNeeded())
In<ELFT>::VerNeed->addSymbol(SS);

View File

@ -8,4 +8,4 @@
#define CLANG_VENDOR "FreeBSD "
#define SVN_REVISION "293443"
#define SVN_REVISION "293807"

View File

@ -4,5 +4,5 @@
#define LLD_VERSION_STRING "4.0.0"
#define LLD_VERSION_MAJOR 4
#define LLD_VERSION_MINOR 0
#define LLD_REVISION_STRING "293443"
#define LLD_REVISION_STRING "293807"
#define LLD_REPOSITORY_STRING "FreeBSD"