Merge llvm, clang, lld and lldb release_40 branch 292732, and update
build glue.
This commit is contained in:
commit
94c53d4054
@ -405,6 +405,7 @@ char ModuleSummaryIndexWrapperPass::ID = 0;
|
||||
INITIALIZE_PASS_BEGIN(ModuleSummaryIndexWrapperPass, "module-summary-analysis",
|
||||
"Module Summary Analysis", false, true)
|
||||
INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
|
||||
INITIALIZE_PASS_END(ModuleSummaryIndexWrapperPass, "module-summary-analysis",
|
||||
"Module Summary Analysis", false, true)
|
||||
|
||||
|
@ -768,13 +768,12 @@ void MetadataLoader::MetadataLoaderImpl::lazyLoadOneMetadata(
|
||||
unsigned ID, PlaceholderQueue &Placeholders) {
|
||||
assert(ID < (MDStringRef.size()) + GlobalMetadataBitPosIndex.size());
|
||||
assert(ID >= MDStringRef.size() && "Unexpected lazy-loading of MDString");
|
||||
#ifndef NDEBUG
|
||||
// Lookup first if the metadata hasn't already been loaded.
|
||||
if (auto *MD = MetadataList.lookup(ID)) {
|
||||
auto *N = dyn_cast_or_null<MDNode>(MD);
|
||||
assert(N && N->isTemporary() && "Lazy loading an already loaded metadata");
|
||||
if (!N->isTemporary())
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
SmallVector<uint64_t, 64> Record;
|
||||
StringRef Blob;
|
||||
IndexCursor.JumpToBit(GlobalMetadataBitPosIndex[ID - MDStringRef.size()]);
|
||||
@ -827,8 +826,22 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
|
||||
auto getMD = [&](unsigned ID) -> Metadata * {
|
||||
if (ID < MDStringRef.size())
|
||||
return lazyLoadOneMDString(ID);
|
||||
if (!IsDistinct)
|
||||
if (!IsDistinct) {
|
||||
if (auto *MD = MetadataList.lookup(ID))
|
||||
return MD;
|
||||
// If lazy-loading is enabled, we try recursively to load the operand
|
||||
// instead of creating a temporary.
|
||||
if (ID < (MDStringRef.size() + GlobalMetadataBitPosIndex.size())) {
|
||||
// Create a temporary for the node that is referencing the operand we
|
||||
// will lazy-load. It is needed before recursing in case there are
|
||||
// uniquing cycles.
|
||||
MetadataList.getMetadataFwdRef(NextMetadataNo);
|
||||
lazyLoadOneMetadata(ID, Placeholders);
|
||||
return MetadataList.lookup(ID);
|
||||
}
|
||||
// Return a temporary.
|
||||
return MetadataList.getMetadataFwdRef(ID);
|
||||
}
|
||||
if (auto *MD = MetadataList.getMetadataIfResolved(ID))
|
||||
return MD;
|
||||
return &Placeholders.getPlaceholderOp(ID);
|
||||
|
@ -829,11 +829,22 @@ static std::string writeGeneratedObject(int count, StringRef CacheEntryPath,
|
||||
|
||||
// Main entry point for the ThinLTO processing
|
||||
void ThinLTOCodeGenerator::run() {
|
||||
// Prepare the resulting object vector
|
||||
assert(ProducedBinaries.empty() && "The generator should not be reused");
|
||||
if (SavedObjectsDirectoryPath.empty())
|
||||
ProducedBinaries.resize(Modules.size());
|
||||
else {
|
||||
sys::fs::create_directories(SavedObjectsDirectoryPath);
|
||||
bool IsDir;
|
||||
sys::fs::is_directory(SavedObjectsDirectoryPath, IsDir);
|
||||
if (!IsDir)
|
||||
report_fatal_error("Unexistent dir: '" + SavedObjectsDirectoryPath + "'");
|
||||
ProducedBinaryFiles.resize(Modules.size());
|
||||
}
|
||||
|
||||
if (CodeGenOnly) {
|
||||
// Perform only parallel codegen and return.
|
||||
ThreadPool Pool;
|
||||
assert(ProducedBinaries.empty() && "The generator should not be reused");
|
||||
ProducedBinaries.resize(Modules.size());
|
||||
int count = 0;
|
||||
for (auto &ModuleBuffer : Modules) {
|
||||
Pool.async([&](int count) {
|
||||
@ -845,7 +856,12 @@ void ThinLTOCodeGenerator::run() {
|
||||
/*IsImporting*/ false);
|
||||
|
||||
// CodeGen
|
||||
ProducedBinaries[count] = codegen(*TheModule);
|
||||
auto OutputBuffer = codegen(*TheModule);
|
||||
if (SavedObjectsDirectoryPath.empty())
|
||||
ProducedBinaries[count] = std::move(OutputBuffer);
|
||||
else
|
||||
ProducedBinaryFiles[count] = writeGeneratedObject(
|
||||
count, "", SavedObjectsDirectoryPath, *OutputBuffer);
|
||||
}, count++);
|
||||
}
|
||||
|
||||
@ -866,18 +882,6 @@ void ThinLTOCodeGenerator::run() {
|
||||
WriteIndexToFile(*Index, OS);
|
||||
}
|
||||
|
||||
// Prepare the resulting object vector
|
||||
assert(ProducedBinaries.empty() && "The generator should not be reused");
|
||||
if (SavedObjectsDirectoryPath.empty())
|
||||
ProducedBinaries.resize(Modules.size());
|
||||
else {
|
||||
sys::fs::create_directories(SavedObjectsDirectoryPath);
|
||||
bool IsDir;
|
||||
sys::fs::is_directory(SavedObjectsDirectoryPath, IsDir);
|
||||
if (!IsDir)
|
||||
report_fatal_error("Unexistent dir: '" + SavedObjectsDirectoryPath + "'");
|
||||
ProducedBinaryFiles.resize(Modules.size());
|
||||
}
|
||||
|
||||
// Prepare the module map.
|
||||
auto ModuleMap = generateModuleMap(Modules);
|
||||
|
@ -29455,19 +29455,11 @@ static SDValue combineSelect(SDNode *N, SelectionDAG &DAG,
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
/// Combine brcond/cmov/setcc/.. based on comparing the result of
|
||||
/// atomic_load_add to use EFLAGS produced by the addition
|
||||
/// directly if possible. For example:
|
||||
///
|
||||
/// (setcc (cmp (atomic_load_add x, -C) C), COND_E)
|
||||
/// becomes:
|
||||
/// (setcc (LADD x, -C), COND_E)
|
||||
///
|
||||
/// and
|
||||
/// Combine:
|
||||
/// (brcond/cmov/setcc .., (cmp (atomic_load_add x, 1), 0), COND_S)
|
||||
/// becomes:
|
||||
/// to:
|
||||
/// (brcond/cmov/setcc .., (LADD x, 1), COND_LE)
|
||||
///
|
||||
/// i.e., reusing the EFLAGS produced by the LOCKed instruction.
|
||||
/// Note that this is only legal for some op/cc combinations.
|
||||
static SDValue combineSetCCAtomicArith(SDValue Cmp, X86::CondCode &CC,
|
||||
SelectionDAG &DAG) {
|
||||
@ -29482,7 +29474,7 @@ static SDValue combineSetCCAtomicArith(SDValue Cmp, X86::CondCode &CC,
|
||||
if (!Cmp.hasOneUse())
|
||||
return SDValue();
|
||||
|
||||
// This applies to variations of the common case:
|
||||
// This only applies to variations of the common case:
|
||||
// (icmp slt x, 0) -> (icmp sle (add x, 1), 0)
|
||||
// (icmp sge x, 0) -> (icmp sgt (add x, 1), 0)
|
||||
// (icmp sle x, 0) -> (icmp slt (sub x, 1), 0)
|
||||
@ -29501,9 +29493,8 @@ static SDValue combineSetCCAtomicArith(SDValue Cmp, X86::CondCode &CC,
|
||||
return SDValue();
|
||||
|
||||
auto *CmpRHSC = dyn_cast<ConstantSDNode>(CmpRHS);
|
||||
if (!CmpRHSC)
|
||||
if (!CmpRHSC || CmpRHSC->getZExtValue() != 0)
|
||||
return SDValue();
|
||||
APInt Comparand = CmpRHSC->getAPIntValue();
|
||||
|
||||
const unsigned Opc = CmpLHS.getOpcode();
|
||||
|
||||
@ -29519,19 +29510,16 @@ static SDValue combineSetCCAtomicArith(SDValue Cmp, X86::CondCode &CC,
|
||||
if (Opc == ISD::ATOMIC_LOAD_SUB)
|
||||
Addend = -Addend;
|
||||
|
||||
if (Comparand == -Addend) {
|
||||
// No change to CC.
|
||||
} else if (CC == X86::COND_S && Comparand == 0 && Addend == 1) {
|
||||
if (CC == X86::COND_S && Addend == 1)
|
||||
CC = X86::COND_LE;
|
||||
} else if (CC == X86::COND_NS && Comparand == 0 && Addend == 1) {
|
||||
else if (CC == X86::COND_NS && Addend == 1)
|
||||
CC = X86::COND_G;
|
||||
} else if (CC == X86::COND_G && Comparand == 0 && Addend == -1) {
|
||||
else if (CC == X86::COND_G && Addend == -1)
|
||||
CC = X86::COND_GE;
|
||||
} else if (CC == X86::COND_LE && Comparand == 0 && Addend == -1) {
|
||||
else if (CC == X86::COND_LE && Addend == -1)
|
||||
CC = X86::COND_L;
|
||||
} else {
|
||||
else
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
SDValue LockOp = lowerAtomicArithWithLOCK(CmpLHS, DAG);
|
||||
DAG.ReplaceAllUsesOfValueWith(CmpLHS.getValue(0),
|
||||
|
@ -232,9 +232,6 @@ void X86Subtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
|
||||
else if (isTargetDarwin() || isTargetLinux() || isTargetSolaris() ||
|
||||
isTargetKFreeBSD() || In64BitMode)
|
||||
stackAlignment = 16;
|
||||
|
||||
assert((!isPMULLDSlow() || hasSSE41()) &&
|
||||
"Feature Slow PMULLD can only be set on a subtarget with SSE4.1");
|
||||
}
|
||||
|
||||
void X86Subtarget::initializeEnvironment() {
|
||||
|
@ -3163,6 +3163,9 @@ LSRInstance::CollectLoopInvariantFixupsAndFormulae() {
|
||||
// Don't bother if the instruction is in a BB which ends in an EHPad.
|
||||
if (UseBB->getTerminator()->isEHPad())
|
||||
continue;
|
||||
// Don't bother rewriting PHIs in catchswitch blocks.
|
||||
if (isa<CatchSwitchInst>(UserInst->getParent()->getTerminator()))
|
||||
continue;
|
||||
// Ignore uses which are part of other SCEV expressions, to avoid
|
||||
// analyzing them multiple times.
|
||||
if (SE.isSCEVable(UserInst->getType())) {
|
||||
@ -4672,7 +4675,8 @@ void LSRInstance::RewriteForPHI(PHINode *PN,
|
||||
// is the canonical backedge for this loop, which complicates post-inc
|
||||
// users.
|
||||
if (e != 1 && BB->getTerminator()->getNumSuccessors() > 1 &&
|
||||
!isa<IndirectBrInst>(BB->getTerminator())) {
|
||||
!isa<IndirectBrInst>(BB->getTerminator()) &&
|
||||
!isa<CatchSwitchInst>(BB->getTerminator())) {
|
||||
BasicBlock *Parent = PN->getParent();
|
||||
Loop *PNLoop = LI.getLoopFor(Parent);
|
||||
if (!PNLoop || Parent != PNLoop->getHeader()) {
|
||||
|
@ -81,6 +81,10 @@ STATISTIC(NumGVNOpsSimplified, "Number of Expressions simplified");
|
||||
STATISTIC(NumGVNPhisAllSame, "Number of PHIs whos arguments are all the same");
|
||||
STATISTIC(NumGVNMaxIterations,
|
||||
"Maximum Number of iterations it took to converge GVN");
|
||||
STATISTIC(NumGVNLeaderChanges, "Number of leader changes");
|
||||
STATISTIC(NumGVNSortedLeaderChanges, "Number of sorted leader changes");
|
||||
STATISTIC(NumGVNAvoidedSortedLeaderChanges,
|
||||
"Number of avoided sorted leader changes");
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// GVN Pass
|
||||
@ -139,6 +143,10 @@ struct CongruenceClass {
|
||||
// This is used so we can detect store equivalence changes properly.
|
||||
int StoreCount = 0;
|
||||
|
||||
// The most dominating leader after our current leader, because the member set
|
||||
// is not sorted and is expensive to keep sorted all the time.
|
||||
std::pair<Value *, unsigned int> NextLeader = {nullptr, ~0U};
|
||||
|
||||
explicit CongruenceClass(unsigned ID) : ID(ID) {}
|
||||
CongruenceClass(unsigned ID, Value *Leader, const Expression *E)
|
||||
: ID(ID), RepLeader(Leader), DefiningExpr(E) {}
|
||||
@ -320,8 +328,8 @@ class NewGVN : public FunctionPass {
|
||||
// Templated to allow them to work both on BB's and BB-edges.
|
||||
template <class T>
|
||||
Value *lookupOperandLeader(Value *, const User *, const T &) const;
|
||||
void performCongruenceFinding(Value *, const Expression *);
|
||||
void moveValueToNewCongruenceClass(Value *, CongruenceClass *,
|
||||
void performCongruenceFinding(Instruction *, const Expression *);
|
||||
void moveValueToNewCongruenceClass(Instruction *, CongruenceClass *,
|
||||
CongruenceClass *);
|
||||
// Reachability handling.
|
||||
void updateReachableEdge(BasicBlock *, BasicBlock *);
|
||||
@ -1056,20 +1064,43 @@ void NewGVN::markLeaderChangeTouched(CongruenceClass *CC) {
|
||||
|
||||
// Move a value, currently in OldClass, to be part of NewClass
|
||||
// Update OldClass for the move (including changing leaders, etc)
|
||||
void NewGVN::moveValueToNewCongruenceClass(Value *V, CongruenceClass *OldClass,
|
||||
void NewGVN::moveValueToNewCongruenceClass(Instruction *I,
|
||||
CongruenceClass *OldClass,
|
||||
CongruenceClass *NewClass) {
|
||||
DEBUG(dbgs() << "New congruence class for " << V << " is " << NewClass->ID
|
||||
DEBUG(dbgs() << "New congruence class for " << I << " is " << NewClass->ID
|
||||
<< "\n");
|
||||
OldClass->Members.erase(V);
|
||||
NewClass->Members.insert(V);
|
||||
if (isa<StoreInst>(V)) {
|
||||
|
||||
if (I == OldClass->NextLeader.first)
|
||||
OldClass->NextLeader = {nullptr, ~0U};
|
||||
|
||||
// The new instruction and new class leader may either be siblings in the
|
||||
// dominator tree, or the new class leader should dominate the new member
|
||||
// instruction. We simply check that the member instruction does not properly
|
||||
// dominate the new class leader.
|
||||
assert(
|
||||
!isa<Instruction>(NewClass->RepLeader) || !NewClass->RepLeader ||
|
||||
I == NewClass->RepLeader ||
|
||||
!DT->properlyDominates(
|
||||
I->getParent(),
|
||||
cast<Instruction>(NewClass->RepLeader)->getParent()) &&
|
||||
"New class for instruction should not be dominated by instruction");
|
||||
|
||||
if (NewClass->RepLeader != I) {
|
||||
auto DFSNum = InstrDFS.lookup(I);
|
||||
if (DFSNum < NewClass->NextLeader.second)
|
||||
NewClass->NextLeader = {I, DFSNum};
|
||||
}
|
||||
|
||||
OldClass->Members.erase(I);
|
||||
NewClass->Members.insert(I);
|
||||
if (isa<StoreInst>(I)) {
|
||||
--OldClass->StoreCount;
|
||||
assert(OldClass->StoreCount >= 0);
|
||||
++NewClass->StoreCount;
|
||||
assert(NewClass->StoreCount > 0);
|
||||
}
|
||||
|
||||
ValueToClass[V] = NewClass;
|
||||
ValueToClass[I] = NewClass;
|
||||
// See if we destroyed the class or need to swap leaders.
|
||||
if (OldClass->Members.empty() && OldClass != InitialClass) {
|
||||
if (OldClass->DefiningExpr) {
|
||||
@ -1078,25 +1109,48 @@ void NewGVN::moveValueToNewCongruenceClass(Value *V, CongruenceClass *OldClass,
|
||||
<< " from table\n");
|
||||
ExpressionToClass.erase(OldClass->DefiningExpr);
|
||||
}
|
||||
} else if (OldClass->RepLeader == V) {
|
||||
} else if (OldClass->RepLeader == I) {
|
||||
// When the leader changes, the value numbering of
|
||||
// everything may change due to symbolization changes, so we need to
|
||||
// reprocess.
|
||||
OldClass->RepLeader = *(OldClass->Members.begin());
|
||||
DEBUG(dbgs() << "Leader change!\n");
|
||||
++NumGVNLeaderChanges;
|
||||
// We don't need to sort members if there is only 1, and we don't care about
|
||||
// sorting the initial class because everything either gets out of it or is
|
||||
// unreachable.
|
||||
if (OldClass->Members.size() == 1 || OldClass == InitialClass) {
|
||||
OldClass->RepLeader = *(OldClass->Members.begin());
|
||||
} else if (OldClass->NextLeader.first) {
|
||||
++NumGVNAvoidedSortedLeaderChanges;
|
||||
OldClass->RepLeader = OldClass->NextLeader.first;
|
||||
OldClass->NextLeader = {nullptr, ~0U};
|
||||
} else {
|
||||
++NumGVNSortedLeaderChanges;
|
||||
// TODO: If this ends up to slow, we can maintain a dual structure for
|
||||
// member testing/insertion, or keep things mostly sorted, and sort only
|
||||
// here, or ....
|
||||
std::pair<Value *, unsigned> MinDFS = {nullptr, ~0U};
|
||||
for (const auto X : OldClass->Members) {
|
||||
auto DFSNum = InstrDFS.lookup(X);
|
||||
if (DFSNum < MinDFS.second)
|
||||
MinDFS = {X, DFSNum};
|
||||
}
|
||||
OldClass->RepLeader = MinDFS.first;
|
||||
}
|
||||
markLeaderChangeTouched(OldClass);
|
||||
}
|
||||
}
|
||||
|
||||
// Perform congruence finding on a given value numbering expression.
|
||||
void NewGVN::performCongruenceFinding(Value *V, const Expression *E) {
|
||||
ValueToExpression[V] = E;
|
||||
void NewGVN::performCongruenceFinding(Instruction *I, const Expression *E) {
|
||||
ValueToExpression[I] = E;
|
||||
// This is guaranteed to return something, since it will at least find
|
||||
// INITIAL.
|
||||
|
||||
CongruenceClass *VClass = ValueToClass[V];
|
||||
assert(VClass && "Should have found a vclass");
|
||||
CongruenceClass *IClass = ValueToClass[I];
|
||||
assert(IClass && "Should have found a IClass");
|
||||
// Dead classes should have been eliminated from the mapping.
|
||||
assert(!VClass->Dead && "Found a dead class");
|
||||
assert(!IClass->Dead && "Found a dead class");
|
||||
|
||||
CongruenceClass *EClass;
|
||||
if (const auto *VE = dyn_cast<VariableExpression>(E)) {
|
||||
@ -1118,13 +1172,13 @@ void NewGVN::performCongruenceFinding(Value *V, const Expression *E) {
|
||||
NewClass->RepLeader =
|
||||
lookupOperandLeader(SI->getValueOperand(), SI, SI->getParent());
|
||||
} else {
|
||||
NewClass->RepLeader = V;
|
||||
NewClass->RepLeader = I;
|
||||
}
|
||||
assert(!isa<VariableExpression>(E) &&
|
||||
"VariableExpression should have been handled already");
|
||||
|
||||
EClass = NewClass;
|
||||
DEBUG(dbgs() << "Created new congruence class for " << *V
|
||||
DEBUG(dbgs() << "Created new congruence class for " << *I
|
||||
<< " using expression " << *E << " at " << NewClass->ID
|
||||
<< " and leader " << *(NewClass->RepLeader) << "\n");
|
||||
DEBUG(dbgs() << "Hash value was " << E->getHashValue() << "\n");
|
||||
@ -1140,36 +1194,31 @@ void NewGVN::performCongruenceFinding(Value *V, const Expression *E) {
|
||||
assert(!EClass->Dead && "We accidentally looked up a dead class");
|
||||
}
|
||||
}
|
||||
bool ClassChanged = VClass != EClass;
|
||||
bool LeaderChanged = LeaderChanges.erase(V);
|
||||
bool ClassChanged = IClass != EClass;
|
||||
bool LeaderChanged = LeaderChanges.erase(I);
|
||||
if (ClassChanged || LeaderChanged) {
|
||||
DEBUG(dbgs() << "Found class " << EClass->ID << " for expression " << E
|
||||
<< "\n");
|
||||
|
||||
if (ClassChanged)
|
||||
|
||||
moveValueToNewCongruenceClass(V, VClass, EClass);
|
||||
|
||||
|
||||
markUsersTouched(V);
|
||||
if (auto *I = dyn_cast<Instruction>(V)) {
|
||||
if (MemoryAccess *MA = MSSA->getMemoryAccess(I)) {
|
||||
// If this is a MemoryDef, we need to update the equivalence table. If
|
||||
// we determined the expression is congruent to a different memory
|
||||
// state, use that different memory state. If we determined it didn't,
|
||||
// we update that as well. Right now, we only support store
|
||||
// expressions.
|
||||
if (!isa<MemoryUse>(MA) && isa<StoreExpression>(E) &&
|
||||
EClass->Members.size() != 1) {
|
||||
auto *DefAccess = cast<StoreExpression>(E)->getDefiningAccess();
|
||||
setMemoryAccessEquivTo(MA, DefAccess != MA ? DefAccess : nullptr);
|
||||
} else {
|
||||
setMemoryAccessEquivTo(MA, nullptr);
|
||||
}
|
||||
markMemoryUsersTouched(MA);
|
||||
moveValueToNewCongruenceClass(I, IClass, EClass);
|
||||
markUsersTouched(I);
|
||||
if (MemoryAccess *MA = MSSA->getMemoryAccess(I)) {
|
||||
// If this is a MemoryDef, we need to update the equivalence table. If
|
||||
// we determined the expression is congruent to a different memory
|
||||
// state, use that different memory state. If we determined it didn't,
|
||||
// we update that as well. Right now, we only support store
|
||||
// expressions.
|
||||
if (!isa<MemoryUse>(MA) && isa<StoreExpression>(E) &&
|
||||
EClass->Members.size() != 1) {
|
||||
auto *DefAccess = cast<StoreExpression>(E)->getDefiningAccess();
|
||||
setMemoryAccessEquivTo(MA, DefAccess != MA ? DefAccess : nullptr);
|
||||
} else {
|
||||
setMemoryAccessEquivTo(MA, nullptr);
|
||||
}
|
||||
markMemoryUsersTouched(MA);
|
||||
}
|
||||
} else if (StoreInst *SI = dyn_cast<StoreInst>(V)) {
|
||||
} else if (auto *SI = dyn_cast<StoreInst>(I)) {
|
||||
// There is, sadly, one complicating thing for stores. Stores do not
|
||||
// produce values, only consume them. However, in order to make loads and
|
||||
// stores value number the same, we ignore the value operand of the store.
|
||||
|
@ -5602,6 +5602,13 @@ void LoopVectorizationLegality::collectLoopUniforms() {
|
||||
// is consecutive-like, the pointer operand should remain uniform.
|
||||
else if (hasConsecutiveLikePtrOperand(&I))
|
||||
ConsecutiveLikePtrs.insert(Ptr);
|
||||
|
||||
// Otherwise, if the memory instruction will be vectorized and its
|
||||
// pointer operand is non-consecutive-like, the memory instruction should
|
||||
// be a gather or scatter operation. Its pointer operand will be
|
||||
// non-uniform.
|
||||
else
|
||||
PossibleNonUniformPtrs.insert(Ptr);
|
||||
}
|
||||
|
||||
// Add to the Worklist all consecutive and consecutive-like pointers that
|
||||
|
@ -3337,8 +3337,8 @@ def note_ovl_candidate : Note<"candidate "
|
||||
def note_ovl_candidate_inherited_constructor : Note<
|
||||
"constructor from base class %0 inherited here">;
|
||||
def note_ovl_candidate_inherited_constructor_slice : Note<
|
||||
"constructor inherited from base class cannot be used to initialize from "
|
||||
"an argument of the derived class type">;
|
||||
"candidate %select{constructor|template}0 ignored: "
|
||||
"inherited constructor cannot be used to %select{copy|move}1 object">;
|
||||
def note_ovl_candidate_illegal_constructor : Note<
|
||||
"candidate %select{constructor|template}0 ignored: "
|
||||
"instantiation %select{takes|would take}0 its own class type by value">;
|
||||
|
@ -512,7 +512,7 @@ class NetBSDTargetInfo : public OSTargetInfo<Target> {
|
||||
Builder.defineMacro("__unix__");
|
||||
Builder.defineMacro("__ELF__");
|
||||
if (Opts.POSIXThreads)
|
||||
Builder.defineMacro("_POSIX_THREADS");
|
||||
Builder.defineMacro("_REENTRANT");
|
||||
|
||||
switch (Triple.getArch()) {
|
||||
default:
|
||||
|
@ -1652,9 +1652,10 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
|
||||
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
// Code completion for a member access expression.
|
||||
Actions.CodeCompleteMemberReferenceExpr(
|
||||
getCurScope(), LHS.get(), OpLoc, OpKind == tok::arrow,
|
||||
ExprStatementTokLoc == LHS.get()->getLocStart());
|
||||
if (Expr *Base = LHS.get())
|
||||
Actions.CodeCompleteMemberReferenceExpr(
|
||||
getCurScope(), Base, OpLoc, OpKind == tok::arrow,
|
||||
ExprStatementTokLoc == Base->getLocStart());
|
||||
|
||||
cutOffParsing();
|
||||
return ExprError();
|
||||
|
@ -5944,6 +5944,28 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
|
||||
Candidate.FailureKind = ovl_fail_illegal_constructor;
|
||||
return;
|
||||
}
|
||||
|
||||
// C++ [over.match.funcs]p8: (proposed DR resolution)
|
||||
// A constructor inherited from class type C that has a first parameter
|
||||
// of type "reference to P" (including such a constructor instantiated
|
||||
// from a template) is excluded from the set of candidate functions when
|
||||
// constructing an object of type cv D if the argument list has exactly
|
||||
// one argument and D is reference-related to P and P is reference-related
|
||||
// to C.
|
||||
auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(FoundDecl.getDecl());
|
||||
if (Shadow && Args.size() == 1 && Constructor->getNumParams() >= 1 &&
|
||||
Constructor->getParamDecl(0)->getType()->isReferenceType()) {
|
||||
QualType P = Constructor->getParamDecl(0)->getType()->getPointeeType();
|
||||
QualType C = Context.getRecordType(Constructor->getParent());
|
||||
QualType D = Context.getRecordType(Shadow->getParent());
|
||||
SourceLocation Loc = Args.front()->getExprLoc();
|
||||
if ((Context.hasSameUnqualifiedType(P, C) || IsDerivedFrom(Loc, P, C)) &&
|
||||
(Context.hasSameUnqualifiedType(D, P) || IsDerivedFrom(Loc, D, P))) {
|
||||
Candidate.Viable = false;
|
||||
Candidate.FailureKind = ovl_fail_inhctor_slice;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned NumParams = Proto->getNumParams();
|
||||
@ -6016,31 +6038,6 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
|
||||
}
|
||||
}
|
||||
|
||||
// C++ [over.best.ics]p4+: (proposed DR resolution)
|
||||
// If the target is the first parameter of an inherited constructor when
|
||||
// constructing an object of type C with an argument list that has exactly
|
||||
// one expression, an implicit conversion sequence cannot be formed if C is
|
||||
// reference-related to the type that the argument would have after the
|
||||
// application of the user-defined conversion (if any) and before the final
|
||||
// standard conversion sequence.
|
||||
auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(FoundDecl.getDecl());
|
||||
if (Shadow && Args.size() == 1 && !isa<InitListExpr>(Args.front())) {
|
||||
bool DerivedToBase, ObjCConversion, ObjCLifetimeConversion;
|
||||
QualType ConvertedArgumentType = Args.front()->getType();
|
||||
if (Candidate.Conversions[0].isUserDefined())
|
||||
ConvertedArgumentType =
|
||||
Candidate.Conversions[0].UserDefined.After.getFromType();
|
||||
if (CompareReferenceRelationship(Args.front()->getLocStart(),
|
||||
Context.getRecordType(Shadow->getParent()),
|
||||
ConvertedArgumentType, DerivedToBase,
|
||||
ObjCConversion,
|
||||
ObjCLifetimeConversion) >= Ref_Related) {
|
||||
Candidate.Viable = false;
|
||||
Candidate.FailureKind = ovl_fail_inhctor_slice;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (EnableIfAttr *FailedAttr = CheckEnableIf(Function, Args)) {
|
||||
Candidate.Viable = false;
|
||||
Candidate.FailureKind = ovl_fail_enable_if;
|
||||
@ -10222,8 +10219,13 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
|
||||
return DiagnoseOpenCLExtensionDisabled(S, Cand);
|
||||
|
||||
case ovl_fail_inhctor_slice:
|
||||
// It's generally not interesting to note copy/move constructors here.
|
||||
if (cast<CXXConstructorDecl>(Fn)->isCopyOrMoveConstructor())
|
||||
return;
|
||||
S.Diag(Fn->getLocation(),
|
||||
diag::note_ovl_candidate_inherited_constructor_slice);
|
||||
diag::note_ovl_candidate_inherited_constructor_slice)
|
||||
<< (Fn->getPrimaryTemplate() ? 1 : 0)
|
||||
<< Fn->getParamDecl(0)->getType()->isRValueReferenceType();
|
||||
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
|
||||
return;
|
||||
|
||||
|
@ -5127,18 +5127,22 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
|
||||
if (CTAK == CTAK_Deduced &&
|
||||
!Context.hasSameType(ParamType.getNonLValueExprType(Context),
|
||||
Arg->getType())) {
|
||||
// C++ [temp.deduct.type]p17: (DR1770)
|
||||
// If P has a form that contains <i>, and if the type of i differs from
|
||||
// the type of the corresponding template parameter of the template named
|
||||
// by the enclosing simple-template-id, deduction fails.
|
||||
//
|
||||
// Note that CTAK will be CTAK_DeducedFromArrayBound if the form was [i]
|
||||
// rather than <i>.
|
||||
//
|
||||
// FIXME: We interpret the 'i' here as referring to the expression
|
||||
// denoting the non-type template parameter rather than the parameter
|
||||
// itself, and so strip off references before comparing types. It's
|
||||
// not clear how this is supposed to work for references.
|
||||
// FIXME: If either type is dependent, we skip the check. This isn't
|
||||
// correct, since during deduction we're supposed to have replaced each
|
||||
// template parameter with some unique (non-dependent) placeholder.
|
||||
// FIXME: If the argument type contains 'auto', we carry on and fail the
|
||||
// type check in order to force specific types to be more specialized than
|
||||
// 'auto'. It's not clear how partial ordering with 'auto' is supposed to
|
||||
// work.
|
||||
if ((ParamType->isDependentType() || Arg->isTypeDependent()) &&
|
||||
!Arg->getType()->getContainedAutoType()) {
|
||||
Converted = TemplateArgument(Arg);
|
||||
return Arg;
|
||||
}
|
||||
// FIXME: This attempts to implement C++ [temp.deduct.type]p17. Per DR1770,
|
||||
// we should actually be checking the type of the template argument in P,
|
||||
// not the type of the template argument deduced from A, against the
|
||||
// template parameter type.
|
||||
Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch)
|
||||
<< Arg->getType()
|
||||
<< ParamType.getUnqualifiedType();
|
||||
|
@ -140,7 +140,7 @@ template <class ELFT>
|
||||
DefinedRegular<ELFT> *SymbolTable<ELFT>::addIgnored(StringRef Name,
|
||||
uint8_t Visibility) {
|
||||
SymbolBody *S = find(Name);
|
||||
if (!S || !S->isUndefined())
|
||||
if (!S || S->isInCurrentDSO())
|
||||
return nullptr;
|
||||
return addAbsolute(Name, Visibility);
|
||||
}
|
||||
@ -283,7 +283,7 @@ static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding) {
|
||||
if (WasInserted)
|
||||
return 1;
|
||||
SymbolBody *Body = S->body();
|
||||
if (Body->isLazy() || Body->isUndefined() || Body->isShared())
|
||||
if (Body->isLazy() || !Body->isInCurrentDSO())
|
||||
return 1;
|
||||
if (Binding == STB_WEAK)
|
||||
return -1;
|
||||
@ -426,12 +426,8 @@ void SymbolTable<ELFT>::addShared(SharedFile<ELFT> *F, StringRef Name,
|
||||
std::tie(S, WasInserted) =
|
||||
insert(Name, Sym.getType(), STV_DEFAULT, /*CanOmitFromDynSym*/ true, F);
|
||||
// Make sure we preempt DSO symbols with default visibility.
|
||||
if (Sym.getVisibility() == STV_DEFAULT) {
|
||||
if (Sym.getVisibility() == STV_DEFAULT)
|
||||
S->ExportDynamic = true;
|
||||
// Exporting preempting symbols takes precedence over linker scripts.
|
||||
if (S->VersionId == VER_NDX_LOCAL)
|
||||
S->VersionId = VER_NDX_GLOBAL;
|
||||
}
|
||||
if (WasInserted || isa<Undefined<ELFT>>(S->body())) {
|
||||
replaceBody<SharedSymbol<ELFT>>(S, F, Name, Sym, Verdef);
|
||||
if (!S->isWeak())
|
||||
@ -467,6 +463,14 @@ template <class ELFT> SymbolBody *SymbolTable<ELFT>::find(StringRef Name) {
|
||||
return SymVector[V.Idx]->body();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
SymbolBody *SymbolTable<ELFT>::findInCurrentDSO(StringRef Name) {
|
||||
if (SymbolBody *S = find(Name))
|
||||
if (S->isInCurrentDSO())
|
||||
return S;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void SymbolTable<ELFT>::addLazyArchive(ArchiveFile *F,
|
||||
const object::Archive::Symbol Sym) {
|
||||
|
@ -82,6 +82,7 @@ template <class ELFT> class SymbolTable {
|
||||
void scanVersionScript();
|
||||
|
||||
SymbolBody *find(StringRef Name);
|
||||
SymbolBody *findInCurrentDSO(StringRef Name);
|
||||
|
||||
void trace(StringRef Name);
|
||||
void wrap(StringRef Name);
|
||||
|
@ -203,8 +203,8 @@ void SymbolBody::parseSymbolVersion() {
|
||||
// Truncate the symbol name so that it doesn't include the version string.
|
||||
Name = {S.data(), Pos};
|
||||
|
||||
// If this is an undefined or shared symbol it is not a definition.
|
||||
if (isUndefined() || isShared())
|
||||
// If this is not in this DSO, it is not a definition.
|
||||
if (!isInCurrentDSO())
|
||||
return;
|
||||
|
||||
// '@@' in a symbol name means the default version.
|
||||
@ -299,7 +299,8 @@ uint8_t Symbol::computeBinding() const {
|
||||
return Binding;
|
||||
if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
|
||||
return STB_LOCAL;
|
||||
if (VersionId == VER_NDX_LOCAL && !body()->isUndefined())
|
||||
const SymbolBody *Body = body();
|
||||
if (VersionId == VER_NDX_LOCAL && Body->isInCurrentDSO())
|
||||
return STB_LOCAL;
|
||||
if (Config->NoGnuUnique && Binding == STB_GNU_UNIQUE)
|
||||
return STB_GLOBAL;
|
||||
|
@ -67,6 +67,7 @@ class SymbolBody {
|
||||
return SymbolKind == LazyArchiveKind || SymbolKind == LazyObjectKind;
|
||||
}
|
||||
bool isShared() const { return SymbolKind == SharedKind; }
|
||||
bool isInCurrentDSO() const { return !isUndefined() && !isShared(); }
|
||||
bool isLocal() const { return IsLocal; }
|
||||
bool isPreemptible() const;
|
||||
StringRef getName() const { return Name; }
|
||||
|
@ -883,9 +883,9 @@ template <class ELFT> void DynamicSection<ELFT>::finalize() {
|
||||
add({DT_FINI_ARRAYSZ, Out<ELFT>::FiniArray, Entry::SecSize});
|
||||
}
|
||||
|
||||
if (SymbolBody *B = Symtab<ELFT>::X->find(Config->Init))
|
||||
if (SymbolBody *B = Symtab<ELFT>::X->findInCurrentDSO(Config->Init))
|
||||
add({DT_INIT, B});
|
||||
if (SymbolBody *B = Symtab<ELFT>::X->find(Config->Fini))
|
||||
if (SymbolBody *B = Symtab<ELFT>::X->findInCurrentDSO(Config->Fini))
|
||||
add({DT_FINI, B});
|
||||
|
||||
bool HasVerNeed = In<ELFT>::VerNeed->getNeedNum() != 0;
|
||||
|
@ -641,7 +641,7 @@ static void addOptionalSynthetic(StringRef Name, OutputSectionBase *Sec,
|
||||
typename ELFT::uint Val,
|
||||
uint8_t StOther = STV_HIDDEN) {
|
||||
if (SymbolBody *S = Symtab<ELFT>::X->find(Name))
|
||||
if (S->isUndefined() || S->isShared())
|
||||
if (!S->isInCurrentDSO())
|
||||
Symtab<ELFT>::X->addSynthetic(Name, Sec, Val, StOther);
|
||||
}
|
||||
|
||||
@ -661,7 +661,7 @@ static Symbol *addOptionalRegular(StringRef Name, InputSectionBase<ELFT> *IS,
|
||||
SymbolBody *S = Symtab<ELFT>::X->find(Name);
|
||||
if (!S)
|
||||
return nullptr;
|
||||
if (!S->isUndefined() && !S->isShared())
|
||||
if (S->isInCurrentDSO())
|
||||
return S->symbol();
|
||||
return addRegular(Name, IS, Value);
|
||||
}
|
||||
|
@ -8,4 +8,4 @@
|
||||
|
||||
#define CLANG_VENDOR "FreeBSD "
|
||||
|
||||
#define SVN_REVISION "292009"
|
||||
#define SVN_REVISION "292732"
|
||||
|
@ -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 "292009"
|
||||
#define LLD_REVISION_STRING "292732"
|
||||
#define LLD_REPOSITORY_STRING "FreeBSD"
|
||||
|
Loading…
Reference in New Issue
Block a user