# HG changeset patch # User mir3636 # Date 1512390052 -32400 # Node ID c4cc77a799c9715e4c434714eaeca6ea161f5699 # Parent 56c5119fbcd2771902273bd645aff33ebbb836fe fix diff -r 56c5119fbcd2 -r c4cc77a799c9 lib/Target/Hexagon/HexagonTargetObjectFile.cpp --- a/lib/Target/Hexagon/HexagonTargetObjectFile.cpp Sun Dec 03 20:09:16 2017 +0900 +++ b/lib/Target/Hexagon/HexagonTargetObjectFile.cpp Mon Dec 04 21:20:52 2017 +0900 @@ -323,6 +323,9 @@ case Type::MetadataTyID: case Type::X86_MMXTyID: case Type::TokenTyID: +#ifndef noCbC + case Type::__CodeTyID: +#endif return 0; } diff -r 56c5119fbcd2 -r c4cc77a799c9 lib/Target/XCore/XCoreISelLowering.cpp --- a/lib/Target/XCore/XCoreISelLowering.cpp Sun Dec 03 20:09:16 2017 +0900 +++ b/lib/Target/XCore/XCoreISelLowering.cpp Mon Dec 04 21:20:52 2017 +0900 @@ -34,6 +34,7 @@ #include "llvm/IR/Intrinsics.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/KnownBits.h" #include "llvm/Support/raw_ostream.h" #include @@ -110,8 +111,6 @@ setOperationAction(ISD::CTPOP, MVT::i32, Expand); setOperationAction(ISD::ROTL , MVT::i32, Expand); setOperationAction(ISD::ROTR , MVT::i32, Expand); - setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Expand); - setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Expand); setOperationAction(ISD::TRAP, MVT::Other, Legal); @@ -156,7 +155,6 @@ // Atomic operations // We request a fence for ATOMIC_* instructions, to reduce them to Monotonic. // As we are always Sequential Consistent, an ATOMIC_FENCE becomes a no OP. - setInsertFencesForAtomic(true); setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Custom); setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Custom); @@ -261,7 +259,7 @@ return DAG.getNode(XCoreISD::PCRelativeWrapper, dl, MVT::i32, GA); const auto *GVar = dyn_cast(GV); - if ((GV->hasSection() && StringRef(GV->getSection()).startswith(".cp.")) || + if ((GV->hasSection() && GV->getSection().startswith(".cp.")) || (GVar && GVar->isConstant() && GV->hasLocalLinkage())) return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, GA); @@ -309,8 +307,7 @@ Type::getInt8Ty(*DAG.getContext()), GA, Idx); SDValue CP = DAG.getConstantPool(GAI, MVT::i32); return DAG.getLoad(getPointerTy(DAG.getDataLayout()), DL, - DAG.getEntryNode(), CP, MachinePointerInfo(), false, - false, false, 0); + DAG.getEntryNode(), CP, MachinePointerInfo()); } } @@ -371,14 +368,12 @@ ScaledIndex); } -SDValue XCoreTargetLowering:: -lowerLoadWordFromAlignedBasePlusOffset(SDLoc DL, SDValue Chain, SDValue Base, - int64_t Offset, SelectionDAG &DAG) const -{ +SDValue XCoreTargetLowering::lowerLoadWordFromAlignedBasePlusOffset( + const SDLoc &DL, SDValue Chain, SDValue Base, int64_t Offset, + SelectionDAG &DAG) const { auto PtrVT = getPointerTy(DAG.getDataLayout()); if ((Offset & 0x3) == 0) { - return DAG.getLoad(PtrVT, DL, Chain, Base, MachinePointerInfo(), false, - false, false, 0); + return DAG.getLoad(PtrVT, DL, Chain, Base, MachinePointerInfo()); } // Lower to pair of consecutive word aligned loads plus some bit shifting. int32_t HighOffset = alignTo(Offset, 4); @@ -399,10 +394,8 @@ SDValue LowShift = DAG.getConstant((Offset - LowOffset) * 8, DL, MVT::i32); SDValue HighShift = DAG.getConstant((HighOffset - Offset) * 8, DL, MVT::i32); - SDValue Low = DAG.getLoad(PtrVT, DL, Chain, LowAddr, MachinePointerInfo(), - false, false, false, 0); - SDValue High = DAG.getLoad(PtrVT, DL, Chain, HighAddr, MachinePointerInfo(), - false, false, false, 0); + SDValue Low = DAG.getLoad(PtrVT, DL, Chain, LowAddr, MachinePointerInfo()); + SDValue High = DAG.getLoad(PtrVT, DL, Chain, HighAddr, MachinePointerInfo()); SDValue LowShifted = DAG.getNode(ISD::SRL, DL, MVT::i32, Low, LowShift); SDValue HighShifted = DAG.getNode(ISD::SHL, DL, MVT::i32, High, HighShift); SDValue Result = DAG.getNode(ISD::OR, DL, MVT::i32, LowShifted, HighShifted); @@ -414,9 +407,9 @@ static bool isWordAligned(SDValue Value, SelectionDAG &DAG) { - APInt KnownZero, KnownOne; - DAG.computeKnownBits(Value, KnownZero, KnownOne); - return KnownZero.countTrailingOnes() >= 2; + KnownBits Known; + DAG.computeKnownBits(Value, Known); + return Known.countMinTrailingZeros() >= 2; } SDValue XCoreTargetLowering:: @@ -462,17 +455,16 @@ } if (LD->getAlignment() == 2) { - SDValue Low = DAG.getExtLoad(ISD::ZEXTLOAD, DL, MVT::i32, Chain, - BasePtr, LD->getPointerInfo(), MVT::i16, - LD->isVolatile(), LD->isNonTemporal(), - LD->isInvariant(), 2); + SDValue Low = + DAG.getExtLoad(ISD::ZEXTLOAD, DL, MVT::i32, Chain, BasePtr, + LD->getPointerInfo(), MVT::i16, + /* Alignment = */ 2, LD->getMemOperand()->getFlags()); SDValue HighAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, BasePtr, DAG.getConstant(2, DL, MVT::i32)); - SDValue High = DAG.getExtLoad(ISD::EXTLOAD, DL, MVT::i32, Chain, - HighAddr, - LD->getPointerInfo().getWithOffset(2), - MVT::i16, LD->isVolatile(), - LD->isNonTemporal(), LD->isInvariant(), 2); + SDValue High = + DAG.getExtLoad(ISD::EXTLOAD, DL, MVT::i32, Chain, HighAddr, + LD->getPointerInfo().getWithOffset(2), MVT::i16, + /* Alignment = */ 2, LD->getMemOperand()->getFlags()); SDValue HighShifted = DAG.getNode(ISD::SHL, DL, MVT::i32, High, DAG.getConstant(16, DL, MVT::i32)); SDValue Result = DAG.getNode(ISD::OR, DL, MVT::i32, Low, HighShifted); @@ -492,11 +484,11 @@ Args.push_back(Entry); TargetLowering::CallLoweringInfo CLI(DAG); - CLI.setDebugLoc(DL).setChain(Chain).setCallee( + CLI.setDebugLoc(DL).setChain(Chain).setLibCallee( CallingConv::C, IntPtrTy, DAG.getExternalSymbol("__misaligned_load", getPointerTy(DAG.getDataLayout())), - std::move(Args), 0); + std::move(Args)); std::pair CallResult = LowerCallTo(CLI); SDValue Ops[] = { CallResult.first, CallResult.second }; @@ -529,16 +521,14 @@ SDValue Low = Value; SDValue High = DAG.getNode(ISD::SRL, dl, MVT::i32, Value, DAG.getConstant(16, dl, MVT::i32)); - SDValue StoreLow = DAG.getTruncStore(Chain, dl, Low, BasePtr, - ST->getPointerInfo(), MVT::i16, - ST->isVolatile(), ST->isNonTemporal(), - 2); + SDValue StoreLow = DAG.getTruncStore( + Chain, dl, Low, BasePtr, ST->getPointerInfo(), MVT::i16, + /* Alignment = */ 2, ST->getMemOperand()->getFlags()); SDValue HighAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, BasePtr, DAG.getConstant(2, dl, MVT::i32)); - SDValue StoreHigh = DAG.getTruncStore(Chain, dl, High, HighAddr, - ST->getPointerInfo().getWithOffset(2), - MVT::i16, ST->isVolatile(), - ST->isNonTemporal(), 2); + SDValue StoreHigh = DAG.getTruncStore( + Chain, dl, High, HighAddr, ST->getPointerInfo().getWithOffset(2), + MVT::i16, /* Alignment = */ 2, ST->getMemOperand()->getFlags()); return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, StoreLow, StoreHigh); } @@ -559,7 +549,7 @@ CallingConv::C, Type::getVoidTy(*DAG.getContext()), DAG.getExternalSymbol("__misaligned_store", getPointerTy(DAG.getDataLayout())), - std::move(Args), 0); + std::move(Args)); std::pair CallResult = LowerCallTo(CLI); return CallResult.second; @@ -725,11 +715,9 @@ (N->getOpcode() == ISD::ADD || N->getOpcode() == ISD::SUB) && "Unknown operand to lower!"); - if (N->getOpcode() == ISD::ADD) { - SDValue Result = TryExpandADDWithMul(N, DAG); - if (Result.getNode()) + if (N->getOpcode() == ISD::ADD) + if (SDValue Result = TryExpandADDWithMul(N, DAG)) return Result; - } SDLoc dl(N); @@ -774,19 +762,17 @@ EVT PtrVT = VAListPtr.getValueType(); const Value *SV = cast(Node->getOperand(2))->getValue(); SDLoc dl(Node); - SDValue VAList = DAG.getLoad(PtrVT, dl, InChain, - VAListPtr, MachinePointerInfo(SV), - false, false, false, 0); + SDValue VAList = + DAG.getLoad(PtrVT, dl, InChain, VAListPtr, MachinePointerInfo(SV)); // Increment the pointer, VAList, to the next vararg SDValue nextPtr = DAG.getNode(ISD::ADD, dl, PtrVT, VAList, DAG.getIntPtrConstant(VT.getSizeInBits() / 8, dl)); // Store the incremented VAList to the legalized pointer InChain = DAG.getStore(VAList.getValue(1), dl, nextPtr, VAListPtr, - MachinePointerInfo(SV), false, false, 0); + MachinePointerInfo(SV)); // Load the actual argument out of the pointer VAList - return DAG.getLoad(VT, dl, InChain, VAList, MachinePointerInfo(), - false, false, false, 0); + return DAG.getLoad(VT, dl, InChain, VAList, MachinePointerInfo()); } SDValue XCoreTargetLowering:: @@ -799,7 +785,7 @@ XCoreFunctionInfo *XFI = MF.getInfo(); SDValue Addr = DAG.getFrameIndex(XFI->getVarArgsFrameIndex(), MVT::i32); return DAG.getStore(Op.getOperand(0), dl, Addr, Op.getOperand(1), - MachinePointerInfo(), false, false, 0); + MachinePointerInfo()); } SDValue XCoreTargetLowering::LowerFRAMEADDR(SDValue Op, @@ -832,9 +818,9 @@ XCoreFunctionInfo *XFI = MF.getInfo(); int FI = XFI->createLRSpillSlot(MF); SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); - return DAG.getLoad( - getPointerTy(DAG.getDataLayout()), SDLoc(Op), DAG.getEntryNode(), FIN, - MachinePointerInfo::getFixedStack(MF, FI), false, false, false, 0); + return DAG.getLoad(getPointerTy(DAG.getDataLayout()), SDLoc(Op), + DAG.getEntryNode(), FIN, + MachinePointerInfo::getFixedStack(MF, FI)); } SDValue XCoreTargetLowering:: @@ -915,33 +901,31 @@ SDValue Addr = Trmp; SDLoc dl(Op); - OutChains[0] = DAG.getStore(Chain, dl, - DAG.getConstant(0x0a3cd805, dl, MVT::i32), Addr, - MachinePointerInfo(TrmpAddr), false, false, 0); + OutChains[0] = + DAG.getStore(Chain, dl, DAG.getConstant(0x0a3cd805, dl, MVT::i32), Addr, + MachinePointerInfo(TrmpAddr)); Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, DAG.getConstant(4, dl, MVT::i32)); - OutChains[1] = DAG.getStore(Chain, dl, - DAG.getConstant(0xd80456c0, dl, MVT::i32), Addr, - MachinePointerInfo(TrmpAddr, 4), false, false, 0); + OutChains[1] = + DAG.getStore(Chain, dl, DAG.getConstant(0xd80456c0, dl, MVT::i32), Addr, + MachinePointerInfo(TrmpAddr, 4)); Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, DAG.getConstant(8, dl, MVT::i32)); - OutChains[2] = DAG.getStore(Chain, dl, - DAG.getConstant(0x27fb0a3c, dl, MVT::i32), Addr, - MachinePointerInfo(TrmpAddr, 8), false, false, 0); + OutChains[2] = + DAG.getStore(Chain, dl, DAG.getConstant(0x27fb0a3c, dl, MVT::i32), Addr, + MachinePointerInfo(TrmpAddr, 8)); Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, DAG.getConstant(12, dl, MVT::i32)); - OutChains[3] = DAG.getStore(Chain, dl, Nest, Addr, - MachinePointerInfo(TrmpAddr, 12), false, false, - 0); + OutChains[3] = + DAG.getStore(Chain, dl, Nest, Addr, MachinePointerInfo(TrmpAddr, 12)); Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, DAG.getConstant(16, dl, MVT::i32)); - OutChains[4] = DAG.getStore(Chain, dl, FPtr, Addr, - MachinePointerInfo(TrmpAddr, 16), false, false, - 0); + OutChains[4] = + DAG.getStore(Chain, dl, FPtr, Addr, MachinePointerInfo(TrmpAddr, 16)); return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains); } @@ -973,29 +957,30 @@ LowerATOMIC_LOAD(SDValue Op, SelectionDAG &DAG) const { AtomicSDNode *N = cast(Op); assert(N->getOpcode() == ISD::ATOMIC_LOAD && "Bad Atomic OP"); - assert(N->getOrdering() <= Monotonic && - "setInsertFencesForAtomic(true) and yet greater than Monotonic"); + assert((N->getOrdering() == AtomicOrdering::Unordered || + N->getOrdering() == AtomicOrdering::Monotonic) && + "setInsertFencesForAtomic(true) expects unordered / monotonic"); if (N->getMemoryVT() == MVT::i32) { if (N->getAlignment() < 4) report_fatal_error("atomic load must be aligned"); return DAG.getLoad(getPointerTy(DAG.getDataLayout()), SDLoc(Op), N->getChain(), N->getBasePtr(), N->getPointerInfo(), - N->isVolatile(), N->isNonTemporal(), N->isInvariant(), - N->getAlignment(), N->getAAInfo(), N->getRanges()); + N->getAlignment(), N->getMemOperand()->getFlags(), + N->getAAInfo(), N->getRanges()); } if (N->getMemoryVT() == MVT::i16) { if (N->getAlignment() < 2) report_fatal_error("atomic load must be aligned"); return DAG.getExtLoad(ISD::EXTLOAD, SDLoc(Op), MVT::i32, N->getChain(), N->getBasePtr(), N->getPointerInfo(), MVT::i16, - N->isVolatile(), N->isNonTemporal(), - N->isInvariant(), N->getAlignment(), N->getAAInfo()); + N->getAlignment(), N->getMemOperand()->getFlags(), + N->getAAInfo()); } if (N->getMemoryVT() == MVT::i8) return DAG.getExtLoad(ISD::EXTLOAD, SDLoc(Op), MVT::i32, N->getChain(), N->getBasePtr(), N->getPointerInfo(), MVT::i8, - N->isVolatile(), N->isNonTemporal(), - N->isInvariant(), N->getAlignment(), N->getAAInfo()); + N->getAlignment(), N->getMemOperand()->getFlags(), + N->getAAInfo()); return SDValue(); } @@ -1003,29 +988,29 @@ LowerATOMIC_STORE(SDValue Op, SelectionDAG &DAG) const { AtomicSDNode *N = cast(Op); assert(N->getOpcode() == ISD::ATOMIC_STORE && "Bad Atomic OP"); - assert(N->getOrdering() <= Monotonic && - "setInsertFencesForAtomic(true) and yet greater than Monotonic"); + assert((N->getOrdering() == AtomicOrdering::Unordered || + N->getOrdering() == AtomicOrdering::Monotonic) && + "setInsertFencesForAtomic(true) expects unordered / monotonic"); if (N->getMemoryVT() == MVT::i32) { if (N->getAlignment() < 4) report_fatal_error("atomic store must be aligned"); - return DAG.getStore(N->getChain(), SDLoc(Op), N->getVal(), - N->getBasePtr(), N->getPointerInfo(), - N->isVolatile(), N->isNonTemporal(), - N->getAlignment(), N->getAAInfo()); + return DAG.getStore(N->getChain(), SDLoc(Op), N->getVal(), N->getBasePtr(), + N->getPointerInfo(), N->getAlignment(), + N->getMemOperand()->getFlags(), N->getAAInfo()); } if (N->getMemoryVT() == MVT::i16) { if (N->getAlignment() < 2) report_fatal_error("atomic store must be aligned"); return DAG.getTruncStore(N->getChain(), SDLoc(Op), N->getVal(), N->getBasePtr(), N->getPointerInfo(), MVT::i16, - N->isVolatile(), N->isNonTemporal(), - N->getAlignment(), N->getAAInfo()); + N->getAlignment(), N->getMemOperand()->getFlags(), + N->getAAInfo()); } if (N->getMemoryVT() == MVT::i8) return DAG.getTruncStore(N->getChain(), SDLoc(Op), N->getVal(), N->getBasePtr(), N->getPointerInfo(), MVT::i8, - N->isVolatile(), N->isNonTemporal(), - N->getAlignment(), N->getAAInfo()); + N->getAlignment(), N->getMemOperand()->getFlags(), + N->getAAInfo()); return SDValue(); } @@ -1061,7 +1046,7 @@ switch (CallConv) { default: - llvm_unreachable("Unsupported calling convention"); + report_fatal_error("Unsupported calling convention"); case CallingConv::Fast: case CallingConv::C: return LowerCCCCallTo(Chain, Callee, CallConv, isVarArg, isTailCall, @@ -1071,11 +1056,10 @@ /// LowerCallResult - Lower the result values of a call into the /// appropriate copies out of appropriate physical registers / memory locations. -static SDValue -LowerCallResult(SDValue Chain, SDValue InFlag, - const SmallVectorImpl &RVLocs, - SDLoc dl, SelectionDAG &DAG, - SmallVectorImpl &InVals) { +static SDValue LowerCallResult(SDValue Chain, SDValue InFlag, + const SmallVectorImpl &RVLocs, + const SDLoc &dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) { SmallVector, 4> ResultMemLocs; // Copy results out of physical registers. for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { @@ -1118,15 +1102,12 @@ /// regs to (physical regs)/(stack frame), CALLSEQ_START and /// CALLSEQ_END are emitted. /// TODO: isTailCall, sret. -SDValue -XCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee, - CallingConv::ID CallConv, bool isVarArg, - bool isTailCall, - const SmallVectorImpl &Outs, - const SmallVectorImpl &OutVals, - const SmallVectorImpl &Ins, - SDLoc dl, SelectionDAG &DAG, - SmallVectorImpl &InVals) const { +SDValue XCoreTargetLowering::LowerCCCCallTo( + SDValue Chain, SDValue Callee, CallingConv::ID CallConv, bool isVarArg, + bool isTailCall, const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, + const SmallVectorImpl &Ins, const SDLoc &dl, + SelectionDAG &DAG, SmallVectorImpl &InVals) const { // Analyze operands of the call, assigning locations to each operand. SmallVector ArgLocs; @@ -1150,8 +1131,7 @@ unsigned NumBytes = RetCCInfo.getNextStackOffset(); auto PtrVT = getPointerTy(DAG.getDataLayout()); - Chain = DAG.getCALLSEQ_START(Chain, - DAG.getConstant(NumBytes, dl, PtrVT, true), dl); + Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, dl); SmallVector, 4> RegsToPass; SmallVector MemOpChains; @@ -1256,19 +1236,14 @@ } /// XCore formal arguments implementation -SDValue -XCoreTargetLowering::LowerFormalArguments(SDValue Chain, - CallingConv::ID CallConv, - bool isVarArg, - const SmallVectorImpl &Ins, - SDLoc dl, - SelectionDAG &DAG, - SmallVectorImpl &InVals) - const { +SDValue XCoreTargetLowering::LowerFormalArguments( + SDValue Chain, CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, const SDLoc &dl, + SelectionDAG &DAG, SmallVectorImpl &InVals) const { switch (CallConv) { default: - llvm_unreachable("Unsupported calling convention"); + report_fatal_error("Unsupported calling convention"); case CallingConv::C: case CallingConv::Fast: return LowerCCCArguments(Chain, CallConv, isVarArg, @@ -1280,17 +1255,12 @@ /// virtual registers and generate load operations for /// arguments places on the stack. /// TODO: sret -SDValue -XCoreTargetLowering::LowerCCCArguments(SDValue Chain, - CallingConv::ID CallConv, - bool isVarArg, - const SmallVectorImpl - &Ins, - SDLoc dl, - SelectionDAG &DAG, - SmallVectorImpl &InVals) const { +SDValue XCoreTargetLowering::LowerCCCArguments( + SDValue Chain, CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, const SDLoc &dl, + SelectionDAG &DAG, SmallVectorImpl &InVals) const { MachineFunction &MF = DAG.getMachineFunction(); - MachineFrameInfo *MFI = MF.getFrameInfo(); + MachineFrameInfo &MFI = MF.getFrameInfo(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); XCoreFunctionInfo *XFI = MF.getInfo(); @@ -1333,7 +1303,7 @@ { #ifndef NDEBUG errs() << "LowerFormalArguments Unhandled argument type: " - << RegVT.getSimpleVT().SimpleTy << "\n"; + << RegVT.getEVTString() << "\n"; #endif llvm_unreachable(nullptr); } @@ -1354,16 +1324,15 @@ << "\n"; } // Create the frame index object for this incoming parameter... - int FI = MFI->CreateFixedObject(ObjSize, - LRSaveSize + VA.getLocMemOffset(), - true); + int FI = MFI.CreateFixedObject(ObjSize, + LRSaveSize + VA.getLocMemOffset(), + true); // Create the SelectionDAG nodes corresponding to a load //from this parameter SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); ArgIn = DAG.getLoad(VA.getLocVT(), dl, Chain, FIN, - MachinePointerInfo::getFixedStack(MF, FI), false, - false, false, 0); + MachinePointerInfo::getFixedStack(MF, FI)); } const ArgDataPair ADP = { ArgIn, Ins[i].Flags }; ArgData.push_back(ADP); @@ -1383,7 +1352,7 @@ // address for (int i = array_lengthof(ArgRegs) - 1; i >= (int)FirstVAReg; --i) { // Create a stack slot - int FI = MFI->CreateFixedObject(4, offset, true); + int FI = MFI.CreateFixedObject(4, offset, true); if (i == (int)FirstVAReg) { XFI->setVarArgsFrameIndex(FI); } @@ -1395,15 +1364,15 @@ SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32); CFRegNode.push_back(Val.getValue(Val->getNumValues() - 1)); // Move argument from virt reg -> stack - SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, - MachinePointerInfo(), false, false, 0); + SDValue Store = + DAG.getStore(Val.getValue(1), dl, Val, FIN, MachinePointerInfo()); MemOps.push_back(Store); } } else { // This will point to the next argument passed via stack. XFI->setVarArgsFrameIndex( - MFI->CreateFixedObject(4, LRSaveSize + CCInfo.getNextStackOffset(), - true)); + MFI.CreateFixedObject(4, LRSaveSize + CCInfo.getNextStackOffset(), + true)); } } @@ -1422,7 +1391,7 @@ unsigned Size = ArgDI->Flags.getByValSize(); unsigned Align = std::max(StackSlotSize, ArgDI->Flags.getByValAlign()); // Create a new object on the stack and copy the pointee into it. - int FI = MFI->CreateStackObject(Size, Align, false); + int FI = MFI.CreateStackObject(Size, Align, false); SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); InVals.push_back(FIN); MemOps.push_back(DAG.getMemcpy(Chain, dl, FIN, ArgDI->SDV, @@ -1463,15 +1432,15 @@ } SDValue -XCoreTargetLowering::LowerReturn(SDValue Chain, - CallingConv::ID CallConv, bool isVarArg, +XCoreTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, + bool isVarArg, const SmallVectorImpl &Outs, const SmallVectorImpl &OutVals, - SDLoc dl, SelectionDAG &DAG) const { + const SDLoc &dl, SelectionDAG &DAG) const { XCoreFunctionInfo *XFI = DAG.getMachineFunction().getInfo(); - MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); + MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); // CCValAssign - represent the assignment of // the return value to a location @@ -1507,15 +1476,14 @@ int Offset = VA.getLocMemOffset(); unsigned ObjSize = VA.getLocVT().getSizeInBits() / 8; // Create the frame index object for the memory location. - int FI = MFI->CreateFixedObject(ObjSize, Offset, false); + int FI = MFI.CreateFixedObject(ObjSize, Offset, false); // Create a SelectionDAG node corresponding to a store // to this memory location. SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); MemOpChains.push_back(DAG.getStore( Chain, dl, OutVals[i], FIN, - MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI), false, - false, 0)); + MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI))); } // Transform all store nodes into one single node because @@ -1551,11 +1519,11 @@ //===----------------------------------------------------------------------===// MachineBasicBlock * -XCoreTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, +XCoreTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const { const TargetInstrInfo &TII = *Subtarget.getInstrInfo(); - DebugLoc dl = MI->getDebugLoc(); - assert((MI->getOpcode() == XCore::SELECT_CC) && + DebugLoc dl = MI.getDebugLoc(); + assert((MI.getOpcode() == XCore::SELECT_CC) && "Unexpected instr type to insert"); // To "insert" a SELECT_CC instruction, we actually have to insert the diamond @@ -1588,7 +1556,8 @@ BB->addSuccessor(sinkMBB); BuildMI(BB, dl, TII.get(XCore::BRFT_lru6)) - .addReg(MI->getOperand(1).getReg()).addMBB(sinkMBB); + .addReg(MI.getOperand(1).getReg()) + .addMBB(sinkMBB); // copy0MBB: // %FalseValue = ... @@ -1602,12 +1571,13 @@ // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] // ... BB = sinkMBB; - BuildMI(*BB, BB->begin(), dl, - TII.get(XCore::PHI), MI->getOperand(0).getReg()) - .addReg(MI->getOperand(3).getReg()).addMBB(copy0MBB) - .addReg(MI->getOperand(2).getReg()).addMBB(thisMBB); + BuildMI(*BB, BB->begin(), dl, TII.get(XCore::PHI), MI.getOperand(0).getReg()) + .addReg(MI.getOperand(3).getReg()) + .addMBB(copy0MBB) + .addReg(MI.getOperand(2).getReg()) + .addMBB(thisMBB); - MI->eraseFromParent(); // The pseudo instruction is gone now. + MI.eraseFromParent(); // The pseudo instruction is gone now. return BB; } @@ -1631,13 +1601,12 @@ if (OutVal.hasOneUse()) { unsigned BitWidth = OutVal.getValueSizeInBits(); APInt DemandedMask = APInt::getLowBitsSet(BitWidth, 8); - APInt KnownZero, KnownOne; + KnownBits Known; TargetLowering::TargetLoweringOpt TLO(DAG, !DCI.isBeforeLegalize(), !DCI.isBeforeLegalizeOps()); const TargetLowering &TLI = DAG.getTargetLoweringInfo(); - if (TLO.ShrinkDemandedConstant(OutVal, DemandedMask) || - TLI.SimplifyDemandedBits(OutVal, DemandedMask, KnownZero, KnownOne, - TLO)) + if (TLI.ShrinkDemandedConstant(OutVal, DemandedMask, TLO) || + TLI.SimplifyDemandedBits(OutVal, DemandedMask, Known, TLO)) DCI.CommitTargetLoweringOpt(TLO); } break; @@ -1648,13 +1617,12 @@ if (Time.hasOneUse()) { unsigned BitWidth = Time.getValueSizeInBits(); APInt DemandedMask = APInt::getLowBitsSet(BitWidth, 16); - APInt KnownZero, KnownOne; + KnownBits Known; TargetLowering::TargetLoweringOpt TLO(DAG, !DCI.isBeforeLegalize(), !DCI.isBeforeLegalizeOps()); const TargetLowering &TLI = DAG.getTargetLoweringInfo(); - if (TLO.ShrinkDemandedConstant(Time, DemandedMask) || - TLI.SimplifyDemandedBits(Time, DemandedMask, KnownZero, KnownOne, - TLO)) + if (TLI.ShrinkDemandedConstant(Time, DemandedMask, TLO) || + TLI.SimplifyDemandedBits(Time, DemandedMask, Known, TLO)) DCI.CommitTargetLoweringOpt(TLO); } break; @@ -1685,11 +1653,11 @@ // fold (ladd x, 0, y) -> 0, add x, y iff carry is unused and y has only the // low bit set if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 1)) { - APInt KnownZero, KnownOne; + KnownBits Known; APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), VT.getSizeInBits() - 1); - DAG.computeKnownBits(N2, KnownZero, KnownOne); - if ((KnownZero & Mask) == Mask) { + DAG.computeKnownBits(N2, Known); + if ((Known.Zero & Mask) == Mask) { SDValue Carry = DAG.getConstant(0, dl, VT); SDValue Result = DAG.getNode(ISD::ADD, dl, VT, N0, N2); SDValue Ops[] = { Result, Carry }; @@ -1708,11 +1676,11 @@ // fold (lsub 0, 0, x) -> x, -x iff x has only the low bit set if (N0C && N0C->isNullValue() && N1C && N1C->isNullValue()) { - APInt KnownZero, KnownOne; + KnownBits Known; APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), VT.getSizeInBits() - 1); - DAG.computeKnownBits(N2, KnownZero, KnownOne); - if ((KnownZero & Mask) == Mask) { + DAG.computeKnownBits(N2, Known); + if ((Known.Zero & Mask) == Mask) { SDValue Borrow = N2; SDValue Result = DAG.getNode(ISD::SUB, dl, VT, DAG.getConstant(0, dl, VT), N2); @@ -1724,11 +1692,11 @@ // fold (lsub x, 0, y) -> 0, sub x, y iff borrow is unused and y has only the // low bit set if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 1)) { - APInt KnownZero, KnownOne; + KnownBits Known; APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), VT.getSizeInBits() - 1); - DAG.computeKnownBits(N2, KnownZero, KnownOne); - if ((KnownZero & Mask) == Mask) { + DAG.computeKnownBits(N2, Known); + if ((Known.Zero & Mask) == Mask) { SDValue Borrow = DAG.getConstant(0, dl, VT); SDValue Result = DAG.getNode(ISD::SUB, dl, VT, N0, N2); SDValue Ops[] = { Result, Borrow }; @@ -1852,19 +1820,19 @@ } void XCoreTargetLowering::computeKnownBitsForTargetNode(const SDValue Op, - APInt &KnownZero, - APInt &KnownOne, + KnownBits &Known, + const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const { - KnownZero = KnownOne = APInt(KnownZero.getBitWidth(), 0); + Known.resetAll(); switch (Op.getOpcode()) { default: break; case XCoreISD::LADD: case XCoreISD::LSUB: if (Op.getResNo() == 1) { // Top bits of carry / borrow are clear. - KnownZero = APInt::getHighBitsSet(KnownZero.getBitWidth(), - KnownZero.getBitWidth() - 1); + Known.Zero = APInt::getHighBitsSet(Known.getBitWidth(), + Known.getBitWidth() - 1); } break; case ISD::INTRINSIC_W_CHAIN: @@ -1873,24 +1841,24 @@ switch (IntNo) { case Intrinsic::xcore_getts: // High bits are known to be zero. - KnownZero = APInt::getHighBitsSet(KnownZero.getBitWidth(), - KnownZero.getBitWidth() - 16); + Known.Zero = APInt::getHighBitsSet(Known.getBitWidth(), + Known.getBitWidth() - 16); break; case Intrinsic::xcore_int: case Intrinsic::xcore_inct: // High bits are known to be zero. - KnownZero = APInt::getHighBitsSet(KnownZero.getBitWidth(), - KnownZero.getBitWidth() - 8); + Known.Zero = APInt::getHighBitsSet(Known.getBitWidth(), + Known.getBitWidth() - 8); break; case Intrinsic::xcore_testct: // Result is either 0 or 1. - KnownZero = APInt::getHighBitsSet(KnownZero.getBitWidth(), - KnownZero.getBitWidth() - 1); + Known.Zero = APInt::getHighBitsSet(Known.getBitWidth(), + Known.getBitWidth() - 1); break; case Intrinsic::xcore_testwct: // Result is in the range 0 - 4. - KnownZero = APInt::getHighBitsSet(KnownZero.getBitWidth(), - KnownZero.getBitWidth() - 3); + Known.Zero = APInt::getHighBitsSet(Known.getBitWidth(), + Known.getBitWidth() - 3); break; } } @@ -1921,7 +1889,8 @@ /// by AM is legal for this target, for a load/store of the specified type. bool XCoreTargetLowering::isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, - unsigned AS) const { + unsigned AS, + Instruction *I) const { #ifndef noCbC if (Ty->getTypeID() == Type::VoidTyID || Ty->getTypeID() == Type::__CodeTyID) #else diff -r 56c5119fbcd2 -r c4cc77a799c9 lib/Transforms/IPO/PassManagerBuilder.cpp --- a/lib/Transforms/IPO/PassManagerBuilder.cpp Sun Dec 03 20:09:16 2017 +0900 +++ b/lib/Transforms/IPO/PassManagerBuilder.cpp Mon Dec 04 21:20:52 2017 +0900 @@ -16,41 +16,46 @@ #include "llvm-c/Transforms/PassManagerBuilder.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/BasicAliasAnalysis.h" -#include "llvm/Analysis/CFLAliasAnalysis.h" +#include "llvm/Analysis/CFLAndersAliasAnalysis.h" +#include "llvm/Analysis/CFLSteensAliasAnalysis.h" #include "llvm/Analysis/GlobalsModRef.h" +#include "llvm/Analysis/InlineCost.h" #include "llvm/Analysis/Passes.h" #include "llvm/Analysis/ScopedNoAliasAA.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TypeBasedAliasAnalysis.h" #include "llvm/IR/DataLayout.h" -#include "llvm/IR/FunctionInfo.h" #include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/ModuleSummaryIndex.h" #include "llvm/IR/Verifier.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/IPO/ForceFunctionAttrs.h" +#include "llvm/Transforms/IPO/FunctionAttrs.h" #include "llvm/Transforms/IPO/InferFunctionAttrs.h" +#include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Scalar/GVN.h" +#include "llvm/Transforms/Scalar/SimpleLoopUnswitch.h" #include "llvm/Transforms/Vectorize.h" -#include "llvm/Transforms/Instrumentation.h" using namespace llvm; static cl::opt -RunLoopVectorization("vectorize-loops", cl::Hidden, - cl::desc("Run the Loop vectorization passes")); + RunPartialInlining("enable-partial-inlining", cl::init(false), cl::Hidden, + cl::ZeroOrMore, cl::desc("Run Partial inlinining pass")); + +static cl::opt + RunLoopVectorization("vectorize-loops", cl::Hidden, + cl::desc("Run the Loop vectorization passes")); static cl::opt RunSLPVectorization("vectorize-slp", cl::Hidden, cl::desc("Run the SLP vectorization passes")); static cl::opt -RunBBVectorization("vectorize-slp-aggressive", cl::Hidden, - cl::desc("Run the BB vectorization passes")); - -static cl::opt UseGVNAfterVectorization("use-gvn-after-vectorization", cl::init(false), cl::Hidden, cl::desc("Run GVN instead of Early CSE after vectorization passes")); @@ -59,21 +64,12 @@ "extra-vectorizer-passes", cl::init(false), cl::Hidden, cl::desc("Run cleanup optimization passes after vectorization.")); -static cl::opt UseNewSROA("use-new-sroa", - cl::init(true), cl::Hidden, - cl::desc("Enable the new, experimental SROA pass")); - static cl::opt RunLoopRerolling("reroll-loops", cl::Hidden, cl::desc("Run the loop rerolling pass")); -static cl::opt -RunFloat2Int("float-to-int", cl::Hidden, cl::init(true), - cl::desc("Run the float2int (float demotion) pass")); - -static cl::opt RunLoadCombine("combine-loads", cl::init(false), - cl::Hidden, - cl::desc("Run the load combining pass")); +static cl::opt RunNewGVN("enable-newgvn", cl::init(false), cl::Hidden, + cl::desc("Run the NewGVN pass")); static cl::opt RunSLPAfterLoopVectorization("run-slp-after-loop-vectorization", @@ -81,61 +77,96 @@ cl::desc("Run the SLP vectorizer (and BB vectorizer) after the Loop " "vectorizer instead of before")); -static cl::opt UseCFLAA("use-cfl-aa", - cl::init(false), cl::Hidden, - cl::desc("Enable the new, experimental CFL alias analysis")); - -static cl::opt -EnableMLSM("mlsm", cl::init(true), cl::Hidden, - cl::desc("Enable motion of merged load and store")); +// Experimental option to use CFL-AA +enum class CFLAAType { None, Steensgaard, Andersen, Both }; +static cl::opt + UseCFLAA("use-cfl-aa", cl::init(CFLAAType::None), cl::Hidden, + cl::desc("Enable the new, experimental CFL alias analysis"), + cl::values(clEnumValN(CFLAAType::None, "none", "Disable CFL-AA"), + clEnumValN(CFLAAType::Steensgaard, "steens", + "Enable unification-based CFL-AA"), + clEnumValN(CFLAAType::Andersen, "anders", + "Enable inclusion-based CFL-AA"), + clEnumValN(CFLAAType::Both, "both", + "Enable both variants of CFL-AA"))); static cl::opt EnableLoopInterchange( "enable-loopinterchange", cl::init(false), cl::Hidden, cl::desc("Enable the new, experimental LoopInterchange Pass")); -static cl::opt EnableLoopDistribute( - "enable-loop-distribute", cl::init(false), cl::Hidden, - cl::desc("Enable the new, experimental LoopDistribution Pass")); - -static cl::opt EnableNonLTOGlobalsModRef( - "enable-non-lto-gmr", cl::init(true), cl::Hidden, - cl::desc( - "Enable the GlobalsModRef AliasAnalysis outside of the LTO pipeline.")); +static cl::opt + EnablePrepareForThinLTO("prepare-for-thinlto", cl::init(false), cl::Hidden, + cl::desc("Enable preparation for ThinLTO.")); -static cl::opt EnableLoopLoadElim( - "enable-loop-load-elim", cl::init(false), cl::Hidden, - cl::desc("Enable the new, experimental LoopLoadElimination Pass")); +static cl::opt RunPGOInstrGen( + "profile-generate", cl::init(false), cl::Hidden, + cl::desc("Enable PGO instrumentation.")); -static cl::opt RunPGOInstrGen( - "profile-generate", cl::init(""), cl::Hidden, - cl::desc("Enable generation phase of PGO instrumentation and specify the " - "path of profile data file")); +static cl::opt + PGOOutputFile("profile-generate-file", cl::init(""), cl::Hidden, + cl::desc("Specify the path of profile data file.")); static cl::opt RunPGOInstrUse( "profile-use", cl::init(""), cl::Hidden, cl::value_desc("filename"), cl::desc("Enable use phase of PGO instrumentation and specify the path " "of profile data file")); +static cl::opt UseLoopVersioningLICM( + "enable-loop-versioning-licm", cl::init(false), cl::Hidden, + cl::desc("Enable the experimental Loop Versioning LICM pass")); + +static cl::opt + DisablePreInliner("disable-preinline", cl::init(false), cl::Hidden, + cl::desc("Disable pre-instrumentation inliner")); + +static cl::opt PreInlineThreshold( + "preinline-threshold", cl::Hidden, cl::init(75), cl::ZeroOrMore, + cl::desc("Control the amount of inlining in pre-instrumentation inliner " + "(default = 75)")); + +static cl::opt EnableEarlyCSEMemSSA( + "enable-earlycse-memssa", cl::init(true), cl::Hidden, + cl::desc("Enable the EarlyCSE w/ MemorySSA pass (default = on)")); + +static cl::opt EnableGVNHoist( + "enable-gvn-hoist", cl::init(false), cl::Hidden, + cl::desc("Enable the GVN hoisting pass (default = off)")); + +static cl::opt + DisableLibCallsShrinkWrap("disable-libcalls-shrinkwrap", cl::init(false), + cl::Hidden, + cl::desc("Disable shrink-wrap library calls")); + +static cl::opt + EnableSimpleLoopUnswitch("enable-simple-loop-unswitch", cl::init(false), + cl::Hidden, + cl::desc("Enable the simple loop unswitch pass.")); + +static cl::opt EnableGVNSink( + "enable-gvn-sink", cl::init(false), cl::Hidden, + cl::desc("Enable the GVN sinking pass (default = off)")); + PassManagerBuilder::PassManagerBuilder() { OptLevel = 2; SizeLevel = 0; LibraryInfo = nullptr; Inliner = nullptr; - FunctionIndex = nullptr; - DisableUnitAtATime = false; DisableUnrollLoops = false; - BBVectorize = RunBBVectorization; SLPVectorize = RunSLPVectorization; LoopVectorize = RunLoopVectorization; RerollLoops = RunLoopRerolling; - LoadCombine = RunLoadCombine; + NewGVN = RunNewGVN; DisableGVNLoadPRE = false; VerifyInput = false; VerifyOutput = false; MergeFunctions = false; PrepareForLTO = false; - PGOInstrGen = RunPGOInstrGen; + EnablePGOInstrGen = RunPGOInstrGen; + PGOInstrGen = PGOOutputFile; PGOInstrUse = RunPGOInstrUse; + PrepareForThinLTO = EnablePrepareForThinLTO; + PerformThinLTO = false; + DivergentTarget = false; } PassManagerBuilder::~PassManagerBuilder() { @@ -147,21 +178,31 @@ static ManagedStatic, 8> > GlobalExtensions; +/// Check if GlobalExtensions is constructed and not empty. +/// Since GlobalExtensions is a managed static, calling 'empty()' will trigger +/// the construction of the object. +static bool GlobalExtensionsNotEmpty() { + return GlobalExtensions.isConstructed() && !GlobalExtensions->empty(); +} + void PassManagerBuilder::addGlobalExtension( PassManagerBuilder::ExtensionPointTy Ty, PassManagerBuilder::ExtensionFn Fn) { - GlobalExtensions->push_back(std::make_pair(Ty, Fn)); + GlobalExtensions->push_back(std::make_pair(Ty, std::move(Fn))); } void PassManagerBuilder::addExtension(ExtensionPointTy Ty, ExtensionFn Fn) { - Extensions.push_back(std::make_pair(Ty, Fn)); + Extensions.push_back(std::make_pair(Ty, std::move(Fn))); } void PassManagerBuilder::addExtensionsToPM(ExtensionPointTy ETy, legacy::PassManagerBase &PM) const { - for (unsigned i = 0, e = GlobalExtensions->size(); i != e; ++i) - if ((*GlobalExtensions)[i].first == ETy) - (*GlobalExtensions)[i].second(*this, PM); + if (GlobalExtensionsNotEmpty()) { + for (auto &Ext : *GlobalExtensions) { + if (Ext.first == ETy) + Ext.second(*this, PM); + } + } for (unsigned i = 0, e = Extensions.size(); i != e; ++i) if (Extensions[i].first == ETy) Extensions[i].second(*this, PM); @@ -169,15 +210,34 @@ void PassManagerBuilder::addInitialAliasAnalysisPasses( legacy::PassManagerBase &PM) const { + switch (UseCFLAA) { + case CFLAAType::Steensgaard: + PM.add(createCFLSteensAAWrapperPass()); + break; + case CFLAAType::Andersen: + PM.add(createCFLAndersAAWrapperPass()); + break; + case CFLAAType::Both: + PM.add(createCFLSteensAAWrapperPass()); + PM.add(createCFLAndersAAWrapperPass()); + break; + default: + break; + } + // Add TypeBasedAliasAnalysis before BasicAliasAnalysis so that // BasicAliasAnalysis wins if they disagree. This is intended to help // support "obvious" type-punning idioms. - if (UseCFLAA) - PM.add(createCFLAAWrapperPass()); PM.add(createTypeBasedAAWrapperPass()); PM.add(createScopedNoAliasAAWrapperPass()); } +void PassManagerBuilder::addInstructionCombiningPass( + legacy::PassManagerBase &PM) const { + bool ExpensiveCombines = OptLevel > 2; + PM.add(createInstructionCombiningPass(ExpensiveCombines)); +} + void PassManagerBuilder::populateFunctionPassManager( legacy::FunctionPassManager &FPM) { addExtensionsToPM(EP_EarlyAsPossible, FPM); @@ -188,10 +248,7 @@ #ifndef noCbC if (OptLevel == 0) { - if (UseNewSROA) - FPM.add(createSROAPass(true)); - else - FPM.add(createScalarReplAggregatesPass()); + FPM.add(createSROAPass(true)); } #else if (OptLevel == 0) return; @@ -201,15 +258,9 @@ FPM.add(createCFGSimplificationPass()); #ifndef noCbC - if (UseNewSROA) - FPM.add(createSROAPass(false)); - else - FPM.add(createScalarReplAggregatesPass()); + FPM.add(createSROAPass(false)); #else - if (UseNewSROA) - FPM.add(createSROAPass()); - else - FPM.add(createScalarReplAggregatesPass()); + FPM.add(createSROAPass()); #endif FPM.add(createEarlyCSEPass()); FPM.add(createLowerExpectIntrinsicPass()); @@ -217,19 +268,152 @@ // Do PGO instrumentation generation or use pass as the option specified. void PassManagerBuilder::addPGOInstrPasses(legacy::PassManagerBase &MPM) { - if (!PGOInstrGen.empty()) { - MPM.add(createPGOInstrumentationGenPass()); + if (!EnablePGOInstrGen && PGOInstrUse.empty() && PGOSampleUse.empty()) + return; + // Perform the preinline and cleanup passes for O1 and above. + // And avoid doing them if optimizing for size. + if (OptLevel > 0 && SizeLevel == 0 && !DisablePreInliner && + PGOSampleUse.empty()) { + // Create preinline pass. We construct an InlineParams object and specify + // the threshold here to avoid the command line options of the regular + // inliner to influence pre-inlining. The only fields of InlineParams we + // care about are DefaultThreshold and HintThreshold. + InlineParams IP; + IP.DefaultThreshold = PreInlineThreshold; + // FIXME: The hint threshold has the same value used by the regular inliner. + // This should probably be lowered after performance testing. + IP.HintThreshold = 325; + + MPM.add(createFunctionInliningPass(IP)); + MPM.add(createSROAPass()); + MPM.add(createEarlyCSEPass()); // Catch trivial redundancies + MPM.add(createCFGSimplificationPass()); // Merge & remove BBs + MPM.add(createInstructionCombiningPass()); // Combine silly seq's + addExtensionsToPM(EP_Peephole, MPM); + } + if (EnablePGOInstrGen) { + MPM.add(createPGOInstrumentationGenLegacyPass()); // Add the profile lowering pass. InstrProfOptions Options; - Options.InstrProfileOutput = PGOInstrGen; - MPM.add(createInstrProfilingPass(Options)); + if (!PGOInstrGen.empty()) + Options.InstrProfileOutput = PGOInstrGen; + Options.DoCounterPromotion = true; + MPM.add(createLoopRotatePass()); + MPM.add(createInstrProfilingLegacyPass(Options)); } if (!PGOInstrUse.empty()) - MPM.add(createPGOInstrumentationUsePass(PGOInstrUse)); + MPM.add(createPGOInstrumentationUseLegacyPass(PGOInstrUse)); + // Indirect call promotion that promotes intra-module targets only. + // For ThinLTO this is done earlier due to interactions with globalopt + // for imported functions. We don't run this at -O0. + if (OptLevel > 0) + MPM.add( + createPGOIndirectCallPromotionLegacyPass(false, !PGOSampleUse.empty())); +} +void PassManagerBuilder::addFunctionSimplificationPasses( + legacy::PassManagerBase &MPM) { + // Start of function pass. + // Break up aggregate allocas, using SSAUpdater. +#ifndef noCbC + MPM.add(createSROAPass(false)); +#else + MPM.add(createSROAPass()); +#endif + MPM.add(createEarlyCSEPass(EnableEarlyCSEMemSSA)); // Catch trivial redundancies + if (EnableGVNHoist) + MPM.add(createGVNHoistPass()); + if (EnableGVNSink) { + MPM.add(createGVNSinkPass()); + MPM.add(createCFGSimplificationPass()); + } + + // Speculative execution if the target has divergent branches; otherwise nop. + MPM.add(createSpeculativeExecutionIfHasBranchDivergencePass()); + MPM.add(createJumpThreadingPass()); // Thread jumps. + MPM.add(createCorrelatedValuePropagationPass()); // Propagate conditionals + MPM.add(createCFGSimplificationPass()); // Merge & remove BBs + // Combine silly seq's + addInstructionCombiningPass(MPM); + if (SizeLevel == 0 && !DisableLibCallsShrinkWrap) + MPM.add(createLibCallsShrinkWrapPass()); + addExtensionsToPM(EP_Peephole, MPM); + + // Optimize memory intrinsic calls based on the profiled size information. + if (SizeLevel == 0) + MPM.add(createPGOMemOPSizeOptLegacyPass()); + +#ifndef noCbC + MPM.add(createTailCallEliminationPass(false)); // Eliminate tail calls +#else + MPM.add(createTailCallEliminationPass()); // Eliminate tail calls +#endif + MPM.add(createCFGSimplificationPass()); // Merge & remove BBs + MPM.add(createReassociatePass()); // Reassociate expressions + // Rotate Loop - disable header duplication at -Oz + MPM.add(createLoopRotatePass(SizeLevel == 2 ? 0 : -1)); + MPM.add(createLICMPass()); // Hoist loop invariants + if (EnableSimpleLoopUnswitch) + MPM.add(createSimpleLoopUnswitchLegacyPass()); + else + MPM.add(createLoopUnswitchPass(SizeLevel || OptLevel < 3, DivergentTarget)); + MPM.add(createCFGSimplificationPass()); + addInstructionCombiningPass(MPM); + MPM.add(createIndVarSimplifyPass()); // Canonicalize indvars + MPM.add(createLoopIdiomPass()); // Recognize idioms like memset. + addExtensionsToPM(EP_LateLoopOptimizations, MPM); + MPM.add(createLoopDeletionPass()); // Delete dead loops + + if (EnableLoopInterchange) { + MPM.add(createLoopInterchangePass()); // Interchange loops + MPM.add(createCFGSimplificationPass()); + } + if (!DisableUnrollLoops) + MPM.add(createSimpleLoopUnrollPass(OptLevel)); // Unroll small loops + addExtensionsToPM(EP_LoopOptimizerEnd, MPM); + + if (OptLevel > 1) { + MPM.add(createMergedLoadStoreMotionPass()); // Merge ld/st in diamonds + MPM.add(NewGVN ? createNewGVNPass() + : createGVNPass(DisableGVNLoadPRE)); // Remove redundancies + } + MPM.add(createMemCpyOptPass()); // Remove memcpy / form memset + MPM.add(createSCCPPass()); // Constant prop with SCCP + + // Delete dead bit computations (instcombine runs after to fold away the dead + // computations, and then ADCE will run later to exploit any new DCE + // opportunities that creates). + MPM.add(createBitTrackingDCEPass()); // Delete dead bit computations + + // Run instcombine after redundancy elimination to exploit opportunities + // opened up by them. + addInstructionCombiningPass(MPM); + addExtensionsToPM(EP_Peephole, MPM); + MPM.add(createJumpThreadingPass()); // Thread jumps + MPM.add(createCorrelatedValuePropagationPass()); + MPM.add(createDeadStoreEliminationPass()); // Delete dead stores + MPM.add(createLICMPass()); + + addExtensionsToPM(EP_ScalarOptimizerLate, MPM); + + if (RerollLoops) + MPM.add(createLoopRerollPass()); + if (!RunSLPAfterLoopVectorization && SLPVectorize) + MPM.add(createSLPVectorizerPass()); // Vectorize parallel scalar chains. + + MPM.add(createAggressiveDCEPass()); // Delete dead instructions + MPM.add(createCFGSimplificationPass()); // Merge & remove BBs + // Clean up after everything. + addInstructionCombiningPass(MPM); + addExtensionsToPM(EP_Peephole, MPM); } void PassManagerBuilder::populateModulePassManager( legacy::PassManagerBase &MPM) { + if (!PGOSampleUse.empty()) { + MPM.add(createPruneEHPass()); + MPM.add(createSampleProfileLoaderPass(PGOSampleUse)); + } + // Allow forcing function attributes as a debugging and tuning aid. MPM.add(createForceFunctionAttrsLegacyPass()); @@ -246,10 +430,10 @@ // creates a CGSCC pass manager, but we don't want to add extensions into // that pass manager. To prevent this we insert a no-op module pass to reset // the pass manager to get the same behavior as EP_OptimizerLast in non-O0 - // builds. The function merging pass is + // builds. The function merging pass is if (MergeFunctions) MPM.add(createMergeFunctionsPass()); - else if (!GlobalExtensions->empty() || !Extensions.empty()) + else if (GlobalExtensionsNotEmpty() || !Extensions.empty()) MPM.add(createBarrierNoopPass()); #ifndef noCbC @@ -257,6 +441,13 @@ #endif addExtensionsToPM(EP_EnabledOnOptLevel0, MPM); + + // Rename anon globals to be able to export them in the summary. + // This has to be done after we add the extensions to the pass manager + // as there could be passes (e.g. Adddress sanitizer) which introduce + // new unnamed globals. + if (PrepareForThinLTO) + MPM.add(createNameAnonGlobalPass()); return; } @@ -266,150 +457,80 @@ addInitialAliasAnalysisPasses(MPM); - if (!DisableUnitAtATime) { - // Infer attributes about declarations if possible. - MPM.add(createInferFunctionAttrsLegacyPass()); - - addExtensionsToPM(EP_ModuleOptimizerEarly, MPM); + // For ThinLTO there are two passes of indirect call promotion. The + // first is during the compile phase when PerformThinLTO=false and + // intra-module indirect call targets are promoted. The second is during + // the ThinLTO backend when PerformThinLTO=true, when we promote imported + // inter-module indirect calls. For that we perform indirect call promotion + // earlier in the pass pipeline, here before globalopt. Otherwise imported + // available_externally functions look unreferenced and are removed. + if (PerformThinLTO) + MPM.add(createPGOIndirectCallPromotionLegacyPass(/*InLTO = */ true, + !PGOSampleUse.empty())); - MPM.add(createIPSCCPPass()); // IP SCCP - MPM.add(createGlobalOptimizerPass()); // Optimize out global vars - // Promote any localized global vars - MPM.add(createPromoteMemoryToRegisterPass()); + // For SamplePGO in ThinLTO compile phase, we do not want to unroll loops + // as it will change the CFG too much to make the 2nd profile annotation + // in backend more difficult. + bool PrepareForThinLTOUsingPGOSampleProfile = + PrepareForThinLTO && !PGOSampleUse.empty(); + if (PrepareForThinLTOUsingPGOSampleProfile) + DisableUnrollLoops = true; - MPM.add(createDeadArgEliminationPass()); // Dead argument elimination + // Infer attributes about declarations if possible. + MPM.add(createInferFunctionAttrsLegacyPass()); + + addExtensionsToPM(EP_ModuleOptimizerEarly, MPM); - MPM.add(createInstructionCombiningPass());// Clean up after IPCP & DAE - addExtensionsToPM(EP_Peephole, MPM); - MPM.add(createCFGSimplificationPass()); // Clean up after IPCP & DAE - } + MPM.add(createIPSCCPPass()); // IP SCCP + MPM.add(createCalledValuePropagationPass()); + MPM.add(createGlobalOptimizerPass()); // Optimize out global vars + // Promote any localized global vars. + MPM.add(createPromoteMemoryToRegisterPass()); + + MPM.add(createDeadArgEliminationPass()); // Dead argument elimination + + addInstructionCombiningPass(MPM); // Clean up after IPCP & DAE + addExtensionsToPM(EP_Peephole, MPM); + MPM.add(createCFGSimplificationPass()); // Clean up after IPCP & DAE - addPGOInstrPasses(MPM); + // For SamplePGO in ThinLTO compile phase, we do not want to do indirect + // call promotion as it will change the CFG too much to make the 2nd + // profile annotation in backend more difficult. + // PGO instrumentation is added during the compile phase for ThinLTO, do + // not run it a second time + if (!PerformThinLTO && !PrepareForThinLTOUsingPGOSampleProfile) + addPGOInstrPasses(MPM); - if (EnableNonLTOGlobalsModRef) - // We add a module alias analysis pass here. In part due to bugs in the - // analysis infrastructure this "works" in that the analysis stays alive - // for the entire SCC pass run below. - MPM.add(createGlobalsAAWrapperPass()); + // We add a module alias analysis pass here. In part due to bugs in the + // analysis infrastructure this "works" in that the analysis stays alive + // for the entire SCC pass run below. + MPM.add(createGlobalsAAWrapperPass()); // Start of CallGraph SCC passes. - if (!DisableUnitAtATime) - MPM.add(createPruneEHPass()); // Remove dead EH info + MPM.add(createPruneEHPass()); // Remove dead EH info + bool RunInliner = false; if (Inliner) { MPM.add(Inliner); Inliner = nullptr; - } - if (!DisableUnitAtATime) - MPM.add(createPostOrderFunctionAttrsPass()); - if (OptLevel > 2) - MPM.add(createArgumentPromotionPass()); // Scalarize uninlined fn args - - // Start of function pass. - // Break up aggregate allocas, using SSAUpdater. -#ifndef noCbC - if (UseNewSROA) - MPM.add(createSROAPass(false)); - else - MPM.add(createScalarReplAggregatesPass(-1, false)); -#else - if (UseNewSROA) - MPM.add(createSROAPass()); - else - MPM.add(createScalarReplAggregatesPass(-1, false)); -#endif - MPM.add(createEarlyCSEPass()); // Catch trivial redundancies - MPM.add(createJumpThreadingPass()); // Thread jumps. - MPM.add(createCorrelatedValuePropagationPass()); // Propagate conditionals - MPM.add(createCFGSimplificationPass()); // Merge & remove BBs - MPM.add(createInstructionCombiningPass()); // Combine silly seq's - addExtensionsToPM(EP_Peephole, MPM); - -#ifndef noCbC - MPM.add(createTailCallEliminationPass(false)); // Eliminate tail calls -#else - MPM.add(createTailCallEliminationPass()); // Eliminate tail calls -#endif - MPM.add(createCFGSimplificationPass()); // Merge & remove BBs - MPM.add(createReassociatePass()); // Reassociate expressions - // Rotate Loop - disable header duplication at -Oz - MPM.add(createLoopRotatePass(SizeLevel == 2 ? 0 : -1)); - MPM.add(createLICMPass()); // Hoist loop invariants - MPM.add(createLoopUnswitchPass(SizeLevel || OptLevel < 3)); - MPM.add(createCFGSimplificationPass()); - MPM.add(createInstructionCombiningPass()); - MPM.add(createIndVarSimplifyPass()); // Canonicalize indvars - MPM.add(createLoopIdiomPass()); // Recognize idioms like memset. - MPM.add(createLoopDeletionPass()); // Delete dead loops - if (EnableLoopInterchange) { - MPM.add(createLoopInterchangePass()); // Interchange loops - MPM.add(createCFGSimplificationPass()); - } - if (!DisableUnrollLoops) - MPM.add(createSimpleLoopUnrollPass()); // Unroll small loops - addExtensionsToPM(EP_LoopOptimizerEnd, MPM); - - if (OptLevel > 1) { - if (EnableMLSM) - MPM.add(createMergedLoadStoreMotionPass()); // Merge ld/st in diamonds - MPM.add(createGVNPass(DisableGVNLoadPRE)); // Remove redundancies - } - MPM.add(createMemCpyOptPass()); // Remove memcpy / form memset - MPM.add(createSCCPPass()); // Constant prop with SCCP - - // Delete dead bit computations (instcombine runs after to fold away the dead - // computations, and then ADCE will run later to exploit any new DCE - // opportunities that creates). - MPM.add(createBitTrackingDCEPass()); // Delete dead bit computations - - // Run instcombine after redundancy elimination to exploit opportunities - // opened up by them. - MPM.add(createInstructionCombiningPass()); - addExtensionsToPM(EP_Peephole, MPM); - MPM.add(createJumpThreadingPass()); // Thread jumps - MPM.add(createCorrelatedValuePropagationPass()); - MPM.add(createDeadStoreEliminationPass()); // Delete dead stores - MPM.add(createLICMPass()); - - addExtensionsToPM(EP_ScalarOptimizerLate, MPM); - - if (RerollLoops) - MPM.add(createLoopRerollPass()); - if (!RunSLPAfterLoopVectorization) { - if (SLPVectorize) - MPM.add(createSLPVectorizerPass()); // Vectorize parallel scalar chains. - - if (BBVectorize) { - MPM.add(createBBVectorizePass()); - MPM.add(createInstructionCombiningPass()); - addExtensionsToPM(EP_Peephole, MPM); - if (OptLevel > 1 && UseGVNAfterVectorization) - MPM.add(createGVNPass(DisableGVNLoadPRE)); // Remove redundancies - else - MPM.add(createEarlyCSEPass()); // Catch trivial redundancies - - // BBVectorize may have significantly shortened a loop body; unroll again. - if (!DisableUnrollLoops) - MPM.add(createLoopUnrollPass()); - } + RunInliner = true; } - if (LoadCombine) - MPM.add(createLoadCombinePass()); + MPM.add(createPostOrderFunctionAttrsLegacyPass()); + if (OptLevel > 2) + MPM.add(createArgumentPromotionPass()); // Scalarize uninlined fn args - MPM.add(createAggressiveDCEPass()); // Delete dead instructions - MPM.add(createCFGSimplificationPass()); // Merge & remove BBs - MPM.add(createInstructionCombiningPass()); // Clean up after everything. - addExtensionsToPM(EP_Peephole, MPM); + addExtensionsToPM(EP_CGSCCOptimizerLate, MPM); + addFunctionSimplificationPasses(MPM); // FIXME: This is a HACK! The inliner pass above implicitly creates a CGSCC // pass manager that we are specifically trying to avoid. To prevent this // we must insert a no-op module pass to reset the pass manager. MPM.add(createBarrierNoopPass()); - if (!DisableUnitAtATime) - MPM.add(createReversePostOrderFunctionAttrsPass()); + if (RunPartialInlining) + MPM.add(createPartialInliningPass()); - if (!DisableUnitAtATime && OptLevel > 1 && !PrepareForLTO) { + if (OptLevel > 1 && !PrepareForLTO && !PrepareForThinLTO) // Remove avail extern fns and globals definitions if we aren't // compiling an object file for later LTO. For LTO we want to preserve // these so they are eligible for inlining at link-time. Note if they @@ -420,28 +541,62 @@ // globals referenced by available external functions dead // and saves running remaining passes on the eliminated functions. MPM.add(createEliminateAvailableExternallyPass()); + + MPM.add(createReversePostOrderFunctionAttrsPass()); + + // The inliner performs some kind of dead code elimination as it goes, + // but there are cases that are not really caught by it. We might + // at some point consider teaching the inliner about them, but it + // is OK for now to run GlobalOpt + GlobalDCE in tandem as their + // benefits generally outweight the cost, making the whole pipeline + // faster. + if (RunInliner) { + MPM.add(createGlobalOptimizerPass()); + MPM.add(createGlobalDCEPass()); + } + + // If we are planning to perform ThinLTO later, let's not bloat the code with + // unrolling/vectorization/... now. We'll first run the inliner + CGSCC passes + // during ThinLTO and perform the rest of the optimizations afterward. + if (PrepareForThinLTO) { + // Rename anon globals to be able to export them in the summary. + MPM.add(createNameAnonGlobalPass()); + return; } - if (EnableNonLTOGlobalsModRef) - // We add a fresh GlobalsModRef run at this point. This is particularly - // useful as the above will have inlined, DCE'ed, and function-attr - // propagated everything. We should at this point have a reasonably minimal - // and richly annotated call graph. By computing aliasing and mod/ref - // information for all local globals here, the late loop passes and notably - // the vectorizer will be able to use them to help recognize vectorizable - // memory operations. - // - // Note that this relies on a bug in the pass manager which preserves - // a module analysis into a function pass pipeline (and throughout it) so - // long as the first function pass doesn't invalidate the module analysis. - // Thus both Float2Int and LoopRotate have to preserve AliasAnalysis for - // this to work. Fortunately, it is trivial to preserve AliasAnalysis - // (doing nothing preserves it as it is required to be conservatively - // correct in the face of IR changes). - MPM.add(createGlobalsAAWrapperPass()); + if (PerformThinLTO) + // Optimize globals now when performing ThinLTO, this enables more + // optimizations later. + MPM.add(createGlobalOptimizerPass()); + + // Scheduling LoopVersioningLICM when inlining is over, because after that + // we may see more accurate aliasing. Reason to run this late is that too + // early versioning may prevent further inlining due to increase of code + // size. By placing it just after inlining other optimizations which runs + // later might get benefit of no-alias assumption in clone loop. + if (UseLoopVersioningLICM) { + MPM.add(createLoopVersioningLICMPass()); // Do LoopVersioningLICM + MPM.add(createLICMPass()); // Hoist loop invariants + } - if (RunFloat2Int) - MPM.add(createFloat2IntPass()); + // We add a fresh GlobalsModRef run at this point. This is particularly + // useful as the above will have inlined, DCE'ed, and function-attr + // propagated everything. We should at this point have a reasonably minimal + // and richly annotated call graph. By computing aliasing and mod/ref + // information for all local globals here, the late loop passes and notably + // the vectorizer will be able to use them to help recognize vectorizable + // memory operations. + // + // Note that this relies on a bug in the pass manager which preserves + // a module analysis into a function pass pipeline (and throughout it) so + // long as the first function pass doesn't invalidate the module analysis. + // Thus both Float2Int and LoopRotate have to preserve AliasAnalysis for + // this to work. Fortunately, it is trivial to preserve AliasAnalysis + // (doing nothing preserves it as it is required to be conservatively + // correct in the face of IR changes). + MPM.add(createGlobalsAAWrapperPass()); + + MPM.add(createFloat2IntPass()); addExtensionsToPM(EP_VectorizerStart, MPM); @@ -451,23 +606,23 @@ MPM.add(createLoopRotatePass(SizeLevel == 2 ? 0 : -1)); // Distribute loops to allow partial vectorization. I.e. isolate dependences - // into separate loop that would otherwise inhibit vectorization. - if (EnableLoopDistribute) - MPM.add(createLoopDistributePass()); + // into separate loop that would otherwise inhibit vectorization. This is + // currently only performed for loops marked with the metadata + // llvm.loop.distribute=true or when -enable-loop-distribute is specified. + MPM.add(createLoopDistributePass()); MPM.add(createLoopVectorizePass(DisableUnrollLoops, LoopVectorize)); // Eliminate loads by forwarding stores from the previous iteration to loads // of the current iteration. - if (EnableLoopLoadElim) - MPM.add(createLoopLoadEliminationPass()); + MPM.add(createLoopLoadEliminationPass()); // FIXME: Because of #pragma vectorize enable, the passes below are always // inserted in the pipeline, even when the vectorizer doesn't run (ex. when // on -O1 and no #pragma is found). Would be good to have these two passes // as function calls, so that we can only pass them when the vectorizer // changed the code. - MPM.add(createInstructionCombiningPass()); + addInstructionCombiningPass(MPM); if (OptLevel > 1 && ExtraVectorizerPasses) { // At higher optimization levels, try to clean up any runtime overlap and // alignment checks inserted by the vectorizer. We want to track correllated @@ -477,96 +632,124 @@ // dead (or speculatable) control flows or more combining opportunities. MPM.add(createEarlyCSEPass()); MPM.add(createCorrelatedValuePropagationPass()); - MPM.add(createInstructionCombiningPass()); + addInstructionCombiningPass(MPM); MPM.add(createLICMPass()); - MPM.add(createLoopUnswitchPass(SizeLevel || OptLevel < 3)); + MPM.add(createLoopUnswitchPass(SizeLevel || OptLevel < 3, DivergentTarget)); MPM.add(createCFGSimplificationPass()); - MPM.add(createInstructionCombiningPass()); + addInstructionCombiningPass(MPM); } - if (RunSLPAfterLoopVectorization) { - if (SLPVectorize) { - MPM.add(createSLPVectorizerPass()); // Vectorize parallel scalar chains. - if (OptLevel > 1 && ExtraVectorizerPasses) { - MPM.add(createEarlyCSEPass()); - } - } - - if (BBVectorize) { - MPM.add(createBBVectorizePass()); - MPM.add(createInstructionCombiningPass()); - addExtensionsToPM(EP_Peephole, MPM); - if (OptLevel > 1 && UseGVNAfterVectorization) - MPM.add(createGVNPass(DisableGVNLoadPRE)); // Remove redundancies - else - MPM.add(createEarlyCSEPass()); // Catch trivial redundancies - - // BBVectorize may have significantly shortened a loop body; unroll again. - if (!DisableUnrollLoops) - MPM.add(createLoopUnrollPass()); + if (RunSLPAfterLoopVectorization && SLPVectorize) { + MPM.add(createSLPVectorizerPass()); // Vectorize parallel scalar chains. + if (OptLevel > 1 && ExtraVectorizerPasses) { + MPM.add(createEarlyCSEPass()); } } addExtensionsToPM(EP_Peephole, MPM); - MPM.add(createCFGSimplificationPass()); - MPM.add(createInstructionCombiningPass()); + MPM.add(createLateCFGSimplificationPass()); // Switches to lookup tables + addInstructionCombiningPass(MPM); if (!DisableUnrollLoops) { - MPM.add(createLoopUnrollPass()); // Unroll small loops + MPM.add(createLoopUnrollPass(OptLevel)); // Unroll small loops // LoopUnroll may generate some redundency to cleanup. - MPM.add(createInstructionCombiningPass()); + addInstructionCombiningPass(MPM); // Runtime unrolling will introduce runtime check in loop prologue. If the // unrolled loop is a inner loop, then the prologue will be inside the // outer loop. LICM pass can help to promote the runtime check out if the // checked value is loop invariant. MPM.add(createLICMPass()); - } + } // After vectorization and unrolling, assume intrinsics may tell us more // about pointer alignments. MPM.add(createAlignmentFromAssumptionsPass()); - if (!DisableUnitAtATime) { - // FIXME: We shouldn't bother with this anymore. - MPM.add(createStripDeadPrototypesPass()); // Get rid of dead prototypes + // FIXME: We shouldn't bother with this anymore. + MPM.add(createStripDeadPrototypesPass()); // Get rid of dead prototypes - // GlobalOpt already deletes dead functions and globals, at -O2 try a - // late pass of GlobalDCE. It is capable of deleting dead cycles. - if (OptLevel > 1) { - MPM.add(createGlobalDCEPass()); // Remove dead fns and globals. - MPM.add(createConstantMergePass()); // Merge dup global constants - } + // GlobalOpt already deletes dead functions and globals, at -O2 try a + // late pass of GlobalDCE. It is capable of deleting dead cycles. + if (OptLevel > 1) { + MPM.add(createGlobalDCEPass()); // Remove dead fns and globals. + MPM.add(createConstantMergePass()); // Merge dup global constants } if (MergeFunctions) MPM.add(createMergeFunctionsPass()); + // LoopSink pass sinks instructions hoisted by LICM, which serves as a + // canonicalization pass that enables other optimizations. As a result, + // LoopSink pass needs to be a very late IR pass to avoid undoing LICM + // result too early. + MPM.add(createLoopSinkPass()); + // Get rid of LCSSA nodes. + MPM.add(createInstructionSimplifierPass()); + + // This hoists/decomposes div/rem ops. It should run after other sink/hoist + // passes to avoid re-sinking, but before SimplifyCFG because it can allow + // flattening of blocks. + MPM.add(createDivRemPairsPass()); + + // LoopSink (and other loop passes since the last simplifyCFG) might have + // resulted in single-entry-single-exit or empty blocks. Clean up the CFG. + MPM.add(createCFGSimplificationPass()); + addExtensionsToPM(EP_OptimizerLast, MPM); } void PassManagerBuilder::addLTOOptimizationPasses(legacy::PassManagerBase &PM) { + // Remove unused virtual tables to improve the quality of code generated by + // whole-program devirtualization and bitset lowering. + PM.add(createGlobalDCEPass()); + // Provide AliasAnalysis services for optimizations. addInitialAliasAnalysisPasses(PM); - if (FunctionIndex) - PM.add(createFunctionImportPass(FunctionIndex)); - // Allow forcing function attributes as a debugging and tuning aid. PM.add(createForceFunctionAttrsLegacyPass()); // Infer attributes about declarations if possible. PM.add(createInferFunctionAttrsLegacyPass()); - // Propagate constants at call sites into the functions they call. This - // opens opportunities for globalopt (and inlining) by substituting function - // pointers passed as arguments to direct uses of functions. - PM.add(createIPSCCPPass()); + if (OptLevel > 1) { + // Indirect call promotion. This should promote all the targets that are + // left by the earlier promotion pass that promotes intra-module targets. + // This two-step promotion is to save the compile time. For LTO, it should + // produce the same result as if we only do promotion here. + PM.add( + createPGOIndirectCallPromotionLegacyPass(true, !PGOSampleUse.empty())); + + // Propagate constants at call sites into the functions they call. This + // opens opportunities for globalopt (and inlining) by substituting function + // pointers passed as arguments to direct uses of functions. + PM.add(createIPSCCPPass()); + + // Attach metadata to indirect call sites indicating the set of functions + // they may target at run-time. This should follow IPSCCP. + PM.add(createCalledValuePropagationPass()); + } + + // Infer attributes about definitions. The readnone attribute in particular is + // required for virtual constant propagation. + PM.add(createPostOrderFunctionAttrsLegacyPass()); + PM.add(createReversePostOrderFunctionAttrsPass()); + + // Split globals using inrange annotations on GEP indices. This can help + // improve the quality of generated code when virtual constant propagation or + // control flow integrity are enabled. + PM.add(createGlobalSplitPass()); + + // Apply whole-program devirtualization and virtual constant propagation. + PM.add(createWholeProgramDevirtPass(ExportSummary, nullptr)); + + // That's all we need at opt level 1. + if (OptLevel == 1) + return; // Now that we internalized some globals, see if we can hack on them! - PM.add(createPostOrderFunctionAttrsPass()); - PM.add(createReversePostOrderFunctionAttrsPass()); PM.add(createGlobalOptimizerPass()); // Promote any localized global vars. PM.add(createPromoteMemoryToRegisterPass()); @@ -582,7 +765,7 @@ // simplification opportunities, and both can propagate functions through // function pointers. When this happens, we often have to resolve varargs // calls, etc, so let instcombine do this. - PM.add(createInstructionCombiningPass()); + addInstructionCombiningPass(PM); addExtensionsToPM(EP_Peephole, PM); // Inline small functions @@ -604,24 +787,21 @@ PM.add(createArgumentPromotionPass()); // The IPO passes may leave cruft around. Clean up after them. - PM.add(createInstructionCombiningPass()); + addInstructionCombiningPass(PM); addExtensionsToPM(EP_Peephole, PM); PM.add(createJumpThreadingPass()); // Break up allocas - if (UseNewSROA) - PM.add(createSROAPass()); - else - PM.add(createScalarReplAggregatesPass()); + PM.add(createSROAPass()); // Run a few AA driven optimizations here and now, to cleanup the code. - PM.add(createPostOrderFunctionAttrsPass()); // Add nocapture. + PM.add(createPostOrderFunctionAttrsLegacyPass()); // Add nocapture. PM.add(createGlobalsAAWrapperPass()); // IP alias analysis. PM.add(createLICMPass()); // Hoist loop invariants. - if (EnableMLSM) - PM.add(createMergedLoadStoreMotionPass()); // Merge ld/st in diamonds. - PM.add(createGVNPass(DisableGVNLoadPRE)); // Remove redundancies. + PM.add(createMergedLoadStoreMotionPass()); // Merge ld/st in diamonds. + PM.add(NewGVN ? createNewGVNPass() + : createGVNPass(DisableGVNLoadPRE)); // Remove redundancies. PM.add(createMemCpyOptPass()); // Remove dead memcpys. // Nuke dead stores. @@ -634,19 +814,19 @@ PM.add(createLoopInterchangePass()); if (!DisableUnrollLoops) - PM.add(createSimpleLoopUnrollPass()); // Unroll small loops + PM.add(createSimpleLoopUnrollPass(OptLevel)); // Unroll small loops PM.add(createLoopVectorizePass(true, LoopVectorize)); // The vectorizer may have significantly shortened a loop body; unroll again. if (!DisableUnrollLoops) - PM.add(createLoopUnrollPass()); + PM.add(createLoopUnrollPass(OptLevel)); // Now that we've optimized loops (in particular loop induction variables), // we may have exposed more scalar opportunities. Run parts of the scalar // optimizer again at this point. - PM.add(createInstructionCombiningPass()); // Initial cleanup + addInstructionCombiningPass(PM); // Initial cleanup PM.add(createCFGSimplificationPass()); // if-convert PM.add(createSCCPPass()); // Propagate exposed constants - PM.add(createInstructionCombiningPass()); // Clean up again + addInstructionCombiningPass(PM); // Clean up again PM.add(createBitTrackingDCEPass()); // More scalar chains could be vectorized due to more alias information @@ -658,11 +838,8 @@ // alignments. PM.add(createAlignmentFromAssumptionsPass()); - if (LoadCombine) - PM.add(createLoadCombinePass()); - // Cleanup and simplify the code after the scalar optimizations. - PM.add(createInstructionCombiningPass()); + addInstructionCombiningPass(PM); addExtensionsToPM(EP_Peephole, PM); PM.add(createJumpThreadingPass()); @@ -685,6 +862,37 @@ PM.add(createMergeFunctionsPass()); } +void PassManagerBuilder::populateThinLTOPassManager( + legacy::PassManagerBase &PM) { + PerformThinLTO = true; + + if (VerifyInput) + PM.add(createVerifierPass()); + + if (ImportSummary) { + // These passes import type identifier resolutions for whole-program + // devirtualization and CFI. They must run early because other passes may + // disturb the specific instruction patterns that these passes look for, + // creating dependencies on resolutions that may not appear in the summary. + // + // For example, GVN may transform the pattern assume(type.test) appearing in + // two basic blocks into assume(phi(type.test, type.test)), which would + // transform a dependency on a WPD resolution into a dependency on a type + // identifier resolution for CFI. + // + // Also, WPD has access to more precise information than ICP and can + // devirtualize more effectively, so it should operate on the IR first. + PM.add(createWholeProgramDevirtPass(nullptr, ImportSummary)); + PM.add(createLowerTypeTestsPass(nullptr, ImportSummary)); + } + + populateModulePassManager(PM); + + if (VerifyOutput) + PM.add(createVerifierPass()); + PerformThinLTO = false; +} + void PassManagerBuilder::populateLTOPassManager(legacy::PassManagerBase &PM) { if (LibraryInfo) PM.add(new TargetLibraryInfoWrapperPass(*LibraryInfo)); @@ -692,17 +900,23 @@ if (VerifyInput) PM.add(createVerifierPass()); - if (OptLevel > 1) + if (OptLevel != 0) addLTOOptimizationPasses(PM); + else { + // The whole-program-devirt pass needs to run at -O0 because only it knows + // about the llvm.type.checked.load intrinsic: it needs to both lower the + // intrinsic itself and handle it in the summary. + PM.add(createWholeProgramDevirtPass(ExportSummary, nullptr)); + } // Create a function that performs CFI checks for cross-DSO calls with targets // in the current module. PM.add(createCrossDSOCFIPass()); - // Lower bit sets to globals. This pass supports Clang's control flow - // integrity mechanisms (-fsanitize=cfi*) and needs to run at link time if CFI - // is enabled. The pass does nothing if CFI is disabled. - PM.add(createLowerBitSetsPass()); + // Lower type metadata and the type.test intrinsic. This pass supports Clang's + // control flow integrity mechanisms (-fsanitize=cfi*) and needs to run at + // link time if CFI is enabled. The pass does nothing if CFI is disabled. + PM.add(createLowerTypeTestsPass(ExportSummary, nullptr)); if (OptLevel != 0) addLateLTOOptimizationPasses(PM); @@ -746,8 +960,7 @@ void LLVMPassManagerBuilderSetDisableUnitAtATime(LLVMPassManagerBuilderRef PMB, LLVMBool Value) { - PassManagerBuilder *Builder = unwrap(PMB); - Builder->DisableUnitAtATime = Value; + // NOTE: The DisableUnitAtATime switch has been removed. } void diff -r 56c5119fbcd2 -r c4cc77a799c9 lib/Transforms/Scalar/TailRecursionElimination.cpp --- a/lib/Transforms/Scalar/TailRecursionElimination.cpp Sun Dec 03 20:09:16 2017 +0900 +++ b/lib/Transforms/Scalar/TailRecursionElimination.cpp Mon Dec 04 21:20:52 2017 +0900 @@ -50,16 +50,17 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Scalar/TailRecursionElimination.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/Statistic.h" -#include "llvm/Analysis/GlobalsModRef.h" #include "llvm/Analysis/CFG.h" #include "llvm/Analysis/CaptureTracking.h" +#include "llvm/Analysis/GlobalsModRef.h" #include "llvm/Analysis/InlineCost.h" #include "llvm/Analysis/InstructionSimplify.h" #include "llvm/Analysis/Loads.h" +#include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/CFG.h" #include "llvm/IR/CallSite.h" @@ -68,6 +69,7 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Function.h" +#include "llvm/IR/InstIterator.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" @@ -75,6 +77,7 @@ #include "llvm/Pass.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Local.h" using namespace llvm; @@ -85,108 +88,14 @@ STATISTIC(NumRetDuped, "Number of return duplicated"); STATISTIC(NumAccumAdded, "Number of accumulators introduced"); -namespace { - struct TailCallElim : public FunctionPass { - const TargetTransformInfo *TTI; - - static char ID; // Pass identification, replacement for typeid - TailCallElim() : FunctionPass(ID) { - initializeTailCallElimPass(*PassRegistry::getPassRegistry()); - } -#ifndef noCbC - TailCallElim(bool f) : FunctionPass(ID) { - initializeTailCallElimPass(*PassRegistry::getPassRegistry()); - onlyForCbC = f; - } -#endif - - void getAnalysisUsage(AnalysisUsage &AU) const override; - - bool runOnFunction(Function &F) override; - - private: - bool runTRE(Function &F); - bool markTails(Function &F, bool &AllCallsAreTailCalls); - - CallInst *FindTRECandidate(Instruction *I, - bool CannotTailCallElimCallsMarkedTail); - bool EliminateRecursiveTailCall(CallInst *CI, ReturnInst *Ret, - BasicBlock *&OldEntry, - bool &TailCallsAreMarkedTail, - SmallVectorImpl &ArgumentPHIs, - bool CannotTailCallElimCallsMarkedTail); - bool FoldReturnAndProcessPred(BasicBlock *BB, - ReturnInst *Ret, BasicBlock *&OldEntry, - bool &TailCallsAreMarkedTail, - SmallVectorImpl &ArgumentPHIs, - bool CannotTailCallElimCallsMarkedTail); - bool ProcessReturningBlock(ReturnInst *RI, BasicBlock *&OldEntry, - bool &TailCallsAreMarkedTail, - SmallVectorImpl &ArgumentPHIs, - bool CannotTailCallElimCallsMarkedTail); - bool CanMoveAboveCall(Instruction *I, CallInst *CI); - Value *CanTransformAccumulatorRecursion(Instruction *I, CallInst *CI); -#ifndef noCbC - bool onlyForCbC; - public: - bool isOnlyForCbC(); - bool markTailToCodeSegments(Function &F); -#endif - }; -} - -char TailCallElim::ID = 0; -INITIALIZE_PASS_BEGIN(TailCallElim, "tailcallelim", - "Tail Call Elimination", false, false) -INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) -INITIALIZE_PASS_END(TailCallElim, "tailcallelim", - "Tail Call Elimination", false, false) - -// Public interface to the TailCallElimination pass -#ifndef noCbC -// Public interface to the TailCallElimination pass -FunctionPass *llvm::createTailCallEliminationPass(bool isOnlyForCbC) { - return new TailCallElim(isOnlyForCbC); -} -#else -FunctionPass *llvm::createTailCallEliminationPass() { - return new TailCallElim(); -} -#endif - -void TailCallElim::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); - AU.addPreserved(); -} - /// \brief Scan the specified function for alloca instructions. /// If it contains any dynamic allocas, returns false. -static bool CanTRE(Function &F) { +static bool canTRE(Function &F) { // Because of PR962, we don't TRE dynamic allocas. - for (auto &BB : F) { - for (auto &I : BB) { - if (AllocaInst *AI = dyn_cast(&I)) { - if (!AI->isStaticAlloca()) - return false; - } - } - } - - return true; -} - -bool TailCallElim::runOnFunction(Function &F) { - if (skipOptnoneFunction(F)) - return false; - - if (F.getFnAttribute("disable-tail-calls").getValueAsString() == "true") - return false; - - bool AllCallsAreTailCalls = false; - bool Modified = markTails(F, AllCallsAreTailCalls); - if (AllCallsAreTailCalls) - Modified |= runTRE(F); - return Modified; + return llvm::all_of(instructions(F), [](Instruction &I) { + auto *AI = dyn_cast(&I); + return !AI || AI->isStaticAlloca(); + }); } namespace { @@ -269,7 +178,30 @@ }; } -bool TailCallElim::markTails(Function &F, bool &AllCallsAreTailCalls) { +#ifndef noCbC +static bool markTailToCodeSegments(Function &F){ + bool Modified = false; + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { + for (auto &I : *BB) { + CallInst *CI = dyn_cast(&I); + Function* Called; + if (CI) + Called = CI->getCalledFunction(); + else + continue; + // We should touch only code segment call. + if (Called && Called->getReturnType()->is__CodeTy()) { + CI->setTailCall(); + Modified = true; + } + } + } + return Modified; +} +#endif + +static bool markTails(Function &F, bool &AllCallsAreTailCalls, + OptimizationRemarkEmitter *ORE) { if (F.callsFunctionThatReturnsTwice()) return false; AllCallsAreTailCalls = true; @@ -328,7 +260,7 @@ if (!CI || CI->isTailCall()) continue; - bool IsNoTail = CI->isNoTailCall(); + bool IsNoTail = CI->isNoTailCall() || CI->hasOperandBundles(); if (!IsNoTail && CI->doesNotAccessMemory()) { // A call to a readnone function whose arguments are all things computed @@ -349,9 +281,11 @@ break; } if (SafeToTail) { - emitOptimizationRemark( - F.getContext(), "tailcallelim", F, CI->getDebugLoc(), - "marked this readnone call a tail call candidate"); + using namespace ore; + ORE->emit([&]() { + return OptimizationRemark(DEBUG_TYPE, "tailcall-readnone", CI) + << "marked as tail call candidate (readnone)"; + }); CI->setTailCall(); Modified = true; continue; @@ -396,9 +330,10 @@ if (Visited[CI->getParent()] != ESCAPED) { // If the escape point was part way through the block, calls after the // escape point wouldn't have been put into DeferredTails. - emitOptimizationRemark(F.getContext(), "tailcallelim", F, - CI->getDebugLoc(), - "marked this call a tail call candidate"); + ORE->emit([&]() { + return OptimizationRemark(DEBUG_TYPE, "tailcall", CI) + << "marked as tail call candidate"; + }); CI->setTailCall(); Modified = true; } else { @@ -409,63 +344,11 @@ return Modified; } -bool TailCallElim::runTRE(Function &F) { - // If this function is a varargs function, we won't be able to PHI the args - // right, so don't even try to convert it... - if (F.getFunctionType()->isVarArg()) return false; - - TTI = &getAnalysis().getTTI(F); - BasicBlock *OldEntry = nullptr; - bool TailCallsAreMarkedTail = false; - SmallVector ArgumentPHIs; - bool MadeChange = false; - - // If false, we cannot perform TRE on tail calls marked with the 'tail' - // attribute, because doing so would cause the stack size to increase (real - // TRE would deallocate variable sized allocas, TRE doesn't). - bool CanTRETailMarkedCall = CanTRE(F); - - // Change any tail recursive calls to loops. - // - // FIXME: The code generator produces really bad code when an 'escaping - // alloca' is changed from being a static alloca to being a dynamic alloca. - // Until this is resolved, disable this transformation if that would ever - // happen. This bug is PR962. - for (Function::iterator BBI = F.begin(), E = F.end(); BBI != E; /*in loop*/) { - BasicBlock *BB = &*BBI++; // FoldReturnAndProcessPred may delete BB. - if (ReturnInst *Ret = dyn_cast(BB->getTerminator())) { - bool Change = ProcessReturningBlock(Ret, OldEntry, TailCallsAreMarkedTail, - ArgumentPHIs, !CanTRETailMarkedCall); - if (!Change && BB->getFirstNonPHIOrDbg() == Ret) - Change = FoldReturnAndProcessPred(BB, Ret, OldEntry, - TailCallsAreMarkedTail, ArgumentPHIs, - !CanTRETailMarkedCall); - MadeChange |= Change; - } - } - - // If we eliminated any tail recursions, it's possible that we inserted some - // silly PHI nodes which just merge an initial value (the incoming operand) - // with themselves. Check to see if we did and clean up our mess if so. This - // occurs when a function passes an argument straight through to its tail - // call. - for (PHINode *PN : ArgumentPHIs) { - // If the PHI Node is a dynamic constant, replace it with the value it is. - if (Value *PNV = SimplifyInstruction(PN, F.getParent()->getDataLayout())) { - PN->replaceAllUsesWith(PNV); - PN->eraseFromParent(); - } - } - - return MadeChange; -} - - /// Return true if it is safe to move the specified /// instruction from after the call to before the call, assuming that all /// instructions between the call and this instruction are movable. /// -bool TailCallElim::CanMoveAboveCall(Instruction *I, CallInst *CI) { +static bool canMoveAboveCall(Instruction *I, CallInst *CI, AliasAnalysis *AA) { // FIXME: We can move load/store/call/free instructions above the call if the // call does not mod/ref the memory location being processed. if (I->mayHaveSideEffects()) // This also handles volatile loads. @@ -476,11 +359,12 @@ if (CI->mayHaveSideEffects()) { // Non-volatile loads may be moved above a call with side effects if it // does not write to memory and the load provably won't trap. - // FIXME: Writes to memory only matter if they may alias the pointer + // Writes to memory only matter if they may alias the pointer // being loaded from. - if (CI->mayWriteToMemory() || + const DataLayout &DL = L->getModule()->getDataLayout(); + if ((AA->getModRefInfo(CI, MemoryLocation::get(L)) & MRI_Mod) || !isSafeToLoadUnconditionally(L->getPointerOperand(), - L->getAlignment(), L)) + L->getAlignment(), DL, L)) return false; } } @@ -490,7 +374,7 @@ // return value of the call, it must only use things that are defined before // the call, or movable instructions between the call and the instruction // itself. - return std::find(I->op_begin(), I->op_end(), CI) == I->op_end(); + return !is_contained(I->operands(), CI); } /// Return true if the specified value is the same when the return would exit @@ -536,8 +420,8 @@ Function *F = CI->getParent()->getParent(); Value *ReturnedValue = nullptr; - for (Function::iterator BBI = F->begin(), E = F->end(); BBI != E; ++BBI) { - ReturnInst *RI = dyn_cast(BBI->getTerminator()); + for (BasicBlock &BBI : *F) { + ReturnInst *RI = dyn_cast(BBI.getTerminator()); if (RI == nullptr || RI == IgnoreRI) continue; // We can only perform this transformation if the value returned is @@ -558,8 +442,7 @@ /// If the specified instruction can be transformed using accumulator recursion /// elimination, return the constant which is the start of the accumulator /// value. Otherwise return null. -Value *TailCallElim::CanTransformAccumulatorRecursion(Instruction *I, - CallInst *CI) { +static Value *canTransformAccumulatorRecursion(Instruction *I, CallInst *CI) { if (!I->isAssociative() || !I->isCommutative()) return nullptr; assert(I->getNumOperands() == 2 && "Associative/commutative operations should have 2 args!"); @@ -579,15 +462,15 @@ return getCommonReturnValue(cast(I->user_back()), CI); } -static Instruction *FirstNonDbg(BasicBlock::iterator I) { +static Instruction *firstNonDbg(BasicBlock::iterator I) { while (isa(I)) ++I; return &*I; } -CallInst* -TailCallElim::FindTRECandidate(Instruction *TI, - bool CannotTailCallElimCallsMarkedTail) { +static CallInst *findTRECandidate(Instruction *TI, + bool CannotTailCallElimCallsMarkedTail, + const TargetTransformInfo *TTI) { BasicBlock *BB = TI->getParent(); Function *F = BB->getParent(); @@ -618,8 +501,8 @@ // and disable this xform in this case, because the code generator will // lower the call to fabs into inline code. if (BB == &F->getEntryBlock() && - FirstNonDbg(BB->front().getIterator()) == CI && - FirstNonDbg(std::next(BB->begin())) == TI && CI->getCalledFunction() && + firstNonDbg(BB->front().getIterator()) == CI && + firstNonDbg(std::next(BB->begin())) == TI && CI->getCalledFunction() && !TTI->isLoweredToCall(CI->getCalledFunction())) { // A single-block function with just a call and a return. Check that // the arguments match. @@ -636,11 +519,12 @@ return CI; } -bool TailCallElim::EliminateRecursiveTailCall(CallInst *CI, ReturnInst *Ret, +static bool eliminateRecursiveTailCall(CallInst *CI, ReturnInst *Ret, BasicBlock *&OldEntry, bool &TailCallsAreMarkedTail, SmallVectorImpl &ArgumentPHIs, - bool CannotTailCallElimCallsMarkedTail) { + AliasAnalysis *AA, + OptimizationRemarkEmitter *ORE) { // If we are introducing accumulator recursion to eliminate operations after // the call instruction that are both associative and commutative, the initial // value for the accumulator is placed in this variable. If this value is set @@ -660,14 +544,15 @@ // Check that this is the case now. BasicBlock::iterator BBI(CI); for (++BBI; &*BBI != Ret; ++BBI) { - if (CanMoveAboveCall(&*BBI, CI)) continue; + if (canMoveAboveCall(&*BBI, CI, AA)) + continue; // If we can't move the instruction above the call, it might be because it // is an associative and commutative operation that could be transformed // using accumulator recursion elimination. Check to see if this is the // case, and if so, remember the initial accumulator value for later. if ((AccumulatorRecursionEliminationInitVal = - CanTransformAccumulatorRecursion(&*BBI, CI))) { + canTransformAccumulatorRecursion(&*BBI, CI))) { // Yes, this is accumulator recursion. Remember which instruction // accumulates. AccumulatorRecursionInstr = &*BBI; @@ -699,8 +584,11 @@ BasicBlock *BB = Ret->getParent(); Function *F = BB->getParent(); - emitOptimizationRemark(F->getContext(), "tailcallelim", *F, CI->getDebugLoc(), - "transforming tail recursion to loop"); + using namespace ore; + ORE->emit([&]() { + return OptimizationRemark(DEBUG_TYPE, "tailcall-recursion", CI) + << "transforming tail recursion into loop"; + }); // OK! We can transform this tail call. If this is the first one found, // create the new entry block, allowing us to branch back to the old entry. @@ -797,8 +685,8 @@ // Finally, rewrite any return instructions in the program to return the PHI // node instead of the "initval" that they do currently. This loop will // actually rewrite the return value we are destroying, but that's ok. - for (Function::iterator BBI = F->begin(), E = F->end(); BBI != E; ++BBI) - if (ReturnInst *RI = dyn_cast(BBI->getTerminator())) + for (BasicBlock &BBI : *F) + if (ReturnInst *RI = dyn_cast(BBI.getTerminator())) RI->setOperand(0, AccPN); ++NumAccumAdded; } @@ -814,16 +702,20 @@ return true; } -bool TailCallElim::FoldReturnAndProcessPred(BasicBlock *BB, - ReturnInst *Ret, BasicBlock *&OldEntry, - bool &TailCallsAreMarkedTail, - SmallVectorImpl &ArgumentPHIs, - bool CannotTailCallElimCallsMarkedTail) { +static bool foldReturnAndProcessPred( + BasicBlock *BB, ReturnInst *Ret, BasicBlock *&OldEntry, + bool &TailCallsAreMarkedTail, SmallVectorImpl &ArgumentPHIs, + bool CannotTailCallElimCallsMarkedTail, const TargetTransformInfo *TTI, + AliasAnalysis *AA, OptimizationRemarkEmitter *ORE) { bool Change = false; + // Make sure this block is a trivial return block. + assert(BB->getFirstNonPHIOrDbg() == Ret && + "Trying to fold non-trivial return block"); + // If the return block contains nothing but the return and PHI's, // there might be an opportunity to duplicate the return in its - // predecessors and perform TRC there. Look for predecessors that end + // predecessors and perform TRE there. Look for predecessors that end // in unconditional branch and recursive call(s). SmallVector UncondBranchPreds; for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) { @@ -837,7 +729,7 @@ while (!UncondBranchPreds.empty()) { BranchInst *BI = UncondBranchPreds.pop_back_val(); BasicBlock *Pred = BI->getParent(); - if (CallInst *CI = FindTRECandidate(BI, CannotTailCallElimCallsMarkedTail)){ + if (CallInst *CI = findTRECandidate(BI, CannotTailCallElimCallsMarkedTail, TTI)){ DEBUG(dbgs() << "FOLDING: " << *BB << "INTO UNCOND BRANCH PRED: " << *Pred); ReturnInst *RI = FoldReturnIntoUncondBranch(Ret, BB, Pred); @@ -845,13 +737,12 @@ // Cleanup: if all predecessors of BB have been eliminated by // FoldReturnIntoUncondBranch, delete it. It is important to empty it, // because the ret instruction in there is still using a value which - // EliminateRecursiveTailCall will attempt to remove. + // eliminateRecursiveTailCall will attempt to remove. if (!BB->hasAddressTaken() && pred_begin(BB) == pred_end(BB)) BB->eraseFromParent(); - EliminateRecursiveTailCall(CI, RI, OldEntry, TailCallsAreMarkedTail, - ArgumentPHIs, - CannotTailCallElimCallsMarkedTail); + eliminateRecursiveTailCall(CI, RI, OldEntry, TailCallsAreMarkedTail, + ArgumentPHIs, AA, ORE); ++NumRetDuped; Change = true; } @@ -860,42 +751,159 @@ return Change; } -bool -TailCallElim::ProcessReturningBlock(ReturnInst *Ret, BasicBlock *&OldEntry, - bool &TailCallsAreMarkedTail, - SmallVectorImpl &ArgumentPHIs, - bool CannotTailCallElimCallsMarkedTail) { - CallInst *CI = FindTRECandidate(Ret, CannotTailCallElimCallsMarkedTail); +static bool processReturningBlock(ReturnInst *Ret, BasicBlock *&OldEntry, + bool &TailCallsAreMarkedTail, + SmallVectorImpl &ArgumentPHIs, + bool CannotTailCallElimCallsMarkedTail, + const TargetTransformInfo *TTI, + AliasAnalysis *AA, + OptimizationRemarkEmitter *ORE) { + CallInst *CI = findTRECandidate(Ret, CannotTailCallElimCallsMarkedTail, TTI); if (!CI) return false; - return EliminateRecursiveTailCall(CI, Ret, OldEntry, TailCallsAreMarkedTail, - ArgumentPHIs, - CannotTailCallElimCallsMarkedTail); + return eliminateRecursiveTailCall(CI, Ret, OldEntry, TailCallsAreMarkedTail, + ArgumentPHIs, AA, ORE); +} + +static bool eliminateTailRecursion(Function &F, const TargetTransformInfo *TTI, + AliasAnalysis *AA, + OptimizationRemarkEmitter *ORE) { + if (F.getFnAttribute("disable-tail-calls").getValueAsString() == "true") + return false; + + bool MadeChange = false; + bool AllCallsAreTailCalls = false; + MadeChange |= markTails(F, AllCallsAreTailCalls, ORE); + if (!AllCallsAreTailCalls) + return MadeChange; + + // If this function is a varargs function, we won't be able to PHI the args + // right, so don't even try to convert it... + if (F.getFunctionType()->isVarArg()) + return false; + + BasicBlock *OldEntry = nullptr; + bool TailCallsAreMarkedTail = false; + SmallVector ArgumentPHIs; + + // If false, we cannot perform TRE on tail calls marked with the 'tail' + // attribute, because doing so would cause the stack size to increase (real + // TRE would deallocate variable sized allocas, TRE doesn't). + bool CanTRETailMarkedCall = canTRE(F); + + // Change any tail recursive calls to loops. + // + // FIXME: The code generator produces really bad code when an 'escaping + // alloca' is changed from being a static alloca to being a dynamic alloca. + // Until this is resolved, disable this transformation if that would ever + // happen. This bug is PR962. + for (Function::iterator BBI = F.begin(), E = F.end(); BBI != E; /*in loop*/) { + BasicBlock *BB = &*BBI++; // foldReturnAndProcessPred may delete BB. + if (ReturnInst *Ret = dyn_cast(BB->getTerminator())) { + bool Change = processReturningBlock(Ret, OldEntry, TailCallsAreMarkedTail, + ArgumentPHIs, !CanTRETailMarkedCall, + TTI, AA, ORE); + if (!Change && BB->getFirstNonPHIOrDbg() == Ret) + Change = foldReturnAndProcessPred(BB, Ret, OldEntry, + TailCallsAreMarkedTail, ArgumentPHIs, + !CanTRETailMarkedCall, TTI, AA, ORE); + MadeChange |= Change; + } + } + + // If we eliminated any tail recursions, it's possible that we inserted some + // silly PHI nodes which just merge an initial value (the incoming operand) + // with themselves. Check to see if we did and clean up our mess if so. This + // occurs when a function passes an argument straight through to its tail + // call. + for (PHINode *PN : ArgumentPHIs) { + // If the PHI Node is a dynamic constant, replace it with the value it is. + if (Value *PNV = SimplifyInstruction(PN, F.getParent()->getDataLayout())) { + PN->replaceAllUsesWith(PNV); + PN->eraseFromParent(); + } + } + + return MadeChange; +} + +namespace { +struct TailCallElim : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + TailCallElim() : FunctionPass(ID) { + initializeTailCallElimPass(*PassRegistry::getPassRegistry()); + } +#ifndef noCbC + TailCallElim(bool f) : FunctionPass(ID) { + initializeTailCallElimPass(*PassRegistry::getPassRegistry()); + onlyForCbC = f; + } +#endif + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + } + + bool runOnFunction(Function &F) override { + if (skipFunction(F)) + return false; + + return eliminateTailRecursion( + F, &getAnalysis().getTTI(F), + &getAnalysis().getAAResults(), + &getAnalysis().getORE()); + } +#ifndef noCbC + private: + bool onlyForCbC; + public: + bool isOnlyForCbC(); +#endif +}; +} + +char TailCallElim::ID = 0; +INITIALIZE_PASS_BEGIN(TailCallElim, "tailcallelim", "Tail Call Elimination", + false, false) +INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) +INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass) +INITIALIZE_PASS_END(TailCallElim, "tailcallelim", "Tail Call Elimination", + false, false) + +// Public interface to the TailCallElimination pass +#ifndef noCbC +// Public interface to the TailCallElimination pass +FunctionPass *llvm::createTailCallEliminationPass(bool isOnlyForCbC) { + return new TailCallElim(isOnlyForCbC); +} +#else +FunctionPass *llvm::createTailCallEliminationPass() { + return new TailCallElim(); +} +#endif + +PreservedAnalyses TailCallElimPass::run(Function &F, + FunctionAnalysisManager &AM) { + + TargetTransformInfo &TTI = AM.getResult(F); + AliasAnalysis &AA = AM.getResult(F); + auto &ORE = AM.getResult(F); + + bool Changed = eliminateTailRecursion(F, &TTI, &AA, &ORE); + + if (!Changed) + return PreservedAnalyses::all(); + PreservedAnalyses PA; + PA.preserve(); + return PA; } #ifndef noCbC bool TailCallElim::isOnlyForCbC(){ return onlyForCbC; } - -bool TailCallElim::markTailToCodeSegments(Function &F){ - bool Modified = false; - for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { - for (auto &I : *BB) { - CallInst *CI = dyn_cast(&I); - Function* Called; - if (CI) - Called = CI->getCalledFunction(); - else - continue; - // We should touch only code segment call. - if (Called && Called->getReturnType()->is__CodeTy()) { - CI->setTailCall(); - Modified = true; - } - } - } - return Modified; -} #endif diff -r 56c5119fbcd2 -r c4cc77a799c9 lib/Transforms/Utils/FunctionComparator.cpp --- a/lib/Transforms/Utils/FunctionComparator.cpp Sun Dec 03 20:09:16 2017 +0900 +++ b/lib/Transforms/Utils/FunctionComparator.cpp Mon Dec 04 21:20:52 2017 +0900 @@ -426,6 +426,9 @@ case Type::LabelTyID: case Type::MetadataTyID: case Type::TokenTyID: +#ifndef noCbC + case Type::__CodeTyID: +#endif return 0; case Type::PointerTyID: diff -r 56c5119fbcd2 -r c4cc77a799c9 tools/clang/include/clang/Basic/LangOptions.def --- a/tools/clang/include/clang/Basic/LangOptions.def Sun Dec 03 20:09:16 2017 +0900 +++ b/tools/clang/include/clang/Basic/LangOptions.def Mon Dec 04 21:20:52 2017 +0900 @@ -24,11 +24,15 @@ // // VALUE_LANGOPT: for options that describe a value rather than a flag. // -// BENIGN_ENUM_LANGOPT, COMPATIBLE_ENUM_LANGOPT: combinations of the above. +// BENIGN_ENUM_LANGOPT, COMPATIBLE_ENUM_LANGOPT, +// BENIGN_VALUE_LANGOPT, COMPATIBLE_VALUE_LANGOPT: combinations of the above. // // FIXME: Clients should be able to more easily select whether they want // different levels of compatibility versus how to handle different kinds // of option. +// +// The Description field should be a noun phrase, for instance "frobbing all +// widgets" or "C's implicit blintz feature". //===----------------------------------------------------------------------===// #ifndef LANGOPT @@ -65,6 +69,16 @@ LANGOPT(Name, Bits, Default, Description) #endif +#ifndef COMPATIBLE_VALUE_LANGOPT +# define COMPATIBLE_VALUE_LANGOPT(Name, Bits, Default, Description) \ + VALUE_LANGOPT(Name, Bits, Default, Description) +#endif + +#ifndef BENIGN_VALUE_LANGOPT +# define BENIGN_VALUE_LANGOPT(Name, Bits, Default, Description) \ + COMPATIBLE_VALUE_LANGOPT(Name, Bits, Default, Description) +#endif + // FIXME: A lot of the BENIGN_ options should be COMPATIBLE_ instead. LANGOPT(C99 , 1, 0, "C99") LANGOPT(C11 , 1, 0, "C11") @@ -75,7 +89,8 @@ LANGOPT(CPlusPlus , 1, 0, "C++") LANGOPT(CPlusPlus11 , 1, 0, "C++11") LANGOPT(CPlusPlus14 , 1, 0, "C++14") -LANGOPT(CPlusPlus1z , 1, 0, "C++1z") +LANGOPT(CPlusPlus1z , 1, 0, "C++17") +LANGOPT(CPlusPlus2a , 1, 0, "C++2a") LANGOPT(ObjC1 , 1, 0, "Objective-C 1") LANGOPT(ObjC2 , 1, 0, "Objective-C 2") BENIGN_LANGOPT(ObjCDefaultSynthProperties , 1, 0, @@ -93,7 +108,7 @@ LANGOPT(DeclSpecKeyword , 1, 0, "__declspec keyword") BENIGN_LANGOPT(DollarIdents , 1, 1, "'$' in identifiers") BENIGN_LANGOPT(AsmPreprocessor, 1, 0, "preprocessor in asm mode") -BENIGN_LANGOPT(GNUMode , 1, 1, "GNU extensions") +LANGOPT(GNUMode , 1, 1, "GNU extensions") LANGOPT(GNUKeywords , 1, 1, "GNU keywords") BENIGN_LANGOPT(ImplicitInt, 1, !C99 && !CPlusPlus, "C89 implicit 'int'") LANGOPT(Digraphs , 1, 0, "digraphs") @@ -110,6 +125,7 @@ LANGOPT(ObjCExceptions , 1, 0, "Objective-C exceptions") LANGOPT(CXXExceptions , 1, 0, "C++ exceptions") LANGOPT(SjLjExceptions , 1, 0, "setjmp-longjump exception handling") +LANGOPT(ExternCNoUnwind , 1, 0, "Assume extern C functions don't unwind") LANGOPT(TraditionalCPP , 1, 0, "traditional CPP emulation") LANGOPT(RTTI , 1, 1, "run-time type information") LANGOPT(RTTIData , 1, 1, "emit run-time type information data") @@ -118,63 +134,80 @@ LANGOPT(NoBuiltin , 1, 0, "disable builtin functions") LANGOPT(NoMathBuiltin , 1, 0, "disable math builtin functions") LANGOPT(GNUAsm , 1, 1, "GNU-style inline assembly") -LANGOPT(Coroutines , 1, 0, "C++ coroutines") +LANGOPT(CoroutinesTS , 1, 0, "C++ coroutines TS") +LANGOPT(RelaxedTemplateTemplateArgs, 1, 0, "C++17 relaxed matching of template template arguments") + +LANGOPT(DoubleSquareBracketAttributes, 1, 0, "'[[]]' attributes extension for all language standard modes") BENIGN_LANGOPT(ThreadsafeStatics , 1, 1, "thread-safe static initializers") LANGOPT(POSIXThreads , 1, 0, "POSIX thread support") LANGOPT(Blocks , 1, 0, "blocks extension to C") -BENIGN_LANGOPT(EmitAllDecls , 1, 0, "support for emitting all declarations") -LANGOPT(MathErrno , 1, 1, "errno support for math functions") -BENIGN_LANGOPT(HeinousExtensions , 1, 0, "Extensions that we really don't like and may be ripped out at any time") +BENIGN_LANGOPT(EmitAllDecls , 1, 0, "emitting all declarations") +LANGOPT(MathErrno , 1, 1, "errno in math functions") +BENIGN_LANGOPT(HeinousExtensions , 1, 0, "extensions that we really don't like and may be ripped out at any time") LANGOPT(Modules , 1, 0, "modules extension to C") +COMPATIBLE_LANGOPT(ModulesTS , 1, 0, "C++ Modules TS") +BENIGN_ENUM_LANGOPT(CompilingModule, CompilingModuleKind, 2, CMK_None, + "compiling a module interface") +BENIGN_LANGOPT(CompilingPCH, 1, 0, "building a pch") COMPATIBLE_LANGOPT(ModulesDeclUse , 1, 0, "require declaration of module uses") -LANGOPT(ModulesSearchAll , 1, 1, "search even non-imported modules to find unresolved references") -COMPATIBLE_LANGOPT(ModulesStrictDeclUse, 1, 0, "require declaration of module uses and all headers to be in modules") -BENIGN_LANGOPT(ModulesErrorRecovery, 1, 1, "automatically import modules as needed when performing error recovery") -BENIGN_LANGOPT(ImplicitModules, 1, 1, "build modules that are not specified via -fmodule-file") +BENIGN_LANGOPT(ModulesSearchAll , 1, 1, "searching even non-imported modules to find unresolved references") +COMPATIBLE_LANGOPT(ModulesStrictDeclUse, 1, 0, "requiring declaration of module uses and all headers to be in modules") +BENIGN_LANGOPT(ModulesErrorRecovery, 1, 1, "automatically importing modules as needed when performing error recovery") +BENIGN_LANGOPT(ImplicitModules, 1, 1, "building modules that are not specified via -fmodule-file") COMPATIBLE_LANGOPT(ModulesLocalVisibility, 1, 0, "local submodule visibility") COMPATIBLE_LANGOPT(Optimize , 1, 0, "__OPTIMIZE__ predefined macro") COMPATIBLE_LANGOPT(OptimizeSize , 1, 0, "__OPTIMIZE_SIZE__ predefined macro") -LANGOPT(Static , 1, 0, "__STATIC__ predefined macro (as opposed to __DYNAMIC__)") +COMPATIBLE_LANGOPT(Static , 1, 0, "__STATIC__ predefined macro (as opposed to __DYNAMIC__)") VALUE_LANGOPT(PackStruct , 32, 0, "default struct packing maximum alignment") VALUE_LANGOPT(MaxTypeAlign , 32, 0, "default maximum alignment for types") -VALUE_LANGOPT(PICLevel , 2, 0, "__PIC__ level") -VALUE_LANGOPT(PIELevel , 2, 0, "__PIE__ level") -LANGOPT(GNUInline , 1, 0, "GNU inline semantics") +VALUE_LANGOPT(AlignDouble , 1, 0, "Controls if doubles should be aligned to 8 bytes (x86 only)") +COMPATIBLE_VALUE_LANGOPT(PICLevel , 2, 0, "__PIC__ level") +COMPATIBLE_VALUE_LANGOPT(PIE , 1, 0, "is pie") +COMPATIBLE_LANGOPT(GNUInline , 1, 0, "GNU inline semantics") COMPATIBLE_LANGOPT(NoInlineDefine , 1, 0, "__NO_INLINE__ predefined macro") COMPATIBLE_LANGOPT(Deprecated , 1, 0, "__DEPRECATED predefined macro") -LANGOPT(FastMath , 1, 0, "__FAST_MATH__ predefined macro") -LANGOPT(FiniteMathOnly , 1, 0, "__FINITE_MATH_ONLY__ predefined macro") -LANGOPT(UnsafeFPMath , 1, 0, "Unsafe Floating Point Math") +COMPATIBLE_LANGOPT(FastMath , 1, 0, "fast FP math optimizations, and __FAST_MATH__ predefined macro") +COMPATIBLE_LANGOPT(FiniteMathOnly , 1, 0, "__FINITE_MATH_ONLY__ predefined macro") +COMPATIBLE_LANGOPT(UnsafeFPMath , 1, 0, "Unsafe Floating Point Math") BENIGN_LANGOPT(ObjCGCBitmapPrint , 1, 0, "printing of GC's bitmap layout for __weak/__strong ivars") BENIGN_LANGOPT(AccessControl , 1, 1, "C++ access control") LANGOPT(CharIsSigned , 1, 1, "signed char") -LANGOPT(ShortWChar , 1, 0, "unsigned short wchar_t") +LANGOPT(WCharSize , 4, 0, "width of wchar_t") +LANGOPT(WCharIsSigned , 1, 0, "signed or unsigned wchar_t") ENUM_LANGOPT(MSPointerToMemberRepresentationMethod, PragmaMSPointersToMembersKind, 2, PPTMK_BestCase, "member-pointer representation method") +ENUM_LANGOPT(DefaultCallingConv, DefaultCallingConvention, 3, DCC_None, "default calling convention") LANGOPT(ShortEnums , 1, 0, "short enum types") LANGOPT(OpenCL , 1, 0, "OpenCL") LANGOPT(OpenCLVersion , 32, 0, "OpenCL version") LANGOPT(NativeHalfType , 1, 0, "Native half type support") +LANGOPT(NativeHalfArgsAndReturns, 1, 0, "Native half args and returns") LANGOPT(HalfArgsAndReturns, 1, 0, "half args and returns") LANGOPT(CUDA , 1, 0, "CUDA") -LANGOPT(OpenMP , 1, 0, "OpenMP support") +LANGOPT(OpenMP , 32, 0, "OpenMP support and version of OpenMP (31, 40 or 45)") LANGOPT(OpenMPUseTLS , 1, 0, "Use TLS for threadprivates or runtime calls") LANGOPT(OpenMPIsDevice , 1, 0, "Generate code only for OpenMP target device") +LANGOPT(RenderScript , 1, 0, "RenderScript") -LANGOPT(CUDAIsDevice , 1, 0, "Compiling for CUDA device") -LANGOPT(CUDAAllowHostCallsFromHostDevice, 1, 0, "Allow host device functions to call host functions") -LANGOPT(CUDADisableTargetCallChecks, 1, 0, "Disable checks for call targets (host, device, etc.)") -LANGOPT(CUDATargetOverloads, 1, 0, "Enable function overloads based on CUDA target attributes") +LANGOPT(CUDAIsDevice , 1, 0, "compiling for CUDA device") +LANGOPT(CUDAAllowVariadicFunctions, 1, 0, "allowing variadic functions in CUDA device code") +LANGOPT(CUDAHostDeviceConstexpr, 1, 1, "treating unattributed constexpr functions as __host__ __device__") +LANGOPT(CUDADeviceFlushDenormalsToZero, 1, 0, "flushing denormals to zero") +LANGOPT(CUDADeviceApproxTranscendentals, 1, 0, "using approximate transcendental functions") -LANGOPT(AssumeSaneOperatorNew , 1, 1, "implicit __attribute__((malloc)) for C++'s new operators") -LANGOPT(SizedDeallocation , 1, 0, "enable sized deallocation functions") +LANGOPT(SizedDeallocation , 1, 0, "sized deallocation") +LANGOPT(AlignedAllocation , 1, 0, "aligned allocation") +LANGOPT(AlignedAllocationUnavailable, 1, 0, "aligned allocation functions are unavailable") +LANGOPT(NewAlignOverride , 32, 0, "maximum alignment guaranteed by '::operator new(size_t)'") LANGOPT(ConceptsTS , 1, 0, "enable C++ Extensions for Concepts") +BENIGN_LANGOPT(ModulesCodegen , 1, 0, "Modules code generation") +BENIGN_LANGOPT(ModulesDebugInfo , 1, 0, "Modules debug info") BENIGN_LANGOPT(ElideConstructors , 1, 1, "C++ copy constructor elision") BENIGN_LANGOPT(DumpRecordLayouts , 1, 0, "dumping the layout of IRgen'd records") BENIGN_LANGOPT(DumpRecordLayoutsSimple , 1, 0, "dumping the layout of IRgen'd records in a simple form") @@ -189,7 +222,8 @@ BENIGN_LANGOPT(SpellChecking , 1, 1, "spell-checking") LANGOPT(SinglePrecisionConstants , 1, 0, "treating double-precision floating point constants as single precision constants") LANGOPT(FastRelaxedMath , 1, 0, "OpenCL fast relaxed math") -LANGOPT(DefaultFPContract , 1, 0, "FP_CONTRACT") +/// \brief FP_CONTRACT mode (on/off/fast). +ENUM_LANGOPT(DefaultFPContractMode, FPContractModeKind, 2, FPC_Off, "FP contraction type") LANGOPT(NoBitFieldTypeAlign , 1, 0, "bit-field type alignment") LANGOPT(HexagonQdsp6Compat , 1, 0, "hexagon-qdsp6 backward compatibility") LANGOPT(ObjCAutoRefCount , 1, 0, "Objective-C automated reference counting") @@ -198,8 +232,7 @@ LANGOPT(ObjCSubscriptingLegacyRuntime , 1, 0, "Subscripting support in legacy ObjectiveC runtime") LANGOPT(FakeAddressSpaceMap , 1, 0, "OpenCL fake address space map") ENUM_LANGOPT(AddressSpaceMapMangling , AddrSpaceMapMangling, 2, ASMM_Target, "OpenCL address space map mangling mode") - -LANGOPT(MRTD , 1, 0, "-mrtd calling convention") +LANGOPT(IncludeDefaultHeader, 1, 0, "Include default header file for OpenCL") BENIGN_LANGOPT(DelayedTemplateParsing , 1, 0, "delayed template parsing") LANGOPT(BlocksRuntimeOptional , 1, 0, "optional blocks runtime") @@ -215,7 +248,7 @@ BENIGN_LANGOPT(ArrowDepth, 32, 256, "maximum number of operator->s to follow") -BENIGN_LANGOPT(InstantiationDepth, 32, 256, +BENIGN_LANGOPT(InstantiationDepth, 32, 1024, "maximum template instantiation depth") BENIGN_LANGOPT(ConstexprCallDepth, 32, 512, "maximum constexpr call depth") @@ -236,6 +269,10 @@ "field padding (0: none, 1:least " "aggressive, 2: more aggressive)") +LANGOPT(XRayInstrument, 1, 0, "controls whether to do XRay instrumentation") + +BENIGN_LANGOPT(AllowEditorPlaceholders, 1, 0, + "allow editor placeholders in source") #ifndef noCbC LANGOPT(HasCodeSegment , 1, 0, "CbC") @@ -248,4 +285,6 @@ #undef COMPATIBLE_ENUM_LANGOPT #undef BENIGN_ENUM_LANGOPT #undef VALUE_LANGOPT +#undef COMPATIBLE_VALUE_LANGOPT +#undef BENIGN_VALUE_LANGOPT diff -r 56c5119fbcd2 -r c4cc77a799c9 tools/clang/include/clang/Basic/Specifiers.h --- a/tools/clang/include/clang/Basic/Specifiers.h Sun Dec 03 20:09:16 2017 +0900 +++ b/tools/clang/include/clang/Basic/Specifiers.h Mon Dec 04 21:20:52 2017 +0900 @@ -52,8 +52,10 @@ TST_int, TST_int128, TST_half, // OpenCL half, ARM NEON __fp16 + TST_Float16, // C11 extension ISO/IEC TS 18661-3 TST_float, TST_double, + TST_float128, TST_bool, // _Bool TST_decimal32, // _Decimal32 TST_decimal64, // _Decimal64 @@ -76,17 +78,21 @@ #ifndef noCbC TST___code, #endif - TST_error // erroneous type + +#define GENERIC_IMAGE_TYPE(ImgType, Id) TST_##ImgType##_t, // OpenCL image types +#include "clang/Basic/OpenCLImageTypes.def" + TST_error // erroneous type }; - + /// \brief Structure that packs information about the type specifiers that /// were written in a particular type specifier sequence. struct WrittenBuiltinSpecs { - /*DeclSpec::TST*/ unsigned Type : 5; + static_assert(TST_error < 1 << 6, "Type bitfield not wide enough for TST"); + /*DeclSpec::TST*/ unsigned Type : 6; /*DeclSpec::TSS*/ unsigned Sign : 2; /*DeclSpec::TSW*/ unsigned Width : 2; - bool ModeAttr : 1; - }; + unsigned ModeAttr : 1; + }; /// \brief A C++ access specifier (public, private, protected), plus the /// special value "none" which means different things in different contexts. @@ -235,13 +241,17 @@ CC_X86ThisCall, // __attribute__((thiscall)) CC_X86VectorCall, // __attribute__((vectorcall)) CC_X86Pascal, // __attribute__((pascal)) - CC_X86_64Win64, // __attribute__((ms_abi)) + CC_Win64, // __attribute__((ms_abi)) CC_X86_64SysV, // __attribute__((sysv_abi)) + CC_X86RegCall, // __attribute__((regcall)) CC_AAPCS, // __attribute__((pcs("aapcs"))) CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp"))) CC_IntelOclBicc, // __attribute__((intel_ocl_bicc)) CC_SpirFunction, // default for OpenCL functions on SPIR target - CC_SpirKernel // inferred for OpenCL kernels on SPIR target + CC_OpenCLKernel, // inferred for OpenCL kernels + CC_Swift, // __attribute__((swiftcall)) + CC_PreserveMost, // __attribute__((preserve_most)) + CC_PreserveAll, // __attribute__((preserve_all)) }; /// \brief Checks whether the given calling convention supports variadic @@ -251,10 +261,12 @@ case CC_X86StdCall: case CC_X86FastCall: case CC_X86ThisCall: + case CC_X86RegCall: case CC_X86Pascal: case CC_X86VectorCall: case CC_SpirFunction: - case CC_SpirKernel: + case CC_OpenCLKernel: + case CC_Swift: return false; default: return true; @@ -286,6 +298,28 @@ /// Retrieve the spelling of the given nullability kind. llvm::StringRef getNullabilitySpelling(NullabilityKind kind, bool isContextSensitive = false); + + /// \brief Kinds of parameter ABI. + enum class ParameterABI { + /// This parameter uses ordinary ABI rules for its type. + Ordinary, + + /// This parameter (which must have pointer type) is a Swift + /// indirect result parameter. + SwiftIndirectResult, + + /// This parameter (which must have pointer-to-pointer type) uses + /// the special Swift error-result ABI treatment. There can be at + /// most one parameter on a given function that uses this treatment. + SwiftErrorResult, + + /// This parameter (which must have pointer type) uses the special + /// Swift context-pointer ABI treatment. There can be at + /// most one parameter on a given function that uses this treatment. + SwiftContext + }; + + llvm::StringRef getParameterABISpelling(ParameterABI kind); } // end namespace clang #endif // LLVM_CLANG_BASIC_SPECIFIERS_H diff -r 56c5119fbcd2 -r c4cc77a799c9 tools/clang/lib/Frontend/FrontendOptions.cpp --- a/tools/clang/lib/Frontend/FrontendOptions.cpp Sun Dec 03 20:09:16 2017 +0900 +++ b/tools/clang/lib/Frontend/FrontendOptions.cpp Mon Dec 04 21:20:52 2017 +0900 @@ -13,23 +13,25 @@ InputKind FrontendOptions::getInputKindForExtension(StringRef Extension) { return llvm::StringSwitch(Extension) - .Cases("ast", "pcm", IK_AST) - .Case("c", IK_C) - .Cases("S", "s", IK_Asm) - .Case("i", IK_PreprocessedC) - .Case("ii", IK_PreprocessedCXX) - .Case("cui", IK_PreprocessedCuda) - .Case("m", IK_ObjC) - .Case("mi", IK_PreprocessedObjC) - .Cases("mm", "M", IK_ObjCXX) - .Case("mii", IK_PreprocessedObjCXX) - .Cases("C", "cc", "cp", IK_CXX) - .Cases("cpp", "CPP", "c++", "cxx", "hpp", IK_CXX) - .Case("cl", IK_OpenCL) - .Case("cu", IK_CUDA) - .Cases("ll", "bc", IK_LLVM_IR) + .Cases("ast", "pcm", InputKind(InputKind::Unknown, InputKind::Precompiled)) + .Case("c", InputKind::C) + .Cases("S", "s", InputKind::Asm) + .Case("i", InputKind(InputKind::C).getPreprocessed()) + .Case("ii", InputKind(InputKind::CXX).getPreprocessed()) + .Case("cui", InputKind(InputKind::CUDA).getPreprocessed()) + .Case("m", InputKind::ObjC) + .Case("mi", InputKind(InputKind::ObjC).getPreprocessed()) + .Cases("mm", "M", InputKind::ObjCXX) + .Case("mii", InputKind(InputKind::ObjCXX).getPreprocessed()) + .Cases("C", "cc", "cp", InputKind::CXX) + .Cases("cpp", "CPP", "c++", "cxx", "hpp", InputKind::CXX) + .Case("cppm", InputKind::CXX) + .Case("iim", InputKind(InputKind::CXX).getPreprocessed()) + .Case("cl", InputKind::OpenCL) + .Case("cu", InputKind::CUDA) + .Cases("ll", "bc", InputKind::LLVM_IR) #ifndef noCbC .Case("cbc", IK_C) #endif - .Default(IK_C); + .Default(InputKind::Unknown); } diff -r 56c5119fbcd2 -r c4cc77a799c9 tools/clang/lib/Lex/PPDirectives.cpp --- a/tools/clang/lib/Lex/PPDirectives.cpp Sun Dec 03 20:09:16 2017 +0900 +++ b/tools/clang/lib/Lex/PPDirectives.cpp Mon Dec 04 21:20:52 2017 +0900 @@ -12,60 +12,59 @@ /// //===----------------------------------------------------------------------===// -#include "clang/Lex/Preprocessor.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/FileManager.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/Module.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/TokenKinds.h" #include "clang/Lex/CodeCompletionHandler.h" #include "clang/Lex/HeaderSearch.h" -#include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/LexDiagnostic.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Lex/MacroInfo.h" #include "clang/Lex/ModuleLoader.h" +#include "clang/Lex/ModuleMap.h" +#include "clang/Lex/PPCallbacks.h" #include "clang/Lex/Pragma.h" -#include "llvm/ADT/APInt.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Lex/PreprocessorOptions.h" +#include "clang/Lex/PTHLexer.h" +#include "clang/Lex/Token.h" +#include "clang/Lex/VariadicMacroSupport.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/AlignOf.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Path.h" -#include "llvm/Support/SaveAndRestore.h" - +#include +#include +#include +#include +#include +#include #ifndef noCbC #include #endif + using namespace clang; //===----------------------------------------------------------------------===// // Utility Methods for Preprocessor Directive Handling. //===----------------------------------------------------------------------===// -MacroInfo *Preprocessor::AllocateMacroInfo() { - MacroInfoChain *MIChain = BP.Allocate(); - MIChain->Next = MIChainHead; +MacroInfo *Preprocessor::AllocateMacroInfo(SourceLocation L) { + auto *MIChain = new (BP) MacroInfoChain{L, MIChainHead}; MIChainHead = MIChain; return &MIChain->MI; } -MacroInfo *Preprocessor::AllocateMacroInfo(SourceLocation L) { - MacroInfo *MI = AllocateMacroInfo(); - new (MI) MacroInfo(L); - return MI; -} - -MacroInfo *Preprocessor::AllocateDeserializedMacroInfo(SourceLocation L, - unsigned SubModuleID) { - static_assert(llvm::AlignOf::Alignment >= sizeof(SubModuleID), - "alignment for MacroInfo is less than the ID"); - DeserializedMacroInfoChain *MIChain = - BP.Allocate(); - MIChain->Next = DeserialMIChainHead; - DeserialMIChainHead = MIChain; - - MacroInfo *MI = &MIChain->MI; - new (MI) MacroInfo(L); - MI->FromASTFile = true; - MI->setOwningModuleID(SubModuleID); - return MI; -} - DefMacroDirective *Preprocessor::AllocateDefMacroDirective(MacroInfo *MI, SourceLocation Loc) { return new (BP) DefMacroDirective(MI, Loc); @@ -140,6 +139,84 @@ return MD_NoWarn; } +// Return true if we want to issue a diagnostic by default if we +// encounter this name in a #include with the wrong case. For now, +// this includes the standard C and C++ headers, Posix headers, +// and Boost headers. Improper case for these #includes is a +// potential portability issue. +static bool warnByDefaultOnWrongCase(StringRef Include) { + // If the first component of the path is "boost", treat this like a standard header + // for the purposes of diagnostics. + if (::llvm::sys::path::begin(Include)->equals_lower("boost")) + return true; + + // "condition_variable" is the longest standard header name at 18 characters. + // If the include file name is longer than that, it can't be a standard header. + static const size_t MaxStdHeaderNameLen = 18u; + if (Include.size() > MaxStdHeaderNameLen) + return false; + + // Lowercase and normalize the search string. + SmallString<32> LowerInclude{Include}; + for (char &Ch : LowerInclude) { + // In the ASCII range? + if (static_cast(Ch) > 0x7f) + return false; // Can't be a standard header + // ASCII lowercase: + if (Ch >= 'A' && Ch <= 'Z') + Ch += 'a' - 'A'; + // Normalize path separators for comparison purposes. + else if (::llvm::sys::path::is_separator(Ch)) + Ch = '/'; + } + + // The standard C/C++ and Posix headers + return llvm::StringSwitch(LowerInclude) + // C library headers + .Cases("assert.h", "complex.h", "ctype.h", "errno.h", "fenv.h", true) + .Cases("float.h", "inttypes.h", "iso646.h", "limits.h", "locale.h", true) + .Cases("math.h", "setjmp.h", "signal.h", "stdalign.h", "stdarg.h", true) + .Cases("stdatomic.h", "stdbool.h", "stddef.h", "stdint.h", "stdio.h", true) + .Cases("stdlib.h", "stdnoreturn.h", "string.h", "tgmath.h", "threads.h", true) + .Cases("time.h", "uchar.h", "wchar.h", "wctype.h", true) + + // C++ headers for C library facilities + .Cases("cassert", "ccomplex", "cctype", "cerrno", "cfenv", true) + .Cases("cfloat", "cinttypes", "ciso646", "climits", "clocale", true) + .Cases("cmath", "csetjmp", "csignal", "cstdalign", "cstdarg", true) + .Cases("cstdbool", "cstddef", "cstdint", "cstdio", "cstdlib", true) + .Cases("cstring", "ctgmath", "ctime", "cuchar", "cwchar", true) + .Case("cwctype", true) + + // C++ library headers + .Cases("algorithm", "fstream", "list", "regex", "thread", true) + .Cases("array", "functional", "locale", "scoped_allocator", "tuple", true) + .Cases("atomic", "future", "map", "set", "type_traits", true) + .Cases("bitset", "initializer_list", "memory", "shared_mutex", "typeindex", true) + .Cases("chrono", "iomanip", "mutex", "sstream", "typeinfo", true) + .Cases("codecvt", "ios", "new", "stack", "unordered_map", true) + .Cases("complex", "iosfwd", "numeric", "stdexcept", "unordered_set", true) + .Cases("condition_variable", "iostream", "ostream", "streambuf", "utility", true) + .Cases("deque", "istream", "queue", "string", "valarray", true) + .Cases("exception", "iterator", "random", "strstream", "vector", true) + .Cases("forward_list", "limits", "ratio", "system_error", true) + + // POSIX headers (which aren't also C headers) + .Cases("aio.h", "arpa/inet.h", "cpio.h", "dirent.h", "dlfcn.h", true) + .Cases("fcntl.h", "fmtmsg.h", "fnmatch.h", "ftw.h", "glob.h", true) + .Cases("grp.h", "iconv.h", "langinfo.h", "libgen.h", "monetary.h", true) + .Cases("mqueue.h", "ndbm.h", "net/if.h", "netdb.h", "netinet/in.h", true) + .Cases("netinet/tcp.h", "nl_types.h", "poll.h", "pthread.h", "pwd.h", true) + .Cases("regex.h", "sched.h", "search.h", "semaphore.h", "spawn.h", true) + .Cases("strings.h", "stropts.h", "sys/ipc.h", "sys/mman.h", "sys/msg.h", true) + .Cases("sys/resource.h", "sys/select.h", "sys/sem.h", "sys/shm.h", "sys/socket.h", true) + .Cases("sys/stat.h", "sys/statvfs.h", "sys/time.h", "sys/times.h", "sys/types.h", true) + .Cases("sys/uio.h", "sys/un.h", "sys/utsname.h", "sys/wait.h", "syslog.h", true) + .Cases("tar.h", "termios.h", "trace.h", "ulimit.h", true) + .Cases("unistd.h", "utime.h", "utmpx.h", "wordexp.h", true) + .Default(false); +} + bool Preprocessor::CheckMacroName(Token &MacroNameTok, MacroUse isDefineUndef, bool *ShadowFlag) { // Missing macro name? @@ -147,26 +224,18 @@ return Diag(MacroNameTok, diag::err_pp_missing_macro_name); IdentifierInfo *II = MacroNameTok.getIdentifierInfo(); - if (!II) { - bool Invalid = false; - std::string Spelling = getSpelling(MacroNameTok, &Invalid); - if (Invalid) - return Diag(MacroNameTok, diag::err_pp_macro_not_identifier); - II = getIdentifierInfo(Spelling); - - if (!II->isCPlusPlusOperatorKeyword()) - return Diag(MacroNameTok, diag::err_pp_macro_not_identifier); - + if (!II) + return Diag(MacroNameTok, diag::err_pp_macro_not_identifier); + + if (II->isCPlusPlusOperatorKeyword()) { // C++ 2.5p2: Alternative tokens behave the same as its primary token // except for their spellings. Diag(MacroNameTok, getLangOpts().MicrosoftExt ? diag::ext_pp_operator_used_as_macro_name : diag::err_pp_operator_used_as_macro_name) << II << MacroNameTok.getKind(); - // Allow #defining |and| and friends for Microsoft compatibility or // recovery when legacy C headers are included in C++. - MacroNameTok.setIdentifierInfo(II); } if ((isDefineUndef != MU_Other) && II->getPPKeywordID() == tok::pp_defined) { @@ -189,7 +258,7 @@ if (ShadowFlag) *ShadowFlag = false; if (!SourceMgr.isInSystemHeader(MacroNameLoc) && - (strcmp(SourceMgr.getBufferName(MacroNameLoc), "") != 0)) { + (SourceMgr.getBufferName(MacroNameLoc) != "")) { MacroDiag D = MD_NoWarn; if (isDefineUndef == MU_Define) { D = shouldWarnOnMacroDef(*this, II); @@ -276,8 +345,6 @@ } } - - /// SkipExcludedConditionalBlock - We just read a \#if or related directive and /// decided that the subsequent tokens are in the \#if'd out portion of the /// file. Lex the rest of the file, until we see an \#endif. If @@ -286,7 +353,8 @@ /// If ElseOk is true, then \#else directives are ok, if not, then we have /// already seen one so a \#else directive is a duplicate. When this returns, /// the caller can lex the first valid token. -void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, +void Preprocessor::SkipExcludedConditionalBlock(const Token &HashToken, + SourceLocation IfTokenLoc, bool FoundNonSkipPortion, bool FoundElse, SourceLocation ElseLoc) { @@ -305,7 +373,7 @@ // disabling warnings, etc. CurPPLexer->LexingRawMode = true; Token Tok; - while (1) { + while (true) { CurLexer->Lex(Tok); if (Tok.is(tok::code_completion)) { @@ -314,18 +382,11 @@ setCodeCompletionReached(); continue; } - + // If this is the end of the buffer, we have an error. if (Tok.is(tok::eof)) { - // Emit errors for each unterminated conditional on the stack, including - // the current one. - while (!CurPPLexer->ConditionalStack.empty()) { - if (CurLexer->getFileLoc() != CodeCompletionFileLoc) - Diag(CurPPLexer->ConditionalStack.back().IfLoc, - diag::err_pp_unterminated_conditional); - CurPPLexer->ConditionalStack.pop_back(); - } - + // We don't emit errors for unterminated conditionals here, + // Lexer::LexEndOfFile can do that propertly. // Just return and let the caller lex after this #include. break; } @@ -378,7 +439,7 @@ Directive = RI; } else { std::string DirectiveStr = getSpelling(Tok); - unsigned IdLen = DirectiveStr.size(); + size_t IdLen = DirectiveStr.size(); if (IdLen >= 20) { CurPPLexer->ParsingPreprocessorDirective = false; // Restore comment saving mode. @@ -467,7 +528,7 @@ assert(CurPPLexer->LexingRawMode && "We have to be skipping here!"); CurPPLexer->LexingRawMode = false; IdentifierInfo *IfNDefMacro = nullptr; - const bool CondValue = EvaluateDirectiveExpression(IfNDefMacro); + const bool CondValue = EvaluateDirectiveExpression(IfNDefMacro).Conditional; CurPPLexer->LexingRawMode = true; if (Callbacks) { const SourceLocation CondEnd = CurPPLexer->getSourceLocation(); @@ -494,15 +555,14 @@ // the #if block. CurPPLexer->LexingRawMode = false; - if (Callbacks) { - SourceLocation BeginLoc = ElseLoc.isValid() ? ElseLoc : IfTokenLoc; - Callbacks->SourceRangeSkipped(SourceRange(BeginLoc, Tok.getLocation())); - } + if (Callbacks) + Callbacks->SourceRangeSkipped( + SourceRange(HashToken.getLocation(), CurPPLexer->getSourceLocation()), + Tok.getLocation()); } void Preprocessor::PTHSkipExcludedConditionalBlock() { - - while (1) { + while (true) { assert(CurPTHLexer); assert(CurPTHLexer->LexingRawMode == false); @@ -565,7 +625,7 @@ // Evaluate the condition of the #elif. IdentifierInfo *IfNDefMacro = nullptr; CurPTHLexer->ParsingPreprocessorDirective = true; - bool ShouldEnter = EvaluateDirectiveExpression(IfNDefMacro); + bool ShouldEnter = EvaluateDirectiveExpression(IfNDefMacro).Conditional; CurPTHLexer->ParsingPreprocessorDirective = false; // If this condition is true, enter it! @@ -575,52 +635,99 @@ } // Otherwise, skip this block and go to the next one. - continue; } } Module *Preprocessor::getModuleForLocation(SourceLocation Loc) { - ModuleMap &ModMap = HeaderInfo.getModuleMap(); - if (SourceMgr.isInMainFile(Loc)) { - if (Module *CurMod = getCurrentModule()) - return CurMod; // Compiling a module. - return HeaderInfo.getModuleMap().SourceModule; // Compiling a source. + if (!SourceMgr.isInMainFile(Loc)) { + // Try to determine the module of the include directive. + // FIXME: Look into directly passing the FileEntry from LookupFile instead. + FileID IDOfIncl = SourceMgr.getFileID(SourceMgr.getExpansionLoc(Loc)); + if (const FileEntry *EntryOfIncl = SourceMgr.getFileEntryForID(IDOfIncl)) { + // The include comes from an included file. + return HeaderInfo.getModuleMap() + .findModuleForHeader(EntryOfIncl) + .getModule(); + } } - // Try to determine the module of the include directive. - // FIXME: Look into directly passing the FileEntry from LookupFile instead. - FileID IDOfIncl = SourceMgr.getFileID(SourceMgr.getExpansionLoc(Loc)); - if (const FileEntry *EntryOfIncl = SourceMgr.getFileEntryForID(IDOfIncl)) { - // The include comes from a file. - return ModMap.findModuleForHeader(EntryOfIncl).getModule(); - } else { - // The include does not come from a file, - // so it is probably a module compilation. - return getCurrentModule(); + + // This is either in the main file or not in a file at all. It belongs + // to the current module, if there is one. + return getLangOpts().CurrentModule.empty() + ? nullptr + : HeaderInfo.lookupModule(getLangOpts().CurrentModule); +} + +const FileEntry * +Preprocessor::getModuleHeaderToIncludeForDiagnostics(SourceLocation IncLoc, + Module *M, + SourceLocation Loc) { + assert(M && "no module to include"); + + // If we have a module import syntax, we shouldn't include a header to + // make a particular module visible. + if (getLangOpts().ObjC2) + return nullptr; + + Module *TopM = M->getTopLevelModule(); + Module *IncM = getModuleForLocation(IncLoc); + + // Walk up through the include stack, looking through textual headers of M + // until we hit a non-textual header that we can #include. (We assume textual + // headers of a module with non-textual headers aren't meant to be used to + // import entities from the module.) + auto &SM = getSourceManager(); + while (!Loc.isInvalid() && !SM.isInMainFile(Loc)) { + auto ID = SM.getFileID(SM.getExpansionLoc(Loc)); + auto *FE = SM.getFileEntryForID(ID); + if (!FE) + break; + + bool InTextualHeader = false; + for (auto Header : HeaderInfo.getModuleMap().findAllModulesForHeader(FE)) { + if (!Header.getModule()->isSubModuleOf(TopM)) + continue; + + if (!(Header.getRole() & ModuleMap::TextualHeader)) { + // If this is an accessible, non-textual header of M's top-level module + // that transitively includes the given location and makes the + // corresponding module visible, this is the thing to #include. + if (Header.isAccessibleFrom(IncM)) + return FE; + + // It's in a private header; we can't #include it. + // FIXME: If there's a public header in some module that re-exports it, + // then we could suggest including that, but it's not clear that's the + // expected way to make this entity visible. + continue; + } + + InTextualHeader = true; + } + + if (!InTextualHeader) + break; + + Loc = SM.getIncludeLoc(ID); } -} - -Module *Preprocessor::getModuleContainingLocation(SourceLocation Loc) { - return HeaderInfo.getModuleMap().inferModuleFromLocation( - FullSourceLoc(Loc, SourceMgr)); + + return nullptr; } const FileEntry *Preprocessor::LookupFile( - SourceLocation FilenameLoc, - StringRef Filename, - bool isAngled, - const DirectoryLookup *FromDir, - const FileEntry *FromFile, - const DirectoryLookup *&CurDir, - SmallVectorImpl *SearchPath, + SourceLocation FilenameLoc, StringRef Filename, bool isAngled, + const DirectoryLookup *FromDir, const FileEntry *FromFile, + const DirectoryLookup *&CurDir, SmallVectorImpl *SearchPath, SmallVectorImpl *RelativePath, - ModuleMap::KnownHeader *SuggestedModule, - bool SkipCache) { - Module *RequestingModule = getModuleForLocation(FilenameLoc); + ModuleMap::KnownHeader *SuggestedModule, bool *IsMapped, bool SkipCache) { + Module *RequestingModule = getModuleForLocation(FilenameLoc); + bool RequestingModuleIsModuleInterface = !SourceMgr.isInMainFile(FilenameLoc); // If the header lookup mechanism may be relative to the current inclusion // stack, record the parent #includes. SmallVector, 16> Includers; + bool BuildSystemModule = false; if (!FromDir && !FromFile) { FileID FID = getCurrentFileLexer()->getFileID(); const FileEntry *FileEnt = SourceMgr.getFileEntryForID(FID); @@ -638,9 +745,10 @@ // come from header declarations in the module map) relative to the module // map file. if (!FileEnt) { - if (FID == SourceMgr.getMainFileID() && MainFileDir) + if (FID == SourceMgr.getMainFileID() && MainFileDir) { Includers.push_back(std::make_pair(nullptr, MainFileDir)); - else if ((FileEnt = + BuildSystemModule = getCurrentModule()->IsSystem; + } else if ((FileEnt = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()))) Includers.push_back(std::make_pair(FileEnt, FileMgr.getDirectory("."))); } else { @@ -651,8 +759,7 @@ // headers included by quoted include directives. // See: http://msdn.microsoft.com/en-us/library/36k2cdd4.aspx if (LangOpts.MSVCCompat && !isAngled) { - for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) { - IncludeStackInfo &ISEntry = IncludeMacroStack[e - i - 1]; + for (IncludeStackInfo &ISEntry : llvm::reverse(IncludeMacroStack)) { if (IsFileLexer(ISEntry)) if ((FileEnt = ISEntry.ThePPLexer->getFileEntry())) Includers.push_back(std::make_pair(FileEnt, FileEnt->getDir())); @@ -670,7 +777,7 @@ while (const FileEntry *FE = HeaderInfo.LookupFile( Filename, FilenameLoc, isAngled, TmpFromDir, TmpCurDir, Includers, SearchPath, RelativePath, RequestingModule, - SuggestedModule, SkipCache)) { + SuggestedModule, /*IsMapped=*/nullptr, SkipCache)) { // Keep looking as if this file did a #include_next. TmpFromDir = TmpCurDir; ++TmpFromDir; @@ -686,11 +793,13 @@ // Do a standard file entry lookup. const FileEntry *FE = HeaderInfo.LookupFile( Filename, FilenameLoc, isAngled, FromDir, CurDir, Includers, SearchPath, - RelativePath, RequestingModule, SuggestedModule, SkipCache); + RelativePath, RequestingModule, SuggestedModule, IsMapped, SkipCache, + BuildSystemModule); if (FE) { if (SuggestedModule && !LangOpts.AsmPreprocessor) HeaderInfo.getModuleMap().diagnoseHeaderInclusion( - RequestingModule, FilenameLoc, Filename, FE); + RequestingModule, RequestingModuleIsModuleInterface, FilenameLoc, + Filename, FE); return FE; } @@ -706,14 +815,14 @@ SuggestedModule))) { if (SuggestedModule && !LangOpts.AsmPreprocessor) HeaderInfo.getModuleMap().diagnoseHeaderInclusion( - RequestingModule, FilenameLoc, Filename, FE); + RequestingModule, RequestingModuleIsModuleInterface, FilenameLoc, + Filename, FE); return FE; } } } - for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) { - IncludeStackInfo &ISEntry = IncludeMacroStack[e-i-1]; + for (IncludeStackInfo &ISEntry : llvm::reverse(IncludeMacroStack)) { if (IsFileLexer(ISEntry)) { if ((CurFileEnt = ISEntry.ThePPLexer->getFileEntry())) { if ((FE = HeaderInfo.LookupSubframeworkHeader( @@ -721,7 +830,8 @@ RequestingModule, SuggestedModule))) { if (SuggestedModule && !LangOpts.AsmPreprocessor) HeaderInfo.getModuleMap().diagnoseHeaderInclusion( - RequestingModule, FilenameLoc, Filename, FE); + RequestingModule, RequestingModuleIsModuleInterface, + FilenameLoc, Filename, FE); return FE; } } @@ -732,7 +842,6 @@ return nullptr; } - //===----------------------------------------------------------------------===// // Preprocessor Directive Handling. //===----------------------------------------------------------------------===// @@ -744,9 +853,11 @@ if (pp->MacroExpansionInDirectivesOverride) pp->DisableMacroExpansion = false; } + ~ResetMacroExpansionHelper() { PP->DisableMacroExpansion = save; } + private: Preprocessor *PP; bool save; @@ -835,15 +946,17 @@ default: break; // C99 6.10.1 - Conditional Inclusion. case tok::pp_if: - return HandleIfDirective(Result, ReadAnyTokensBeforeDirective); + return HandleIfDirective(Result, SavedHash, ReadAnyTokensBeforeDirective); case tok::pp_ifdef: - return HandleIfdefDirective(Result, false, true/*not valid for miopt*/); + return HandleIfdefDirective(Result, SavedHash, false, + true /*not valid for miopt*/); case tok::pp_ifndef: - return HandleIfdefDirective(Result, true, ReadAnyTokensBeforeDirective); + return HandleIfdefDirective(Result, SavedHash, true, + ReadAnyTokensBeforeDirective); case tok::pp_elif: - return HandleElifDirective(Result); + return HandleElifDirective(Result, SavedHash); case tok::pp_else: - return HandleElseDirective(Result); + return HandleElseDirective(Result, SavedHash); case tok::pp_endif: return HandleEndifDirective(Result); @@ -853,17 +966,17 @@ return HandleIncludeDirective(SavedHash.getLocation(), Result); case tok::pp___include_macros: // Handle -imacros. - return HandleIncludeMacrosDirective(SavedHash.getLocation(), Result); + return HandleIncludeMacrosDirective(SavedHash.getLocation(), Result); // C99 6.10.3 - Macro Replacement. case tok::pp_define: return HandleDefineDirective(Result, ImmediatelyAfterTopLevelIfndef); case tok::pp_undef: - return HandleUndefDirective(Result); + return HandleUndefDirective(); // C99 6.10.4 - Line Control. case tok::pp_line: - return HandleLineDirective(Result); + return HandleLineDirective(); // C99 6.10.5 - Error Directive. case tok::pp_error: @@ -892,15 +1005,15 @@ case tok::pp_unassert: //isExtension = true; // FIXME: implement #unassert break; - + case tok::pp___public_macro: if (getLangOpts().Modules) return HandleMacroPublicDirective(Result); break; - + case tok::pp___private_macro: if (getLangOpts().Modules) - return HandleMacroPrivateDirective(Result); + return HandleMacroPrivateDirective(); break; } break; @@ -911,20 +1024,20 @@ // various pseudo-ops. Just return the # token and push back the following // token to be lexed next time. if (getLangOpts().AsmPreprocessor) { - Token *Toks = new Token[2]; + auto Toks = llvm::make_unique(2); // Return the # and the token after it. Toks[0] = SavedHash; Toks[1] = Result; - + // If the second token is a hashhash token, then we need to translate it to // unknown so the token lexer doesn't try to perform token pasting. if (Result.is(tok::hashhash)) Toks[1].setKind(tok::unknown); - + // Enter this token stream so that we re-lex the tokens. Make sure to // enable macro expansion, in case the token after the # is an identifier // that is expanded. - EnterTokenStream(Toks, 2, false, true); + EnterTokenStream(std::move(Toks), 2, false); return; } @@ -957,7 +1070,7 @@ unsigned ActualLength = PP.getSpelling(DigitTok, DigitTokBegin, &Invalid); if (Invalid) return true; - + // Verify that we have a simple digit-sequence, and compute the value. This // is always a simple digit string computed in decimal, so we do this manually // here. @@ -998,7 +1111,7 @@ /// # line digit-sequence /// # line digit-sequence "s-char-sequence" /// \endverbatim -void Preprocessor::HandleLineDirective(Token &Tok) { +void Preprocessor::HandleLineDirective() { // Read the line # and string argument. Per C99 6.10.4p5, these tokens are // expanded. Token DigitTok; @@ -1008,7 +1121,7 @@ unsigned LineNo; if (GetLineValue(DigitTok, LineNo, diag::err_pp_line_requires_integer,*this)) return; - + if (LineNo == 0) Diag(DigitTok, diag::ext_pp_line_zero); @@ -1053,18 +1166,26 @@ CheckEndOfDirective("line", true); } - SourceMgr.AddLineNote(DigitTok.getLocation(), LineNo, FilenameID); + // Take the file kind of the file containing the #line directive. #line + // directives are often used for generated sources from the same codebase, so + // the new file should generally be classified the same way as the current + // file. This is visible in GCC's pre-processed output, which rewrites #line + // to GNU line markers. + SrcMgr::CharacteristicKind FileKind = + SourceMgr.getFileCharacteristic(DigitTok.getLocation()); + + SourceMgr.AddLineNote(DigitTok.getLocation(), LineNo, FilenameID, false, + false, FileKind); if (Callbacks) Callbacks->FileChanged(CurPPLexer->getSourceLocation(), - PPCallbacks::RenameFile, - SrcMgr::C_User); + PPCallbacks::RenameFile, FileKind); } /// ReadLineMarkerFlags - Parse and validate any flags at the end of a GNU line /// marker directive. static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit, - bool &IsSystemHeader, bool &IsExternCHeader, + SrcMgr::CharacteristicKind &FileKind, Preprocessor &PP) { unsigned FlagVal; Token FlagTok; @@ -1091,7 +1212,7 @@ PresumedLoc PLoc = SM.getPresumedLoc(FlagTok.getLocation()); if (PLoc.isInvalid()) return true; - + // If there is no include loc (main file) or if the include loc is in a // different physical file, then we aren't in a "1" line marker flag region. SourceLocation IncLoc = PLoc.getIncludeLoc(); @@ -1115,7 +1236,7 @@ return true; } - IsSystemHeader = true; + FileKind = SrcMgr::C_System; PP.Lex(FlagTok); if (FlagTok.is(tok::eod)) return false; @@ -1129,7 +1250,7 @@ return true; } - IsExternCHeader = true; + FileKind = SrcMgr::C_ExternCSystem; PP.Lex(FlagTok); if (FlagTok.is(tok::eod)) return false; @@ -1159,14 +1280,15 @@ Lex(StrTok); bool IsFileEntry = false, IsFileExit = false; - bool IsSystemHeader = false, IsExternCHeader = false; int FilenameID = -1; + SrcMgr::CharacteristicKind FileKind = SrcMgr::C_User; // If the StrTok is "eod", then it wasn't present. Otherwise, it must be a // string followed by eod. - if (StrTok.is(tok::eod)) - ; // ok - else if (StrTok.isNot(tok::string_literal)) { + if (StrTok.is(tok::eod)) { + // Treat this like "#line NN", which doesn't change file characteristics. + FileKind = SourceMgr.getFileCharacteristic(DigitTok.getLocation()); + } else if (StrTok.isNot(tok::string_literal)) { Diag(StrTok, diag::err_pp_linemarker_invalid_filename); return DiscardUntilEndOfDirective(); } else if (StrTok.hasUDSuffix()) { @@ -1185,15 +1307,13 @@ FilenameID = SourceMgr.getLineTableFilenameID(Literal.GetString()); // If a filename was present, read any flags that are present. - if (ReadLineMarkerFlags(IsFileEntry, IsFileExit, - IsSystemHeader, IsExternCHeader, *this)) + if (ReadLineMarkerFlags(IsFileEntry, IsFileExit, FileKind, *this)) return; } // Create a line note with this information. - SourceMgr.AddLineNote(DigitTok.getLocation(), LineNo, FilenameID, - IsFileEntry, IsFileExit, - IsSystemHeader, IsExternCHeader); + SourceMgr.AddLineNote(DigitTok.getLocation(), LineNo, FilenameID, IsFileEntry, + IsFileExit, FileKind); // If the preprocessor has callbacks installed, notify them of the #line // change. This is used so that the line marker comes out in -E mode for @@ -1204,17 +1324,11 @@ Reason = PPCallbacks::EnterFile; else if (IsFileExit) Reason = PPCallbacks::ExitFile; - SrcMgr::CharacteristicKind FileKind = SrcMgr::C_User; - if (IsExternCHeader) - FileKind = SrcMgr::C_ExternCSystem; - else if (IsSystemHeader) - FileKind = SrcMgr::C_System; Callbacks->FileChanged(CurPPLexer->getSourceLocation(), Reason, FileKind); } } - /// HandleUserDiagnosticDirective - Handle a #warning or #error directive. /// void Preprocessor::HandleUserDiagnosticDirective(Token &Tok, @@ -1233,7 +1347,7 @@ // Find the first non-whitespace character, so that we can make the // diagnostic more succinct. - StringRef Msg = StringRef(Message).ltrim(" "); + StringRef Msg = StringRef(Message).ltrim(' '); if (isWarning) Diag(Tok, diag::pp_hash_warning) << Msg; @@ -1280,7 +1394,7 @@ void Preprocessor::HandleMacroPublicDirective(Token &Tok) { Token MacroNameTok; ReadMacroName(MacroNameTok, MU_Undef); - + // Error reading macro name? If so, diagnostic already issued. if (MacroNameTok.is(tok::eod)) return; @@ -1291,40 +1405,40 @@ IdentifierInfo *II = MacroNameTok.getIdentifierInfo(); // Okay, we finally have a valid identifier to undef. MacroDirective *MD = getLocalMacroDirective(II); - + // If the macro is not defined, this is an error. if (!MD) { Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << II; return; } - + // Note that this macro has now been exported. appendMacroDirective(II, AllocateVisibilityMacroDirective( MacroNameTok.getLocation(), /*IsPublic=*/true)); } /// \brief Handle a #private directive. -void Preprocessor::HandleMacroPrivateDirective(Token &Tok) { +void Preprocessor::HandleMacroPrivateDirective() { Token MacroNameTok; ReadMacroName(MacroNameTok, MU_Undef); - + // Error reading macro name? If so, diagnostic already issued. if (MacroNameTok.is(tok::eod)) return; - + // Check to see if this is the last token on the #__private_macro line. CheckEndOfDirective("__private_macro"); - + IdentifierInfo *II = MacroNameTok.getIdentifierInfo(); // Okay, we finally have a valid identifier to undef. MacroDirective *MD = getLocalMacroDirective(II); - + // If the macro is not defined, this is an error. if (!MD) { Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << II; return; } - + // Note that this macro has now been marked private. appendMacroDirective(II, AllocateVisibilityMacroDirective( MacroNameTok.getLocation(), /*IsPublic=*/false)); @@ -1399,7 +1513,7 @@ Lex(CurTok); while (CurTok.isNot(tok::eod)) { End = CurTok.getLocation(); - + // FIXME: Provide code completion for #includes. if (CurTok.is(tok::code_completion)) { setCodeCompletionReached(); @@ -1413,7 +1527,7 @@ FilenameBuffer.push_back(' '); // Get the spelling of the token, directly into FilenameBuffer if possible. - unsigned PreAppendSize = FilenameBuffer.size(); + size_t PreAppendSize = FilenameBuffer.size(); FilenameBuffer.resize(PreAppendSize+CurTok.getLength()); const char *BufPtr = &FilenameBuffer[PreAppendSize]; @@ -1441,18 +1555,18 @@ } /// \brief Push a token onto the token stream containing an annotation. -static void EnterAnnotationToken(Preprocessor &PP, - SourceLocation Begin, SourceLocation End, - tok::TokenKind Kind, void *AnnotationVal) { +void Preprocessor::EnterAnnotationToken(SourceRange Range, + tok::TokenKind Kind, + void *AnnotationVal) { // FIXME: Produce this as the current token directly, rather than // allocating a new token for it. - Token *Tok = new Token[1]; + auto Tok = llvm::make_unique(1); Tok[0].startToken(); Tok[0].setKind(Kind); - Tok[0].setLocation(Begin); - Tok[0].setAnnotationEndLoc(End); + Tok[0].setLocation(Range.getBegin()); + Tok[0].setAnnotationEndLoc(Range.getEnd()); Tok[0].setAnnotationValue(AnnotationVal); - PP.EnterTokenStream(Tok, 1, true, true); + EnterTokenStream(std::move(Tok), 1, true); } /// \brief Produce a diagnostic informing the user that a #include or similar @@ -1464,30 +1578,30 @@ assert(PP.getLangOpts().ObjC2 && "no import syntax available"); SmallString<128> PathString; - for (unsigned I = 0, N = Path.size(); I != N; ++I) { + for (size_t I = 0, N = Path.size(); I != N; ++I) { if (I) PathString += '.'; PathString += Path[I].first->getName(); } int IncludeKind = 0; - + switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) { case tok::pp_include: IncludeKind = 0; break; - + case tok::pp_import: IncludeKind = 1; - break; - + break; + case tok::pp_include_next: IncludeKind = 2; break; - + case tok::pp___include_macros: IncludeKind = 3; break; - + default: llvm_unreachable("unknown include directive kind"); } @@ -1500,17 +1614,69 @@ ("@import " + PathString + ";").str()); } +// Given a vector of path components and a string containing the real +// path to the file, build a properly-cased replacement in the vector, +// and return true if the replacement should be suggested. +static bool trySimplifyPath(SmallVectorImpl &Components, + StringRef RealPathName) { + auto RealPathComponentIter = llvm::sys::path::rbegin(RealPathName); + auto RealPathComponentEnd = llvm::sys::path::rend(RealPathName); + int Cnt = 0; + bool SuggestReplacement = false; + // Below is a best-effort to handle ".." in paths. It is admittedly + // not 100% correct in the presence of symlinks. + for (auto &Component : llvm::reverse(Components)) { + if ("." == Component) { + } else if (".." == Component) { + ++Cnt; + } else if (Cnt) { + --Cnt; + } else if (RealPathComponentIter != RealPathComponentEnd) { + if (Component != *RealPathComponentIter) { + // If these path components differ by more than just case, then we + // may be looking at symlinked paths. Bail on this diagnostic to avoid + // noisy false positives. + SuggestReplacement = RealPathComponentIter->equals_lower(Component); + if (!SuggestReplacement) + break; + Component = *RealPathComponentIter; + } + ++RealPathComponentIter; + } + } + return SuggestReplacement; +} + +bool Preprocessor::checkModuleIsAvailable(const LangOptions &LangOpts, + const TargetInfo &TargetInfo, + DiagnosticsEngine &Diags, Module *M) { + Module::Requirement Requirement; + Module::UnresolvedHeaderDirective MissingHeader; + if (M->isAvailable(LangOpts, TargetInfo, Requirement, MissingHeader)) + return false; + + if (MissingHeader.FileNameLoc.isValid()) { + Diags.Report(MissingHeader.FileNameLoc, diag::err_module_header_missing) + << MissingHeader.IsUmbrella << MissingHeader.FileName; + } else { + // FIXME: Track the location at which the requirement was specified, and + // use it here. + Diags.Report(M->DefinitionLoc, diag::err_module_unavailable) + << M->getFullModuleName() << Requirement.second << Requirement.first; + } + return true; +} + /// HandleIncludeDirective - The "\#include" tokens have just been read, read /// the file to be included from the lexer, then include it! This is a common /// routine with functionality shared between \#include, \#include_next and /// \#import. LookupFrom is set when this is a \#include_next directive, it /// specifies the file to start searching from. -void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, +void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, Token &IncludeTok, const DirectoryLookup *LookupFrom, const FileEntry *LookupFromFile, bool isImport) { - Token FilenameTok; CurPPLexer->LexIncludeFilename(FilenameTok); @@ -1519,7 +1685,7 @@ StringRef Filename; SourceLocation End; SourceLocation CharEnd; // the end of this directive, in characters - + switch (FilenameTok.getKind()) { case tok::eod: // If the token kind is EOD, the error has already been diagnosed. @@ -1590,8 +1756,8 @@ } if (HeaderInfo.HasIncludeAliasMap()) { - // Map the filename with the brackets still attached. If the name doesn't - // map to anything, fall back on the filename we've already gotten the + // Map the filename with the brackets still attached. If the name doesn't + // map to anything, fall back on the filename we've already gotten the // spelling for. StringRef NewName = HeaderInfo.MapHeaderToIncludeAlias(OriginalFilename); if (!NewName.empty()) @@ -1599,6 +1765,7 @@ } // Search include directories. + bool IsMapped = false; const DirectoryLookup *CurDir; SmallString<1024> SearchPath; SmallString<1024> RelativePath; @@ -1617,7 +1784,7 @@ FilenameLoc, LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, isAngled, LookupFrom, LookupFromFile, CurDir, Callbacks ? &SearchPath : nullptr, Callbacks ? &RelativePath : nullptr, - &SuggestedModule); + &SuggestedModule, &IsMapped); if (!File) { if (Callbacks) { @@ -1628,19 +1795,19 @@ // Add the recovery path to the list of search paths. DirectoryLookup DL(DE, SrcMgr::C_User, false); HeaderInfo.AddSearchPath(DL, isAngled); - + // Try the lookup again, skipping the cache. File = LookupFile( FilenameLoc, LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, isAngled, LookupFrom, LookupFromFile, CurDir, nullptr, nullptr, - &SuggestedModule, /*SkipCache*/ true); + &SuggestedModule, &IsMapped, /*SkipCache*/ true); } } } if (!SuppressIncludeNotFoundError) { - // If the file could not be located and it was included via angle + // If the file could not be located and it was included via angle // brackets, we can attempt a lookup as though it were a quoted path to // provide the user with a possible fixit. if (isAngled) { @@ -1649,19 +1816,19 @@ LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, false, LookupFrom, LookupFromFile, CurDir, Callbacks ? &SearchPath : nullptr, - Callbacks ? &RelativePath : nullptr, - &SuggestedModule); + Callbacks ? &RelativePath : nullptr, &SuggestedModule, &IsMapped); if (File) { SourceRange Range(FilenameTok.getLocation(), CharEnd); - Diag(FilenameTok, diag::err_pp_file_not_found_not_fatal) << - Filename << + Diag(FilenameTok, diag::err_pp_file_not_found_not_fatal) << + Filename << FixItHint::CreateReplacement(Range, "\"" + Filename.str() + "\""); } } // If the file is still not found, just go with the vanilla diagnostic if (!File) - Diag(FilenameTok, diag::err_pp_file_not_found) << Filename; + Diag(FilenameTok, diag::err_pp_file_not_found) << Filename + << FilenameRange; } } @@ -1671,34 +1838,24 @@ // we've imported or already built. bool ShouldEnter = true; + if (PPOpts->SingleFileParseMode) + ShouldEnter = false; + // Determine whether we should try to import the module for this #include, if // there is one. Don't do so if precompiled module support is disabled or we // are processing this module textually (because we're building the module). - if (File && SuggestedModule && getLangOpts().Modules && + if (ShouldEnter && File && SuggestedModule && getLangOpts().Modules && SuggestedModule.getModule()->getTopLevelModuleName() != - getLangOpts().CurrentModule && - SuggestedModule.getModule()->getTopLevelModuleName() != - getLangOpts().ImplementationOfModule) { - + getLangOpts().CurrentModule) { // If this include corresponds to a module but that module is // unavailable, diagnose the situation and bail out. - if (!SuggestedModule.getModule()->isAvailable()) { - clang::Module::Requirement Requirement; - clang::Module::UnresolvedHeaderDirective MissingHeader; - Module *M = SuggestedModule.getModule(); - // Identify the cause. - (void)M->isAvailable(getLangOpts(), getTargetInfo(), Requirement, - MissingHeader); - if (MissingHeader.FileNameLoc.isValid()) { - Diag(MissingHeader.FileNameLoc, diag::err_module_header_missing) - << MissingHeader.IsUmbrella << MissingHeader.FileName; - } else { - Diag(M->DefinitionLoc, diag::err_module_unavailable) - << M->getFullModuleName() << Requirement.second << Requirement.first; - } + // FIXME: Remove this; loadModule does the same check (but produces + // slightly worse diagnostics). + if (checkModuleIsAvailable(getLangOpts(), getTargetInfo(), getDiagnostics(), + SuggestedModule.getModule())) { Diag(FilenameTok.getLocation(), diag::note_implicit_top_level_module_import_here) - << M->getTopLevelModuleName(); + << SuggestedModule.getModule()->getTopLevelModuleName(); return; } @@ -1715,7 +1872,7 @@ // We only do this in Objective-C, where we have a module-import syntax. if (getLangOpts().ObjC2) diagnoseAutoModuleImport(*this, HashLoc, IncludeTok, Path, CharEnd); - + // Load the module to import its macros. We'll make the declarations // visible when the parser gets here. // FIXME: Pass SuggestedModule in here rather than converting it to a path @@ -1731,9 +1888,12 @@ else if (Imported.isMissingExpected()) { // We failed to find a submodule that we assumed would exist (because it // was in the directory of an umbrella header, for instance), but no - // actual module exists for it (because the umbrella header is + // actual module containing it exists (because the umbrella header is // incomplete). Treat this as a textual inclusion. SuggestedModule = ModuleMap::KnownHeader(); + } else if (Imported.isConfigMismatch()) { + // On a configuration mismatch, enter the header textually. We still know + // that it's part of the corresponding module. } else { // We hit an error processing the import. Bail out. if (hadModuleLoaderFatalFailure()) { @@ -1752,6 +1912,25 @@ } } + // The #included file will be considered to be a system header if either it is + // in a system include directory, or if the #includer is a system include + // header. + SrcMgr::CharacteristicKind FileCharacter = + SourceMgr.getFileCharacteristic(FilenameTok.getLocation()); + if (File) + FileCharacter = std::max(HeaderInfo.getFileDirFlavor(File), FileCharacter); + + // Ask HeaderInfo if we should enter this #include file. If not, #including + // this file will have no effect. + bool SkipHeader = false; + if (ShouldEnter && File && + !HeaderInfo.ShouldEnterIncludeFile(*this, File, isImport, + getLangOpts().Modules, + SuggestedModule.getModule())) { + ShouldEnter = false; + SkipHeader = true; + } + if (Callbacks) { // Notify the callback object that we've seen an inclusion directive. Callbacks->InclusionDirective( @@ -1759,40 +1938,70 @@ LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, isAngled, FilenameRange, File, SearchPath, RelativePath, ShouldEnter ? nullptr : SuggestedModule.getModule()); + if (SkipHeader && !SuggestedModule.getModule()) + Callbacks->FileSkipped(*File, FilenameTok, FileCharacter); } if (!File) return; - - // The #included file will be considered to be a system header if either it is - // in a system include directory, or if the #includer is a system include - // header. - SrcMgr::CharacteristicKind FileCharacter = - std::max(HeaderInfo.getFileDirFlavor(File), - SourceMgr.getFileCharacteristic(FilenameTok.getLocation())); // FIXME: If we have a suggested module, and we've already visited this file, // don't bother entering it again. We know it has no further effect. - // Ask HeaderInfo if we should enter this #include file. If not, #including - // this file will have no effect. - if (ShouldEnter && - !HeaderInfo.ShouldEnterIncludeFile(*this, File, isImport, - SuggestedModule.getModule())) { - ShouldEnter = false; - if (Callbacks) - Callbacks->FileSkipped(*File, FilenameTok, FileCharacter); + // Issue a diagnostic if the name of the file on disk has a different case + // than the one we're about to open. + const bool CheckIncludePathPortability = + !IsMapped && File && !File->tryGetRealPathName().empty(); + + if (CheckIncludePathPortability) { + StringRef Name = LangOpts.MSVCCompat ? NormalizedPath.str() : Filename; + StringRef RealPathName = File->tryGetRealPathName(); + SmallVector Components(llvm::sys::path::begin(Name), + llvm::sys::path::end(Name)); + + if (trySimplifyPath(Components, RealPathName)) { + SmallString<128> Path; + Path.reserve(Name.size()+2); + Path.push_back(isAngled ? '<' : '"'); + bool isLeadingSeparator = llvm::sys::path::is_absolute(Name); + for (auto Component : Components) { + if (isLeadingSeparator) + isLeadingSeparator = false; + else + Path.append(Component); + // Append the separator the user used, or the close quote + Path.push_back( + Path.size() <= Filename.size() ? Filename[Path.size()-1] : + (isAngled ? '>' : '"')); + } + // For user files and known standard headers, by default we issue a diagnostic. + // For other system headers, we don't. They can be controlled separately. + auto DiagId = (FileCharacter == SrcMgr::C_User || warnByDefaultOnWrongCase(Name)) ? + diag::pp_nonportable_path : diag::pp_nonportable_system_path; + SourceRange Range(FilenameTok.getLocation(), CharEnd); + Diag(FilenameTok, DiagId) << Path << + FixItHint::CreateReplacement(Range, Path); + } } // If we don't need to enter the file, stop now. if (!ShouldEnter) { // If this is a module import, make it visible if needed. if (auto *M = SuggestedModule.getModule()) { + // When building a pch, -fmodule-name tells the compiler to textually + // include headers in the specified module. But it is possible that + // ShouldEnter is false because we are skipping the header. In that + // case, We are not importing the specified module. + if (SkipHeader && getLangOpts().CompilingPCH && + M->getTopLevelModuleName() == getLangOpts().CurrentModule) + return; + makeModuleVisible(M, HashLoc); if (IncludeTok.getIdentifierInfo()->getPPKeywordID() != tok::pp___include_macros) - EnterAnnotationToken(*this, HashLoc, End, tok::annot_module_include, M); + EnterAnnotationToken(SourceRange(HashLoc, End), + tok::annot_module_include, M); } return; } @@ -1812,18 +2021,25 @@ // Determine if we're switching to building a new submodule, and which one. if (auto *M = SuggestedModule.getModule()) { - assert(!CurSubmodule && "should not have marked this as a module yet"); - CurSubmodule = M; + // When building a pch, -fmodule-name tells the compiler to textually + // include headers in the specified module. We are not building the + // specified module. + if (getLangOpts().CompilingPCH && + M->getTopLevelModuleName() == getLangOpts().CurrentModule) + return; + + assert(!CurLexerSubmodule && "should not have marked this as a module yet"); + CurLexerSubmodule = M; // Let the macro handling code know that any future macros are within // the new submodule. - EnterSubmodule(M, HashLoc); + EnterSubmodule(M, HashLoc, /*ForPragma*/false); // Let the parser know that any future declarations are within the new // submodule. // FIXME: There's no point doing this if we're handling a #__include_macros // directive. - EnterAnnotationToken(*this, HashLoc, End, tok::annot_module_begin, M); + EnterAnnotationToken(SourceRange(HashLoc, End), tok::annot_module_begin, M); } } @@ -1838,10 +2054,14 @@ // diagnostic. const DirectoryLookup *Lookup = CurDirLookup; const FileEntry *LookupFromFile = nullptr; - if (isInPrimaryFile()) { + if (isInPrimaryFile() && LangOpts.IsHeaderFile) { + // If the main file is a header, then it's either for PCH/AST generation, + // or libclang opened it. Either way, handle it as a normal include below + // and do not complain about include_next. + } else if (isInPrimaryFile()) { Lookup = nullptr; Diag(IncludeNextTok, diag::pp_include_next_in_primary); - } else if (CurSubmodule) { + } else if (CurLexerSubmodule) { // Start looking up in the directory *after* the one in which the current // file would be found, if any. assert(CurPPLexer && "#include_next directive in macro?"); @@ -1867,7 +2087,7 @@ // so we can continue processing from there. Diag(Tok, diag::err_pp_import_directive_ms ); - // Read tokens until we get to the end of the directive. Note that the + // Read tokens until we get to the end of the directive. Note that the // directive can be split over multiple lines using the backslash character. DiscardUntilEndOfDirective(); } @@ -1893,7 +2113,7 @@ // This directive should only occur in the predefines buffer. If not, emit an // error and reject it. SourceLocation Loc = IncludeMacrosTok.getLocation(); - if (strcmp(SourceMgr.getBufferName(Loc), "") != 0) { + if (SourceMgr.getBufferName(Loc) != "") { Diag(IncludeMacrosTok.getLocation(), diag::pp_include_macros_out_of_predefines); DiscardUntilEndOfDirective(); @@ -1915,26 +2135,26 @@ // Preprocessor Macro Directive Handling. //===----------------------------------------------------------------------===// -/// ReadMacroDefinitionArgList - The ( starting an argument list of a macro -/// definition has just been read. Lex the rest of the arguments and the +/// ReadMacroParameterList - The ( starting a parameter list of a macro +/// definition has just been read. Lex the rest of the parameters and the /// closing ), updating MI with what we learn. Return true if an error occurs -/// parsing the arg list. -bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI, Token &Tok) { - SmallVector Arguments; - - while (1) { +/// parsing the param list. +bool Preprocessor::ReadMacroParameterList(MacroInfo *MI, Token &Tok) { + SmallVector Parameters; + + while (true) { LexUnexpandedToken(Tok); switch (Tok.getKind()) { case tok::r_paren: - // Found the end of the argument list. - if (Arguments.empty()) // #define FOO() + // Found the end of the parameter list. + if (Parameters.empty()) // #define FOO() return false; // Otherwise we have #define FOO(A,) Diag(Tok, diag::err_pp_expected_ident_in_arg_list); return true; case tok::ellipsis: // #define X(... -> C99 varargs if (!LangOpts.C99) - Diag(Tok, LangOpts.CPlusPlus11 ? + Diag(Tok, LangOpts.CPlusPlus11 ? diag::warn_cxx98_compat_variadic_macro : diag::ext_variadic_macro); @@ -1950,10 +2170,10 @@ Diag(Tok, diag::err_pp_missing_rparen_in_macro_def); return true; } - // Add the __VA_ARGS__ identifier as an argument. - Arguments.push_back(Ident__VA_ARGS__); + // Add the __VA_ARGS__ identifier as a parameter. + Parameters.push_back(Ident__VA_ARGS__); MI->setIsC99Varargs(); - MI->setArgumentList(Arguments, BP); + MI->setParameterList(Parameters, BP); return false; case tok::eod: // #define X( Diag(Tok, diag::err_pp_missing_rparen_in_macro_def); @@ -1968,16 +2188,16 @@ return true; } - // If this is already used as an argument, it is used multiple times (e.g. + // If this is already used as a parameter, it is used multiple times (e.g. // #define X(A,A. - if (std::find(Arguments.begin(), Arguments.end(), II) != - Arguments.end()) { // C99 6.10.3p6 + if (std::find(Parameters.begin(), Parameters.end(), II) != + Parameters.end()) { // C99 6.10.3p6 Diag(Tok, diag::err_pp_duplicate_name_in_arg_list) << II; return true; } - // Add the argument to the macro info. - Arguments.push_back(II); + // Add the parameter to the macro info. + Parameters.push_back(II); // Lex the token after the identifier. LexUnexpandedToken(Tok); @@ -1987,7 +2207,7 @@ Diag(Tok, diag::err_pp_expected_comma_in_arg_list); return true; case tok::r_paren: // #define X(A) - MI->setArgumentList(Arguments, BP); + MI->setParameterList(Parameters, BP); return false; case tok::comma: // #define X(A, break; @@ -2003,7 +2223,7 @@ } MI->setIsGNUVarargs(); - MI->setArgumentList(Arguments, BP); + MI->setParameterList(Parameters, BP); return false; } } @@ -2052,32 +2272,28 @@ MI->getNumTokens() == 0; } -/// HandleDefineDirective - Implements \#define. This consumes the entire macro -/// line then lets the caller lex the next real token. -void Preprocessor::HandleDefineDirective(Token &DefineTok, - bool ImmediatelyAfterHeaderGuard) { - ++NumDefined; - - Token MacroNameTok; - bool MacroShadowsKeyword; - ReadMacroName(MacroNameTok, MU_Define, &MacroShadowsKeyword); - - // Error reading macro name? If so, diagnostic already issued. - if (MacroNameTok.is(tok::eod)) - return; +// ReadOptionalMacroParameterListAndBody - This consumes all (i.e. the +// entire line) of the macro's tokens and adds them to MacroInfo, and while +// doing so performs certain validity checks including (but not limited to): +// - # (stringization) is followed by a macro parameter +// +// Returns a nullptr if an invalid sequence of tokens is encountered or returns +// a pointer to a MacroInfo object. + +MacroInfo *Preprocessor::ReadOptionalMacroParameterListAndBody( + const Token &MacroNameTok, const bool ImmediatelyAfterHeaderGuard) { Token LastTok = MacroNameTok; - - // If we are supposed to keep comments in #defines, reenable comment saving - // mode. - if (CurLexer) CurLexer->SetCommentRetentionState(KeepMacroComments); - // Create the new macro. - MacroInfo *MI = AllocateMacroInfo(MacroNameTok.getLocation()); + MacroInfo *const MI = AllocateMacroInfo(MacroNameTok.getLocation()); Token Tok; LexUnexpandedToken(Tok); + // Used to un-poison and then re-poison identifiers of the __VA_ARGS__ ilk + // within their appropriate context. + VariadicMacroScopeGuard VariadicMacroScopeGuard(*this); + // If this is a function-like macro definition, parse the argument list, // marking each of the identifiers as being used as macro arguments. Also, // check other constraints on the first token of the macro body. @@ -2095,21 +2311,21 @@ } else if (Tok.is(tok::l_paren)) { // This is a function-like macro definition. Read the argument list. MI->setIsFunctionLike(); - if (ReadMacroDefinitionArgList(MI, LastTok)) { + if (ReadMacroParameterList(MI, LastTok)) { // Throw away the rest of the line. if (CurPPLexer->ParsingPreprocessorDirective) DiscardUntilEndOfDirective(); - return; + return nullptr; } - // If this is a definition of a variadic C99 function-like macro, not using - // the GNU named varargs extension, enabled __VA_ARGS__. - - // "Poison" __VA_ARGS__, which can only appear in the expansion of a macro. - // This gets unpoisoned where it is allowed. - assert(Ident__VA_ARGS__->isPoisoned() && "__VA_ARGS__ should be poisoned!"); - if (MI->isC99Varargs()) - Ident__VA_ARGS__->setIsPoisoned(false); + // If this is a definition of an ISO C/C++ variadic function-like macro (not + // using the GNU named varargs extension) inform our variadic scope guard + // which un-poisons and re-poisons certain identifiers (e.g. __VA_ARGS__) + // allowed only within the definition of a variadic macro. + + if (MI->isC99Varargs()) { + VariadicMacroScopeGuard.enterScope(); + } // Read the first token after the arg list for down below. LexUnexpandedToken(Tok); @@ -2151,17 +2367,54 @@ // Get the next token of the macro. LexUnexpandedToken(Tok); } - } else { // Otherwise, read the body of a function-like macro. While we are at it, // check C99 6.10.3.2p1: ensure that # operators are followed by macro // parameters in function-like macro expansions. + + VAOptDefinitionContext VAOCtx(*this); + while (Tok.isNot(tok::eod)) { LastTok = Tok; - if (Tok.isNot(tok::hash) && Tok.isNot(tok::hashhash)) { + if (!Tok.isOneOf(tok::hash, tok::hashat, tok::hashhash)) { MI->AddTokenToBody(Tok); + if (VAOCtx.isVAOptToken(Tok)) { + // If we're already within a VAOPT, emit an error. + if (VAOCtx.isInVAOpt()) { + Diag(Tok, diag::err_pp_vaopt_nested_use); + return nullptr; + } + // Ensure VAOPT is followed by a '(' . + LexUnexpandedToken(Tok); + if (Tok.isNot(tok::l_paren)) { + Diag(Tok, diag::err_pp_missing_lparen_in_vaopt_use); + return nullptr; + } + MI->AddTokenToBody(Tok); + VAOCtx.sawVAOptFollowedByOpeningParens(Tok.getLocation()); + LexUnexpandedToken(Tok); + if (Tok.is(tok::hashhash)) { + Diag(Tok, diag::err_vaopt_paste_at_start); + return nullptr; + } + continue; + } else if (VAOCtx.isInVAOpt()) { + if (Tok.is(tok::r_paren)) { + if (VAOCtx.sawClosingParen()) { + const unsigned NumTokens = MI->getNumTokens(); + assert(NumTokens >= 3 && "Must have seen at least __VA_OPT__( " + "and a subsequent tok::r_paren"); + if (MI->getReplacementToken(NumTokens - 2).is(tok::hashhash)) { + Diag(Tok, diag::err_vaopt_paste_at_end); + return nullptr; + } + } + } else if (Tok.is(tok::l_paren)) { + VAOCtx.sawOpeningParen(Tok.getLocation()); + } + } // Get the next token of the macro. LexUnexpandedToken(Tok); continue; @@ -2180,11 +2433,10 @@ } if (Tok.is(tok::hashhash)) { - // If we see token pasting, check if it looks like the gcc comma // pasting extension. We'll use this information to suppress // diagnostics later on. - + // Get the next token of the macro. LexUnexpandedToken(Tok); @@ -2203,12 +2455,14 @@ continue; } + // Our Token is a stringization operator. // Get the next token of the macro. LexUnexpandedToken(Tok); - // Check for a valid macro arg identifier. - if (Tok.getIdentifierInfo() == nullptr || - MI->getArgumentNum(Tok.getIdentifierInfo()) == -1) { + // Check for a valid macro arg identifier or __VA_OPT__. + if (!VAOCtx.isVAOptToken(Tok) && + (Tok.getIdentifierInfo() == nullptr || + MI->getParameterNum(Tok.getIdentifierInfo()) == -1)) { // If this is assembler-with-cpp mode, we accept random gibberish after // the '#' because '#' is often a comment character. However, change @@ -2219,32 +2473,64 @@ MI->AddTokenToBody(LastTok); continue; } else { - Diag(Tok, diag::err_pp_stringize_not_parameter); - - // Disable __VA_ARGS__ again. - Ident__VA_ARGS__->setIsPoisoned(true); - return; + Diag(Tok, diag::err_pp_stringize_not_parameter) + << LastTok.is(tok::hashat); + return nullptr; } } // Things look ok, add the '#' and param name tokens to the macro. MI->AddTokenToBody(LastTok); - MI->AddTokenToBody(Tok); - LastTok = Tok; - - // Get the next token of the macro. - LexUnexpandedToken(Tok); + + // If the token following '#' is VAOPT, let the next iteration handle it + // and check it for correctness, otherwise add the token and prime the + // loop with the next one. + if (!VAOCtx.isVAOptToken(Tok)) { + MI->AddTokenToBody(Tok); + LastTok = Tok; + + // Get the next token of the macro. + LexUnexpandedToken(Tok); + } + } + if (VAOCtx.isInVAOpt()) { + assert(Tok.is(tok::eod) && "Must be at End Of preprocessing Directive"); + Diag(Tok, diag::err_pp_expected_after) + << LastTok.getKind() << tok::r_paren; + Diag(VAOCtx.getUnmatchedOpeningParenLoc(), diag::note_matching) << tok::l_paren; + return nullptr; } } + MI->setDefinitionEndLoc(LastTok.getLocation()); + return MI; +} +/// HandleDefineDirective - Implements \#define. This consumes the entire macro +/// line then lets the caller lex the next real token. +void Preprocessor::HandleDefineDirective( + Token &DefineTok, const bool ImmediatelyAfterHeaderGuard) { + ++NumDefined; + + Token MacroNameTok; + bool MacroShadowsKeyword; + ReadMacroName(MacroNameTok, MU_Define, &MacroShadowsKeyword); + + // Error reading macro name? If so, diagnostic already issued. + if (MacroNameTok.is(tok::eod)) + return; + + // If we are supposed to keep comments in #defines, reenable comment saving + // mode. + if (CurLexer) CurLexer->SetCommentRetentionState(KeepMacroComments); + + MacroInfo *const MI = ReadOptionalMacroParameterListAndBody( + MacroNameTok, ImmediatelyAfterHeaderGuard); + + if (!MI) return; if (MacroShadowsKeyword && !isConfigurationPattern(MacroNameTok, MI, getLangOpts())) { Diag(MacroNameTok, diag::warn_pp_macro_hides_keyword); - } - - // Disable __VA_ARGS__ again. - Ident__VA_ARGS__->setIsPoisoned(true); - + } // Check that there is no paste (##) operator at the beginning or end of the // replacement list. unsigned NumTokens = MI->getNumTokens(); @@ -2259,7 +2545,7 @@ } } - MI->setDefinitionEndLoc(LastTok.getLocation()); + // Finally, if this identifier already had a macro defined for it, verify that // the macro bodies are identical, and issue diagnostics if they are not. @@ -2296,7 +2582,7 @@ if (!OtherMI->isUsed() && OtherMI->isWarnIfUnused()) Diag(OtherMI->getDefinitionLoc(), diag::pp_macro_not_used); - // Warn if defining "__LINE__" and other builtins, per C99 6.10.8/4 and + // Warn if defining "__LINE__" and other builtins, per C99 6.10.8/4 and // C++ [cpp.predefined]p4, but allow it as an extension. if (OtherMI->isBuiltinMacro()) Diag(MacroNameTok, diag::ext_pp_redef_builtin_macro); @@ -2332,7 +2618,7 @@ /// HandleUndefDirective - Implements \#undef. /// -void Preprocessor::HandleUndefDirective(Token &UndefTok) { +void Preprocessor::HandleUndefDirective() { ++NumUndefined; Token MacroNameTok; @@ -2348,28 +2634,28 @@ // Okay, we have a valid identifier to undef. auto *II = MacroNameTok.getIdentifierInfo(); auto MD = getMacroDefinition(II); + UndefMacroDirective *Undef = nullptr; + + // If the macro is not defined, this is a noop undef. + if (const MacroInfo *MI = MD.getMacroInfo()) { + if (!MI->isUsed() && MI->isWarnIfUnused()) + Diag(MI->getDefinitionLoc(), diag::pp_macro_not_used); + + if (MI->isWarnIfUnused()) + WarnUnusedMacroLocs.erase(MI->getDefinitionLoc()); + + Undef = AllocateUndefMacroDirective(MacroNameTok.getLocation()); + } // If the callbacks want to know, tell them about the macro #undef. // Note: no matter if the macro was defined or not. if (Callbacks) - Callbacks->MacroUndefined(MacroNameTok, MD); - - // If the macro is not defined, this is a noop undef, just return. - const MacroInfo *MI = MD.getMacroInfo(); - if (!MI) - return; - - if (!MI->isUsed() && MI->isWarnIfUnused()) - Diag(MI->getDefinitionLoc(), diag::pp_macro_not_used); - - if (MI->isWarnIfUnused()) - WarnUnusedMacroLocs.erase(MI->getDefinitionLoc()); - - appendMacroDirective(MacroNameTok.getIdentifierInfo(), - AllocateUndefMacroDirective(MacroNameTok.getLocation())); + Callbacks->MacroUndefined(MacroNameTok, MD, Undef); + + if (Undef) + appendMacroDirective(II, Undef); } - //===----------------------------------------------------------------------===// // Preprocessor Conditional Directive Handling. //===----------------------------------------------------------------------===// @@ -2379,7 +2665,9 @@ /// true if any tokens have been returned or pp-directives activated before this /// \#ifndef has been lexed. /// -void Preprocessor::HandleIfdefDirective(Token &Result, bool isIfndef, +void Preprocessor::HandleIfdefDirective(Token &Result, + const Token &HashToken, + bool isIfndef, bool ReadAnyTokensBeforeDirective) { ++NumIf; Token DirectiveTok = Result; @@ -2391,8 +2679,8 @@ if (MacroNameTok.is(tok::eod)) { // Skip code until we get to #endif. This helps with recovery by not // emitting an error when the #endif is reached. - SkipExcludedConditionalBlock(DirectiveTok.getLocation(), - /*Foundnonskip*/false, /*FoundElse*/false); + SkipExcludedConditionalBlock(HashToken, DirectiveTok.getLocation(), + /*Foundnonskip*/ false, /*FoundElse*/ false); return; } @@ -2427,29 +2715,37 @@ } // Should we include the stuff contained by this directive? - if (!MI == isIfndef) { + if (PPOpts->SingleFileParseMode && !MI) { + // In 'single-file-parse mode' undefined identifiers trigger parsing of all + // the directive blocks. + CurPPLexer->pushConditionalLevel(DirectiveTok.getLocation(), + /*wasskip*/false, /*foundnonskip*/false, + /*foundelse*/false); + } else if (!MI == isIfndef) { // Yes, remember that we are inside a conditional, then lex the next token. CurPPLexer->pushConditionalLevel(DirectiveTok.getLocation(), /*wasskip*/false, /*foundnonskip*/true, /*foundelse*/false); } else { // No, skip the contents of this block. - SkipExcludedConditionalBlock(DirectiveTok.getLocation(), - /*Foundnonskip*/false, - /*FoundElse*/false); + SkipExcludedConditionalBlock(HashToken, DirectiveTok.getLocation(), + /*Foundnonskip*/ false, + /*FoundElse*/ false); } } /// HandleIfDirective - Implements the \#if directive. /// void Preprocessor::HandleIfDirective(Token &IfToken, + const Token &HashToken, bool ReadAnyTokensBeforeDirective) { ++NumIf; // Parse and evaluate the conditional expression. IdentifierInfo *IfNDefMacro = nullptr; const SourceLocation ConditionalBegin = CurPPLexer->getSourceLocation(); - const bool ConditionalTrue = EvaluateDirectiveExpression(IfNDefMacro); + const DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro); + const bool ConditionalTrue = DER.Conditional; const SourceLocation ConditionalEnd = CurPPLexer->getSourceLocation(); // If this condition is equivalent to #ifndef X, and if this is the first @@ -2468,14 +2764,20 @@ (ConditionalTrue ? PPCallbacks::CVK_True : PPCallbacks::CVK_False)); // Should we include the stuff contained by this directive? - if (ConditionalTrue) { + if (PPOpts->SingleFileParseMode && DER.IncludedUndefinedIds) { + // In 'single-file-parse mode' undefined identifiers trigger parsing of all + // the directive blocks. + CurPPLexer->pushConditionalLevel(IfToken.getLocation(), /*wasskip*/false, + /*foundnonskip*/false, /*foundelse*/false); + } else if (ConditionalTrue) { // Yes, remember that we are inside a conditional, then lex the next token. CurPPLexer->pushConditionalLevel(IfToken.getLocation(), /*wasskip*/false, /*foundnonskip*/true, /*foundelse*/false); } else { // No, skip the contents of this block. - SkipExcludedConditionalBlock(IfToken.getLocation(), /*Foundnonskip*/false, - /*FoundElse*/false); + SkipExcludedConditionalBlock(HashToken, IfToken.getLocation(), + /*Foundnonskip*/ false, + /*FoundElse*/ false); } } @@ -2507,7 +2809,7 @@ /// HandleElseDirective - Implements the \#else directive. /// -void Preprocessor::HandleElseDirective(Token &Result) { +void Preprocessor::HandleElseDirective(Token &Result, const Token &HashToken) { ++NumElse; // #else directive in a non-skipping conditional... start skipping. @@ -2529,14 +2831,23 @@ if (Callbacks) Callbacks->Else(Result.getLocation(), CI.IfLoc); + if (PPOpts->SingleFileParseMode && !CI.FoundNonSkip) { + // In 'single-file-parse mode' undefined identifiers trigger parsing of all + // the directive blocks. + CurPPLexer->pushConditionalLevel(CI.IfLoc, /*wasskip*/false, + /*foundnonskip*/false, /*foundelse*/true); + return; + } + // Finally, skip the rest of the contents of this block. - SkipExcludedConditionalBlock(CI.IfLoc, /*Foundnonskip*/true, - /*FoundElse*/true, Result.getLocation()); + SkipExcludedConditionalBlock(HashToken, CI.IfLoc, /*Foundnonskip*/ true, + /*FoundElse*/ true, Result.getLocation()); } /// HandleElifDirective - Implements the \#elif directive. /// -void Preprocessor::HandleElifDirective(Token &ElifToken) { +void Preprocessor::HandleElifDirective(Token &ElifToken, + const Token &HashToken) { ++NumElse; // #elif directive in a non-skipping conditional... start skipping. @@ -2558,17 +2869,26 @@ // If this is a #elif with a #else before it, report the error. if (CI.FoundElse) Diag(ElifToken, diag::pp_err_elif_after_else); - + if (Callbacks) Callbacks->Elif(ElifToken.getLocation(), SourceRange(ConditionalBegin, ConditionalEnd), PPCallbacks::CVK_NotEvaluated, CI.IfLoc); + if (PPOpts->SingleFileParseMode && !CI.FoundNonSkip) { + // In 'single-file-parse mode' undefined identifiers trigger parsing of all + // the directive blocks. + CurPPLexer->pushConditionalLevel(ElifToken.getLocation(), /*wasskip*/false, + /*foundnonskip*/false, /*foundelse*/false); + return; + } + // Finally, skip the rest of the contents of this block. - SkipExcludedConditionalBlock(CI.IfLoc, /*Foundnonskip*/true, - /*FoundElse*/CI.FoundElse, + SkipExcludedConditionalBlock(HashToken, CI.IfLoc, /*Foundnonskip*/ true, + /*FoundElse*/ CI.FoundElse, ElifToken.getLocation()); } + #ifndef noCbC /// IncludeHeader - Include a header file. /// Current Token is saved for returning current file because it has been already lexed from buffer of input file. diff -r 56c5119fbcd2 -r c4cc77a799c9 tools/clang/lib/Lex/PPLexerChange.cpp --- a/tools/clang/lib/Lex/PPLexerChange.cpp Sun Dec 03 20:09:16 2017 +0900 +++ b/tools/clang/lib/Lex/PPLexerChange.cpp Mon Dec 04 21:20:52 2017 +0900 @@ -40,10 +40,9 @@ // If there are any stacked lexers, we're in a #include. assert(IsFileLexer(IncludeMacroStack[0]) && "Top level include stack isn't our primary lexer?"); - for (unsigned i = 1, e = IncludeMacroStack.size(); i != e; ++i) - if (IsFileLexer(IncludeMacroStack[i])) - return false; - return true; + return std::none_of( + IncludeMacroStack.begin() + 1, IncludeMacroStack.end(), + [&](const IncludeStackInfo &ISI) -> bool { return IsFileLexer(ISI); }); } /// getCurrentLexer - Return the current file lexer being lexed from. Note @@ -54,8 +53,7 @@ return CurPPLexer; // Look for a stacked lexer. - for (unsigned i = IncludeMacroStack.size(); i != 0; --i) { - const IncludeStackInfo& ISI = IncludeMacroStack[i-1]; + for (const IncludeStackInfo &ISI : llvm::reverse(IncludeMacroStack)) { if (IsFileLexer(ISI)) return ISI.ThePPLexer; } @@ -118,7 +116,7 @@ CurLexer.reset(TheLexer); CurPPLexer = TheLexer; CurDirLookup = CurDir; - CurSubmodule = nullptr; + CurLexerSubmodule = nullptr; if (CurLexerKind != CLK_LexAfterModuleImport) CurLexerKind = CLK_Lexer; @@ -143,7 +141,7 @@ CurDirLookup = CurDir; CurPTHLexer.reset(PL); CurPPLexer = CurPTHLexer.get(); - CurSubmodule = nullptr; + CurLexerSubmodule = nullptr; if (CurLexerKind != CLK_LexAfterModuleImport) CurLexerKind = CLK_PTHLexer; @@ -288,6 +286,48 @@ return EndPos; } +static void collectAllSubModulesWithUmbrellaHeader( + const Module &Mod, SmallVectorImpl &SubMods) { + if (Mod.getUmbrellaHeader()) + SubMods.push_back(&Mod); + for (auto *M : Mod.submodules()) + collectAllSubModulesWithUmbrellaHeader(*M, SubMods); +} + +void Preprocessor::diagnoseMissingHeaderInUmbrellaDir(const Module &Mod) { + assert(Mod.getUmbrellaHeader() && "Module must use umbrella header"); + SourceLocation StartLoc = + SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()); + if (getDiagnostics().isIgnored(diag::warn_uncovered_module_header, StartLoc)) + return; + + ModuleMap &ModMap = getHeaderSearchInfo().getModuleMap(); + const DirectoryEntry *Dir = Mod.getUmbrellaDir().Entry; + vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem(); + std::error_code EC; + for (vfs::recursive_directory_iterator Entry(FS, Dir->getName(), EC), End; + Entry != End && !EC; Entry.increment(EC)) { + using llvm::StringSwitch; + + // Check whether this entry has an extension typically associated with + // headers. + if (!StringSwitch(llvm::sys::path::extension(Entry->getName())) + .Cases(".h", ".H", ".hh", ".hpp", true) + .Default(false)) + continue; + + if (const FileEntry *Header = getFileManager().getFile(Entry->getName())) + if (!getSourceManager().hasFileInfo(Header)) { + if (!ModMap.isHeaderInUnavailableModule(Header)) { + // Find the relative path that would access this header. + SmallString<128> RelativePath; + computeRelativePath(FileMgr, Dir, Header, RelativePath); + Diag(StartLoc, diag::warn_uncovered_module_header) + << Mod.getFullModuleName() << RelativePath; + } + } + } +} /// HandleEndOfFile - This callback is invoked when the lexer hits the end of /// the current file. This either returns the EOF token or pops a level off @@ -296,6 +336,26 @@ assert(!CurTokenLexer && "Ending a file when currently in a macro!"); + // If we have an unclosed module region from a pragma at the end of a + // module, complain and close it now. + // FIXME: This is not correct if we are building a module from PTH. + const bool LeavingSubmodule = CurLexer && CurLexerSubmodule; + if ((LeavingSubmodule || IncludeMacroStack.empty()) && + !BuildingSubmoduleStack.empty() && + BuildingSubmoduleStack.back().IsPragma) { + Diag(BuildingSubmoduleStack.back().ImportLoc, + diag::err_pp_module_begin_without_module_end); + Module *M = LeaveSubmodule(/*ForPragma*/true); + + Result.startToken(); + const char *EndPos = getCurLexerEndPos(); + CurLexer->BufferPtr = EndPos; + CurLexer->FormTokenWithChars(Result, EndPos, tok::annot_module_end); + Result.setAnnotationEndLoc(Result.getLocation()); + Result.setAnnotationValue(M); + return true; + } + // See if this file had a controlling macro. if (CurPPLexer) { // Not ending a macro, ignore it. if (const IdentifierInfo *ControllingMacro = @@ -304,9 +364,8 @@ if (const FileEntry *FE = CurPPLexer->getFileEntry()) { HeaderInfo.SetFileControllingMacro(FE, ControllingMacro); if (MacroInfo *MI = - getMacroInfo(const_cast(ControllingMacro))) { - MI->UsedForHeaderGuard = true; - } + getMacroInfo(const_cast(ControllingMacro))) + MI->setUsedForHeaderGuard(true); if (const IdentifierInfo *DefinedMacro = CurPPLexer->MIOpt.GetDefinedMacro()) { if (!isMacroDefined(ControllingMacro) && @@ -398,26 +457,32 @@ SourceMgr.setNumCreatedFIDsForFileID(CurPPLexer->getFileID(), NumFIDs); } + bool ExitedFromPredefinesFile = false; FileID ExitedFID; - if (Callbacks && !isEndOfMacro && CurPPLexer) + if (!isEndOfMacro && CurPPLexer) { ExitedFID = CurPPLexer->getFileID(); - bool LeavingSubmodule = CurSubmodule && CurLexer; + assert(PredefinesFileID.isValid() && + "HandleEndOfFile is called before PredefinesFileId is set"); + ExitedFromPredefinesFile = (PredefinesFileID == ExitedFID); + } + if (LeavingSubmodule) { + // We're done with this submodule. + Module *M = LeaveSubmodule(/*ForPragma*/false); + // Notify the parser that we've left the module. const char *EndPos = getCurLexerEndPos(); Result.startToken(); CurLexer->BufferPtr = EndPos; CurLexer->FormTokenWithChars(Result, EndPos, tok::annot_module_end); Result.setAnnotationEndLoc(Result.getLocation()); - Result.setAnnotationValue(CurSubmodule); - - // We're done with this submodule. - LeaveSubmodule(); + Result.setAnnotationValue(M); } // We're done with the #included file. RemoveTopOfLexerStack(); + // Propagate info about start-of-line/leading white-space/etc. PropagateLineStartLeadingSpaceInfo(Result); @@ -428,6 +493,7 @@ Callbacks->FileChanged(CurPPLexer->getSourceLocation(), PPCallbacks::ExitFile, FileType, ExitedFID); } + #ifndef noCbC if (SavedTokenFlag && IncludeMacroStack.size() == SavedDepth){ Result = SavedToken; @@ -445,7 +511,13 @@ } return true; } -#endif +#endif + + // Restore conditional stack from the preamble right after exiting from the + // predefines file. + if (ExitedFromPredefinesFile) + replayPreambleConditionalStack(); + // Client should lex another token unless we generated an EOM. return LeavingSubmodule; } @@ -491,44 +563,14 @@ } // If we are building a module that has an umbrella header, make sure that - // each of the headers within the directory covered by the umbrella header - // was actually included by the umbrella header. + // each of the headers within the directory, including all submodules, is + // covered by the umbrella header was actually included by the umbrella + // header. if (Module *Mod = getCurrentModule()) { - if (Mod->getUmbrellaHeader()) { - SourceLocation StartLoc - = SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()); - - if (!getDiagnostics().isIgnored(diag::warn_uncovered_module_header, - StartLoc)) { - ModuleMap &ModMap = getHeaderSearchInfo().getModuleMap(); - const DirectoryEntry *Dir = Mod->getUmbrellaDir().Entry; - vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem(); - std::error_code EC; - for (vfs::recursive_directory_iterator Entry(FS, Dir->getName(), EC), End; - Entry != End && !EC; Entry.increment(EC)) { - using llvm::StringSwitch; - - // Check whether this entry has an extension typically associated with - // headers. - if (!StringSwitch(llvm::sys::path::extension(Entry->getName())) - .Cases(".h", ".H", ".hh", ".hpp", true) - .Default(false)) - continue; - - if (const FileEntry *Header = - getFileManager().getFile(Entry->getName())) - if (!getSourceManager().hasFileInfo(Header)) { - if (!ModMap.isHeaderInUnavailableModule(Header)) { - // Find the relative path that would access this header. - SmallString<128> RelativePath; - computeRelativePath(FileMgr, Dir, Header, RelativePath); - Diag(StartLoc, diag::warn_uncovered_module_header) - << Mod->getFullModuleName() << RelativePath; - } - } - } - } - } + llvm::SmallVector AllMods; + collectAllSubModulesWithUmbrellaHeader(*Mod, AllMods); + for (auto *M : AllMods) + diagnoseMissingHeaderInUmbrellaDir(*M); } return true; @@ -582,8 +624,7 @@ // explicit EOD token. PreprocessorLexer *FoundLexer = nullptr; bool LexerWasInPPMode = false; - for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) { - IncludeStackInfo &ISI = *(IncludeMacroStack.end()-i-1); + for (const IncludeStackInfo &ISI : llvm::reverse(IncludeMacroStack)) { if (ISI.ThePPLexer == nullptr) continue; // Scan for a real lexer. // Once we find a real lexer, mark it as raw mode (disabling macro @@ -635,11 +676,13 @@ assert(!FoundLexer && "Lexer should return EOD before EOF in PP mode"); } -void Preprocessor::EnterSubmodule(Module *M, SourceLocation ImportLoc) { +void Preprocessor::EnterSubmodule(Module *M, SourceLocation ImportLoc, + bool ForPragma) { if (!getLangOpts().ModulesLocalVisibility) { // Just track that we entered this submodule. BuildingSubmoduleStack.push_back( - BuildingSubmoduleInfo(M, ImportLoc, CurSubmoduleState)); + BuildingSubmoduleInfo(M, ImportLoc, ForPragma, CurSubmoduleState, + PendingModuleMacroNames.size())); return; } @@ -681,7 +724,8 @@ // Track that we entered this module. BuildingSubmoduleStack.push_back( - BuildingSubmoduleInfo(M, ImportLoc, CurSubmoduleState)); + BuildingSubmoduleInfo(M, ImportLoc, ForPragma, CurSubmoduleState, + PendingModuleMacroNames.size())); // Switch to this submodule as the current submodule. CurSubmoduleState = &State; @@ -691,45 +735,77 @@ makeModuleVisible(M, ImportLoc); } -void Preprocessor::LeaveSubmodule() { +bool Preprocessor::needModuleMacros() const { + // If we're not within a submodule, we never need to create ModuleMacros. + if (BuildingSubmoduleStack.empty()) + return false; + // If we are tracking module macro visibility even for textually-included + // headers, we need ModuleMacros. + if (getLangOpts().ModulesLocalVisibility) + return true; + // Otherwise, we only need module macros if we're actually compiling a module + // interface. + return getLangOpts().isCompilingModule(); +} + +Module *Preprocessor::LeaveSubmodule(bool ForPragma) { + if (BuildingSubmoduleStack.empty() || + BuildingSubmoduleStack.back().IsPragma != ForPragma) { + assert(ForPragma && "non-pragma module enter/leave mismatch"); + return nullptr; + } + auto &Info = BuildingSubmoduleStack.back(); Module *LeavingMod = Info.M; SourceLocation ImportLoc = Info.ImportLoc; + if (!needModuleMacros() || + (!getLangOpts().ModulesLocalVisibility && + LeavingMod->getTopLevelModuleName() != getLangOpts().CurrentModule)) { + // If we don't need module macros, or this is not a module for which we + // are tracking macro visibility, don't build any, and preserve the list + // of pending names for the surrounding submodule. + BuildingSubmoduleStack.pop_back(); + makeModuleVisible(LeavingMod, ImportLoc); + return LeavingMod; + } + // Create ModuleMacros for any macros defined in this submodule. - for (auto &Macro : CurSubmoduleState->Macros) { - auto *II = const_cast(Macro.first); + llvm::SmallPtrSet VisitedMacros; + for (unsigned I = Info.OuterPendingModuleMacroNames; + I != PendingModuleMacroNames.size(); ++I) { + auto *II = const_cast(PendingModuleMacroNames[I]); + if (!VisitedMacros.insert(II).second) + continue; + + auto MacroIt = CurSubmoduleState->Macros.find(II); + if (MacroIt == CurSubmoduleState->Macros.end()) + continue; + auto &Macro = MacroIt->second; // Find the starting point for the MacroDirective chain in this submodule. MacroDirective *OldMD = nullptr; - if (getLangOpts().ModulesLocalVisibility) { + auto *OldState = Info.OuterSubmoduleState; + if (getLangOpts().ModulesLocalVisibility) + OldState = &NullSubmoduleState; + if (OldState && OldState != CurSubmoduleState) { // FIXME: It'd be better to start at the state from when we most recently // entered this submodule, but it doesn't really matter. - auto &PredefMacros = NullSubmoduleState.Macros; - auto PredefMacroIt = PredefMacros.find(Macro.first); - if (PredefMacroIt == PredefMacros.end()) + auto &OldMacros = OldState->Macros; + auto OldMacroIt = OldMacros.find(II); + if (OldMacroIt == OldMacros.end()) OldMD = nullptr; else - OldMD = PredefMacroIt->second.getLatest(); + OldMD = OldMacroIt->second.getLatest(); } // This module may have exported a new macro. If so, create a ModuleMacro // representing that fact. bool ExplicitlyPublic = false; - for (auto *MD = Macro.second.getLatest(); MD != OldMD; - MD = MD->getPrevious()) { + for (auto *MD = Macro.getLatest(); MD != OldMD; MD = MD->getPrevious()) { assert(MD && "broken macro directive chain"); - // Stop on macros defined in other submodules we #included along the way. - // There's no point doing this if we're tracking local submodule - // visibility, since there can be no such directives in our list. - if (!getLangOpts().ModulesLocalVisibility) { - Module *Mod = getModuleContainingLocation(MD->getLocation()); - if (Mod != LeavingMod) - break; - } - if (auto *VisMD = dyn_cast(MD)) { // The latest visibility directive for a name in a submodule affects // all the directives that come before it. @@ -748,13 +824,21 @@ bool IsNew; // Don't bother creating a module macro if it would represent a #undef // that doesn't override anything. - if (Def || !Macro.second.getOverriddenMacros().empty()) + if (Def || !Macro.getOverriddenMacros().empty()) addModuleMacro(LeavingMod, II, Def, - Macro.second.getOverriddenMacros(), IsNew); + Macro.getOverriddenMacros(), IsNew); + + if (!getLangOpts().ModulesLocalVisibility) { + // This macro is exposed to the rest of this compilation as a + // ModuleMacro; we don't need to track its MacroDirective any more. + Macro.setLatest(nullptr); + Macro.setOverriddenMacros(*this, {}); + } break; } } } + PendingModuleMacroNames.resize(Info.OuterPendingModuleMacroNames); // FIXME: Before we leave this submodule, we should parse all the other // headers within it. Otherwise, we're left with an inconsistent state @@ -769,4 +853,5 @@ // A nested #include makes the included submodule visible. makeModuleVisible(LeavingMod, ImportLoc); + return LeavingMod; } diff -r 56c5119fbcd2 -r c4cc77a799c9 tools/clang/lib/Lex/Preprocessor.cpp --- a/tools/clang/lib/Lex/Preprocessor.cpp Sun Dec 03 20:09:16 2017 +0900 +++ b/tools/clang/lib/Lex/Preprocessor.cpp Mon Dec 04 21:20:52 2017 +0900 @@ -43,39 +43,52 @@ #include "clang/Lex/PreprocessingRecord.h" #include "clang/Lex/PreprocessorOptions.h" #include "clang/Lex/ScratchBuffer.h" -#include "llvm/ADT/APFloat.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Capacity.h" -#include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" +#include +#include +#include +#include +#include +#include + using namespace clang; +LLVM_INSTANTIATE_REGISTRY(PragmaHandlerRegistry) + //===----------------------------------------------------------------------===// ExternalPreprocessorSource::~ExternalPreprocessorSource() { } -Preprocessor::Preprocessor(IntrusiveRefCntPtr PPOpts, +Preprocessor::Preprocessor(std::shared_ptr PPOpts, DiagnosticsEngine &diags, LangOptions &opts, - SourceManager &SM, HeaderSearch &Headers, - ModuleLoader &TheModuleLoader, + SourceManager &SM, MemoryBufferCache &PCMCache, + HeaderSearch &Headers, ModuleLoader &TheModuleLoader, IdentifierInfoLookup *IILookup, bool OwnsHeaders, TranslationUnitKind TUKind) - : PPOpts(PPOpts), Diags(&diags), LangOpts(opts), Target(nullptr), + : PPOpts(std::move(PPOpts)), Diags(&diags), LangOpts(opts), Target(nullptr), AuxTarget(nullptr), FileMgr(Headers.getFileMgr()), SourceMgr(SM), - ScratchBuf(new ScratchBuffer(SourceMgr)), HeaderInfo(Headers), - TheModuleLoader(TheModuleLoader), ExternalSource(nullptr), - Identifiers(opts, IILookup), + PCMCache(PCMCache), ScratchBuf(new ScratchBuffer(SourceMgr)), + HeaderInfo(Headers), TheModuleLoader(TheModuleLoader), + ExternalSource(nullptr), Identifiers(opts, IILookup), PragmaHandlers(new PragmaNamespace(StringRef())), IncrementalProcessing(false), TUKind(TUKind), CodeComplete(nullptr), CodeCompletionFile(nullptr), CodeCompletionOffset(0), LastTokenWasAt(false), ModuleImportExpectsIdentifier(false), - CodeCompletionReached(0), MainFileDir(nullptr), - SkipMainFilePreamble(0, true), CurPPLexer(nullptr), CurDirLookup(nullptr), - CurLexerKind(CLK_Lexer), CurSubmodule(nullptr), Callbacks(nullptr), + CodeCompletionReached(false), CodeCompletionII(nullptr), + MainFileDir(nullptr), SkipMainFilePreamble(0, true), CurPPLexer(nullptr), + CurDirLookup(nullptr), CurLexerKind(CLK_Lexer), + CurLexerSubmodule(nullptr), Callbacks(nullptr), CurSubmoduleState(&NullSubmoduleState), MacroArgCache(nullptr), - Record(nullptr), MIChainHead(nullptr), DeserialMIChainHead(nullptr) { + Record(nullptr), MIChainHead(nullptr) { OwnsHeaderSearch = OwnsHeaders; CounterValue = 0; // __COUNTER__ starts at 0. @@ -108,12 +121,18 @@ // We haven't read anything from the external source. ReadMacrosFromExternalSource = false; - - // "Poison" __VA_ARGS__, which can only appear in the expansion of a macro. - // This gets unpoisoned where it is allowed. + + // "Poison" __VA_ARGS__, __VA_OPT__ which can only appear in the expansion of + // a macro. They get unpoisoned where it is allowed. (Ident__VA_ARGS__ = getIdentifierInfo("__VA_ARGS__"))->setIsPoisoned(); SetPoisonReason(Ident__VA_ARGS__,diag::ext_pp_bad_vaargs_use); - + if (getLangOpts().CPlusPlus2a) { + (Ident__VA_OPT__ = getIdentifierInfo("__VA_OPT__"))->setIsPoisoned(); + SetPoisonReason(Ident__VA_OPT__,diag::ext_pp_bad_vaopt_use); + } else { + Ident__VA_OPT__ = nullptr; + } + // Initialize the pragma handlers. RegisterBuiltinPragmas(); @@ -141,6 +160,9 @@ SavedDepth = 0; SavedTokenFlag = false; #endif + + if (this->PPOpts->GeneratePreamble) + PreambleConditionalStack.startRecording(); } Preprocessor::~Preprocessor() { @@ -160,11 +182,6 @@ std::fill(TokenLexerCache, TokenLexerCache + NumCachedTokenLexers, nullptr); CurTokenLexer.reset(); - while (DeserializedMacroInfoChain *I = DeserialMIChainHead) { - DeserialMIChainHead = I->Next; - I->~DeserializedMacroInfoChain(); - } - // Free any cached MacroArgs. for (MacroArgs *ArgList = MacroArgCache; ArgList;) ArgList = ArgList->deallocate(); @@ -481,7 +498,7 @@ } Module *Preprocessor::getCurrentModule() { - if (getLangOpts().CurrentModule.empty()) + if (!getLangOpts().isCompilingModule()) return nullptr; return getHeaderSearchInfo().lookupModule(getLangOpts().CurrentModule); @@ -491,7 +508,6 @@ // Preprocessor Initialization Methods //===----------------------------------------------------------------------===// - /// EnterMainSourceFile - Enter the specified FileID as the main source file, /// which implicitly adds the builtin defines etc. void Preprocessor::EnterMainSourceFile() { @@ -510,9 +526,9 @@ // If we've been asked to skip bytes in the main file (e.g., as part of a // precompiled preamble), do so now. if (SkipMainFilePreamble.first > 0) - CurLexer->SkipBytes(SkipMainFilePreamble.first, - SkipMainFilePreamble.second); - + CurLexer->SetByteOffset(SkipMainFilePreamble.first, + SkipMainFilePreamble.second); + // Tell the header info that the main file was entered. If the file is later // #imported, it won't be re-entered. if (const FileEntry *FE = SourceMgr.getFileEntryForID(MainFileID)) @@ -531,6 +547,16 @@ EnterSourceFile(FID, nullptr, SourceLocation()); } +void Preprocessor::replayPreambleConditionalStack() { + // Restore the conditional stack from the preamble, if there is one. + if (PreambleConditionalStack.isReplaying()) { + assert(CurPPLexer && + "CurPPLexer is null when calling replayPreambleConditionalStack."); + CurPPLexer->setConditionalLevels(PreambleConditionalStack.getStack()); + PreambleConditionalStack.doneReplaying(); + } +} + void Preprocessor::EndSourceFile() { // Notify the client that we reached the end of the source file. if (Callbacks) @@ -568,7 +594,11 @@ // Update the token info (identifier info and appropriate token kind). Identifier.setIdentifierInfo(II); - Identifier.setKind(II->getTokenID()); + if (getLangOpts().MSVCCompat && II->isCPlusPlusOperatorKeyword() && + getSourceManager().isInSystemHeader(Identifier.getLocation())) + Identifier.setKind(clang::tok::identifier); + else + Identifier.setKind(II->getTokenID()); return II; } @@ -612,6 +642,8 @@ return llvm::StringSwitch(II.getName()) #define CXX11_KEYWORD(NAME, FLAGS) \ .Case(#NAME, diag::warn_cxx11_keyword) +#define CXX2A_KEYWORD(NAME, FLAGS) \ + .Case(#NAME, diag::warn_cxx2a_keyword) #include "clang/Basic/TokenKinds.def" ; @@ -619,6 +651,11 @@ "Keyword not known to come from a newer Standard or proposed Standard"); } +void Preprocessor::updateOutOfDateIdentifier(IdentifierInfo &II) const { + assert(II.isOutOfDate() && "not out of date"); + getExternalSource()->updateOutOfDateIdentifier(II); +} + /// HandleIdentifier - This callback is invoked when the lexer reads an /// identifier. This callback looks up the identifier in the map and/or /// potentially macro expands it or turns it into a named token (like 'for'). @@ -640,13 +677,15 @@ // unpoisoned it if we're defining a C99 macro. if (II.isOutOfDate()) { bool CurrentIsPoisoned = false; - if (&II == Ident__VA_ARGS__) - CurrentIsPoisoned = Ident__VA_ARGS__->isPoisoned(); + const bool IsSpecialVariadicMacro = + &II == Ident__VA_ARGS__ || &II == Ident__VA_OPT__; + if (IsSpecialVariadicMacro) + CurrentIsPoisoned = II.isPoisoned(); - ExternalSource->updateOutOfDateIdentifier(II); + updateOutOfDateIdentifier(II); Identifier.setKind(II.getTokenID()); - if (&II == Ident__VA_ARGS__) + if (IsSpecialVariadicMacro) II.setIsPoisoned(CurrentIsPoisoned); } @@ -689,12 +728,6 @@ II.setIsFutureCompatKeyword(false); } - // C++ 2.11p2: If this is an alternative representation of a C++ operator, - // then we act as if it is the actual operator and not the textual - // representation of it. - if (II.isCPlusPlusOperatorKeyword()) - Identifier.setIdentifierInfo(nullptr); - // If this is an extension token, diagnose its use. // We avoid diagnosing tokens that originate from macro definitions. // FIXME: This warning is disabled in cases where it shouldn't be, @@ -708,9 +741,12 @@ // Note that we do not treat 'import' as a contextual // keyword when we're in a caching lexer, because caching lexers only get // used in contexts where import declarations are disallowed. - if (LastTokenWasAt && II.isModulesImport() && !InMacroArgs && - !DisableMacroExpansion && - (getLangOpts().Modules || getLangOpts().DebuggerSupport) && + // + // Likewise if this is the C++ Modules TS import keyword. + if (((LastTokenWasAt && II.isModulesImport()) || + Identifier.is(tok::kw_import)) && + !InMacroArgs && !DisableMacroExpansion && + (getLangOpts().Modules || getLangOpts().DebuggerSupport) && CurLexerKind != CLK_CachingLexer) { ModuleImportLoc = Identifier.getLocation(); ModuleImportPath.clear(); @@ -749,10 +785,12 @@ } } while (!ReturnedToken); + if (Result.is(tok::code_completion)) + setCodeCompletionIdentifierInfo(Result.getIdentifierInfo()); + LastTokenWasAt = Result.is(tok::at); } - /// \brief Lex a token following the 'import' contextual keyword. /// void Preprocessor::LexAfterModuleImport(Token &Result) { @@ -779,7 +817,8 @@ } // If we're expecting a '.' or a ';', and we got a '.', then wait until we - // see the next identifier. + // see the next identifier. (We can also see a '[[' that begins an + // attribute-specifier-seq here under the C++ Modules TS.) if (!ModuleImportExpectsIdentifier && Result.getKind() == tok::period) { ModuleImportExpectsIdentifier = true; CurLexerKind = CLK_LexAfterModuleImport; @@ -788,6 +827,23 @@ // If we have a non-empty module path, load the named module. if (!ModuleImportPath.empty()) { + // Under the Modules TS, the dot is just part of the module name, and not + // a real hierarachy separator. Flatten such module names now. + // + // FIXME: Is this the right level to be performing this transformation? + std::string FlatModuleName; + if (getLangOpts().ModulesTS) { + for (auto &Piece : ModuleImportPath) { + if (!FlatModuleName.empty()) + FlatModuleName += "."; + FlatModuleName += Piece.first->getName(); + } + SourceLocation FirstPathLoc = ModuleImportPath[0].second; + ModuleImportPath.clear(); + ModuleImportPath.push_back( + std::make_pair(getIdentifierInfo(FlatModuleName), FirstPathLoc)); + } + Module *Imported = nullptr; if (getLangOpts().Modules) { Imported = TheModuleLoader.loadModule(ModuleImportLoc, diff -r 56c5119fbcd2 -r c4cc77a799c9 tools/clang/lib/Parse/ParseCbC.cpp --- a/tools/clang/lib/Parse/ParseCbC.cpp Sun Dec 03 20:09:16 2017 +0900 +++ b/tools/clang/lib/Parse/ParseCbC.cpp Mon Dec 04 21:20:52 2017 +0900 @@ -1,7 +1,7 @@ #ifndef noCbC #include "clang/Parse/Parser.h" -#include "RAIIObjectsForParser.h" +#include "clang/Parse/RAIIObjectsForParser.h" #include "clang/AST/ASTContext.h" #include "clang/Basic/PrettyStackTrace.h" #include "clang/Basic/TargetInfo.h" diff -r 56c5119fbcd2 -r c4cc77a799c9 tools/clang/lib/Parse/ParseStmt.cpp --- a/tools/clang/lib/Parse/ParseStmt.cpp Sun Dec 03 20:09:16 2017 +0900 +++ b/tools/clang/lib/Parse/ParseStmt.cpp Mon Dec 04 21:20:52 2017 +0900 @@ -12,19 +12,15 @@ // //===----------------------------------------------------------------------===// +#include "clang/Basic/Attributes.h" +#include "clang/Basic/PrettyStackTrace.h" #include "clang/Parse/Parser.h" -#include "RAIIObjectsForParser.h" -#include "clang/AST/ASTContext.h" -#include "clang/Basic/Attributes.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/Basic/PrettyStackTrace.h" +#include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/LoopHint.h" #include "clang/Sema/PrettyDeclStackTrace.h" #include "clang/Sema/Scope.h" #include "clang/Sema/TypoCorrection.h" -#include "llvm/ADT/SmallString.h" - using namespace clang; //===----------------------------------------------------------------------===// @@ -101,13 +97,15 @@ /// StmtResult Parser::ParseStatementOrDeclaration(StmtVector &Stmts, - AllowedContsructsKind Allowed, + AllowedConstructsKind Allowed, SourceLocation *TrailingElseLoc) { ParenBraceBracketBalancer BalancerRAIIObj(*this); ParsedAttributesWithRange Attrs(AttrFactory); MaybeParseCXX11Attributes(Attrs, nullptr, /*MightBeObjCMessageSend*/ true); + if (!MaybeParseOpenCLUnrollHintAttribute(Attrs)) + return StmtError(); StmtResult Res = ParseStatementOrDeclarationAfterAttributes( Stmts, Allowed, TrailingElseLoc, Attrs); @@ -152,7 +150,7 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes(StmtVector &Stmts, - AllowedContsructsKind Allowed, SourceLocation *TrailingElseLoc, + AllowedConstructsKind Allowed, SourceLocation *TrailingElseLoc, ParsedAttributesWithRange &Attrs) { const char *SemiError = nullptr; StmtResult Res; @@ -205,10 +203,12 @@ } // Fall through + LLVM_FALLTHROUGH; } default: { - if ((getLangOpts().CPlusPlus || Allowed == ACK_Any) && + if ((getLangOpts().CPlusPlus || getLangOpts().MicrosoftExt || + Allowed == ACK_Any) && isDeclarationStatement()) { SourceLocation DeclStart = Tok.getLocation(), DeclEnd; DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext, @@ -354,7 +354,13 @@ case tok::annot_pragma_fp_contract: ProhibitAttributes(Attrs); Diag(Tok, diag::err_pragma_fp_contract_scope); - ConsumeToken(); + ConsumeAnnotationToken(); + return StmtError(); + + case tok::annot_pragma_fp: + ProhibitAttributes(Attrs); + Diag(Tok, diag::err_pragma_fp_scope); + ConsumeAnnotationToken(); return StmtError(); case tok::annot_pragma_opencl_extension: @@ -392,6 +398,10 @@ case tok::annot_pragma_dump: HandlePragmaDump(); return StmtEmpty(); + + case tok::annot_pragma_attribute: + HandlePragmaAttribute(); + return StmtEmpty(); } // If we reached this code, the statement must end in a semicolon. @@ -412,6 +422,8 @@ // If a case keyword is missing, this is where it should be inserted. Token OldToken = Tok; + ExprStatementTokLoc = Tok.getLocation(); + // expression[opt] ';' ExprResult Expr(ParseExpression()); if (Expr.isInvalid()) { @@ -456,9 +468,10 @@ if (Tok.isNot(tok::l_brace)) return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace); - StmtResult TryBlock(ParseCompoundStatement(/*isStmtExpr=*/false, - Scope::DeclScope | Scope::SEHTryScope)); - if(TryBlock.isInvalid()) + StmtResult TryBlock(ParseCompoundStatement( + /*isStmtExpr=*/false, + Scope::DeclScope | Scope::CompoundStmtScope | Scope::SEHTryScope)); + if (TryBlock.isInvalid()) return TryBlock; StmtResult Handler; @@ -843,7 +856,8 @@ } StmtResult Parser::ParseCompoundStatement(bool isStmtExpr) { - return ParseCompoundStatement(isStmtExpr, Scope::DeclScope); + return ParseCompoundStatement(isStmtExpr, + Scope::DeclScope | Scope::CompoundStmtScope); } /// ParseCompoundStatement - Parse a "{}" block. @@ -914,6 +928,9 @@ case tok::annot_pragma_fp_contract: HandlePragmaFPContract(); break; + case tok::annot_pragma_fp: + HandlePragmaFP(); + break; case tok::annot_pragma_ms_pointers_to_members: HandlePragmaMSPointersToMembers(); break; @@ -1057,7 +1074,8 @@ /// ParseParenExprOrCondition: /// [C ] '(' expression ')' -/// [C++] '(' condition ')' [not allowed if OnlyAllowCondition=true] +/// [C++] '(' condition ')' +/// [C++1z] '(' init-statement[opt] condition ')' /// /// This function parses and performs error recovery on the specified condition /// or expression (depending on whether we're in C++ or C mode). This function @@ -1066,29 +1084,29 @@ /// should try to recover harder. It returns false if the condition is /// successfully parsed. Note that a successful parse can still have semantic /// errors in the condition. -bool Parser::ParseParenExprOrCondition(ExprResult &ExprResult, - Decl *&DeclResult, +bool Parser::ParseParenExprOrCondition(StmtResult *InitStmt, + Sema::ConditionResult &Cond, SourceLocation Loc, - bool ConvertToBoolean) { + Sema::ConditionKind CK) { BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); if (getLangOpts().CPlusPlus) - ParseCXXCondition(ExprResult, DeclResult, Loc, ConvertToBoolean); + Cond = ParseCXXCondition(InitStmt, Loc, CK); else { - ExprResult = ParseExpression(); - DeclResult = nullptr; + ExprResult CondExpr = ParseExpression(); // If required, convert to a boolean value. - if (!ExprResult.isInvalid() && ConvertToBoolean) - ExprResult - = Actions.ActOnBooleanCondition(getCurScope(), Loc, ExprResult.get()); + if (CondExpr.isInvalid()) + Cond = Sema::ConditionError(); + else + Cond = Actions.ActOnCondition(getCurScope(), Loc, CondExpr.get(), CK); } // If the parser was confused by the condition and we don't have a ')', try to // recover by skipping ahead to a semi and bailing out. If condexp is // semantically invalid but we have well formed code, keep going. - if (ExprResult.isInvalid() && !DeclResult && Tok.isNot(tok::r_paren)) { + if (Cond.isInvalid() && Tok.isNot(tok::r_paren)) { SkipUntil(tok::semi); // Skipping may have stopped if it found the containing ')'. If so, we can // continue parsing the if statement. @@ -1123,6 +1141,14 @@ assert(Tok.is(tok::kw_if) && "Not an if stmt!"); SourceLocation IfLoc = ConsumeToken(); // eat the 'if'. + bool IsConstexpr = false; + if (Tok.is(tok::kw_constexpr)) { + Diag(Tok, getLangOpts().CPlusPlus1z ? diag::warn_cxx14_compat_constexpr_if + : diag::ext_constexpr_if); + IsConstexpr = true; + ConsumeToken(); + } + if (Tok.isNot(tok::l_paren)) { Diag(Tok, diag::err_expected_lparen_after) << "if"; SkipUntil(tok::semi); @@ -1146,12 +1172,16 @@ ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, C99orCXX); // Parse the condition. - ExprResult CondExp; - Decl *CondVar = nullptr; - if (ParseParenExprOrCondition(CondExp, CondVar, IfLoc, true)) + StmtResult InitStmt; + Sema::ConditionResult Cond; + if (ParseParenExprOrCondition(&InitStmt, Cond, IfLoc, + IsConstexpr ? Sema::ConditionKind::ConstexprIf + : Sema::ConditionKind::Boolean)) return StmtError(); - FullExprArg FullCondExp(Actions.MakeFullExpr(CondExp.get(), IfLoc)); + llvm::Optional ConstexprCondition; + if (IsConstexpr) + ConstexprCondition = Cond.getKnownValue(); // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if // there is no compound stmt. C90 does not have this clause. We only do this @@ -1177,7 +1207,14 @@ SourceLocation ThenStmtLoc = Tok.getLocation(); SourceLocation InnerStatementTrailingElseLoc; - StmtResult ThenStmt(ParseStatement(&InnerStatementTrailingElseLoc)); + StmtResult ThenStmt; + { + EnterExpressionEvaluationContext PotentiallyDiscarded( + Actions, Sema::ExpressionEvaluationContext::DiscardedStatement, nullptr, + false, + /*ShouldEnter=*/ConstexprCondition && !*ConstexprCondition); + ThenStmt = ParseStatement(&InnerStatementTrailingElseLoc); + } // Pop the 'if' scope if needed. InnerScope.Exit(); @@ -1203,8 +1240,13 @@ // The substatement in a selection-statement (each substatement, in the else // form of the if statement) implicitly defines a local scope. // - ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace)); + ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, + Tok.is(tok::l_brace)); + EnterExpressionEvaluationContext PotentiallyDiscarded( + Actions, Sema::ExpressionEvaluationContext::DiscardedStatement, nullptr, + false, + /*ShouldEnter=*/ConstexprCondition && *ConstexprCondition); ElseStmt = ParseStatement(); // Pop the 'else' scope if needed. @@ -1235,8 +1277,8 @@ if (ElseStmt.isInvalid()) ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc); - return Actions.ActOnIfStmt(IfLoc, FullCondExp, CondVar, ThenStmt.get(), - ElseLoc, ElseStmt.get()); + return Actions.ActOnIfStmt(IfLoc, IsConstexpr, InitStmt.get(), Cond, + ThenStmt.get(), ElseLoc, ElseStmt.get()); } /// ParseSwitchStatement @@ -1273,13 +1315,14 @@ ParseScope SwitchScope(this, ScopeFlags); // Parse the condition. - ExprResult Cond; - Decl *CondVar = nullptr; - if (ParseParenExprOrCondition(Cond, CondVar, SwitchLoc, false)) + StmtResult InitStmt; + Sema::ConditionResult Cond; + if (ParseParenExprOrCondition(&InitStmt, Cond, SwitchLoc, + Sema::ConditionKind::Switch)) return StmtError(); - StmtResult Switch - = Actions.ActOnStartOfSwitchStmt(SwitchLoc, Cond.get(), CondVar); + StmtResult Switch = + Actions.ActOnStartOfSwitchStmt(SwitchLoc, InitStmt.get(), Cond); if (Switch.isInvalid()) { // Skip the switch body. @@ -1361,13 +1404,11 @@ ParseScope WhileScope(this, ScopeFlags); // Parse the condition. - ExprResult Cond; - Decl *CondVar = nullptr; - if (ParseParenExprOrCondition(Cond, CondVar, WhileLoc, true)) + Sema::ConditionResult Cond; + if (ParseParenExprOrCondition(nullptr, Cond, WhileLoc, + Sema::ConditionKind::Boolean)) return StmtError(); - FullExprArg FullCond(Actions.MakeFullExpr(Cond.get(), WhileLoc)); - // C99 6.8.5p5 - In C99, the body of the while statement is a scope, even if // there is no compound stmt. C90 does not have this clause. We only do this // if the body isn't a compound statement to avoid push/pop in common cases. @@ -1388,10 +1429,10 @@ InnerScope.Exit(); WhileScope.Exit(); - if ((Cond.isInvalid() && !CondVar) || Body.isInvalid()) + if (Cond.isInvalid() || Body.isInvalid()) return StmtError(); - return Actions.ActOnWhileStmt(WhileLoc, FullCond, CondVar, Body.get()); + return Actions.ActOnWhileStmt(WhileLoc, Cond, Body.get()); } /// ParseDoStatement @@ -1549,12 +1590,10 @@ bool ForEach = false, ForRange = false; StmtResult FirstPart; - bool SecondPartIsInvalid = false; - FullExprArg SecondPart(Actions); + Sema::ConditionResult SecondPart; ExprResult Collection; ForRangeInit ForRangeInit; FullExprArg ThirdPart(Actions); - Decl *SecondVar = nullptr; if (Tok.is(tok::code_completion)) { Actions.CodeCompleteOrdinaryName(getCurScope(), @@ -1659,7 +1698,7 @@ Diag(Tok, diag::err_for_range_expected_decl) << FirstPart.get()->getSourceRange(); SkipUntil(tok::r_paren, StopBeforeMatch); - SecondPartIsInvalid = true; + SecondPart = Sema::ConditionError(); } else { if (!Value.isInvalid()) { Diag(Tok, diag::err_expected_semi_for); @@ -1674,29 +1713,29 @@ // Parse the second part of the for specifier. getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope); - if (!ForEach && !ForRange) { - assert(!SecondPart.get() && "Shouldn't have a second expression yet."); + if (!ForEach && !ForRange && !SecondPart.isInvalid()) { // Parse the second part of the for specifier. if (Tok.is(tok::semi)) { // for (...;; // no second part. } else if (Tok.is(tok::r_paren)) { // missing both semicolons. } else { - ExprResult Second; if (getLangOpts().CPlusPlus) - ParseCXXCondition(Second, SecondVar, ForLoc, true); + SecondPart = + ParseCXXCondition(nullptr, ForLoc, Sema::ConditionKind::Boolean); else { - Second = ParseExpression(); - if (!Second.isInvalid()) - Second = Actions.ActOnBooleanCondition(getCurScope(), ForLoc, - Second.get()); + ExprResult SecondExpr = ParseExpression(); + if (SecondExpr.isInvalid()) + SecondPart = Sema::ConditionError(); + else + SecondPart = + Actions.ActOnCondition(getCurScope(), ForLoc, SecondExpr.get(), + Sema::ConditionKind::Boolean); } - SecondPartIsInvalid = Second.isInvalid(); - SecondPart = Actions.MakeFullExpr(Second.get(), ForLoc); } if (Tok.isNot(tok::semi)) { - if (!SecondPartIsInvalid || SecondVar) + if (!SecondPart.isInvalid()) Diag(Tok, diag::err_expected_semi_for); else // Skip until semicolon or rparen, don't consume it. @@ -1732,9 +1771,11 @@ StmtResult ForEachStmt; if (ForRange) { + ExprResult CorrectedRange = + Actions.CorrectDelayedTyposInExpr(ForRangeInit.RangeExpr.get()); ForRangeStmt = Actions.ActOnCXXForRangeStmt( getCurScope(), ForLoc, CoawaitLoc, FirstPart.get(), - ForRangeInit.ColonLoc, ForRangeInit.RangeExpr.get(), + ForRangeInit.ColonLoc, CorrectedRange.get(), T.getCloseLocation(), Sema::BFRK_Build); // Similarly, we need to do the semantic analysis for a for-range @@ -1793,8 +1834,8 @@ return Actions.FinishCXXForRangeStmt(ForRangeStmt.get(), Body.get()); return Actions.ActOnForStmt(ForLoc, T.getOpenLocation(), FirstPart.get(), - SecondPart, SecondVar, ThirdPart, - T.getCloseLocation(), Body.get()); + SecondPart, ThirdPart, T.getCloseLocation(), + Body.get()); } /// ParseGotoStatement @@ -1890,12 +1931,12 @@ } } if (IsCoreturn) - return Actions.ActOnCoreturnStmt(ReturnLoc, R.get()); + return Actions.ActOnCoreturnStmt(getCurScope(), ReturnLoc, R.get()); return Actions.ActOnReturnStmt(ReturnLoc, R.get(), getCurScope()); } StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts, - AllowedContsructsKind Allowed, + AllowedConstructsKind Allowed, SourceLocation *TrailingElseLoc, ParsedAttributesWithRange &Attrs) { // Create temporary attribute list. @@ -1928,19 +1969,14 @@ assert(Tok.is(tok::l_brace)); SourceLocation LBraceLoc = Tok.getLocation(); - if (SkipFunctionBodies && (!Decl || Actions.canSkipFunctionBody(Decl)) && - trySkippingFunctionBody()) { - BodyScope.Exit(); - return Actions.ActOnSkippedFunctionBody(Decl); - } - PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc, "parsing function body"); // Save and reset current vtordisp stack if we have entered a C++ method body. bool IsCXXMethod = getLangOpts().CPlusPlus && Decl && isa(Decl); - Sema::VtorDispStackRAII SavedVtorDispStack(Actions, IsCXXMethod); + Sema::PragmaStackSentinelRAII + PragmaStackSentinel(Actions, "InternalPragmaState", IsCXXMethod); // Do not enter a scope for the brace, as the arguments are in the same scope // (the function body) as the body itself. Instead, just read the statement @@ -1975,16 +2011,11 @@ else Actions.ActOnDefaultCtorInitializers(Decl); - if (SkipFunctionBodies && Actions.canSkipFunctionBody(Decl) && - trySkippingFunctionBody()) { - BodyScope.Exit(); - return Actions.ActOnSkippedFunctionBody(Decl); - } - // Save and reset current vtordisp stack if we have entered a C++ method body. bool IsCXXMethod = getLangOpts().CPlusPlus && Decl && isa(Decl); - Sema::VtorDispStackRAII SavedVtorDispStack(Actions, IsCXXMethod); + Sema::PragmaStackSentinelRAII + PragmaStackSentinel(Actions, "InternalPragmaState", IsCXXMethod); SourceLocation LBraceLoc = Tok.getLocation(); StmtResult FnBody(ParseCXXTryBlockCommon(TryLoc, /*FnTry*/true)); @@ -2000,27 +2031,43 @@ } bool Parser::trySkippingFunctionBody() { - assert(Tok.is(tok::l_brace)); assert(SkipFunctionBodies && "Should only be called when SkipFunctionBodies is enabled"); - if (!PP.isCodeCompletionEnabled()) { - ConsumeBrace(); - SkipUntil(tok::r_brace); + SkipFunctionBody(); return true; } // We're in code-completion mode. Skip parsing for all function bodies unless // the body contains the code-completion point. TentativeParsingAction PA(*this); - ConsumeBrace(); - if (SkipUntil(tok::r_brace, StopAtCodeCompletion)) { + bool IsTryCatch = Tok.is(tok::kw_try); + CachedTokens Toks; + bool ErrorInPrologue = ConsumeAndStoreFunctionPrologue(Toks); + if (llvm::any_of(Toks, [](const Token &Tok) { + return Tok.is(tok::code_completion); + })) { + PA.Revert(); + return false; + } + if (ErrorInPrologue) { PA.Commit(); + SkipMalformedDecl(); return true; } - - PA.Revert(); - return false; + if (!SkipUntil(tok::r_brace, StopAtCodeCompletion)) { + PA.Revert(); + return false; + } + while (IsTryCatch && Tok.is(tok::kw_catch)) { + if (!SkipUntil(tok::l_brace, StopAtCodeCompletion) || + !SkipUntil(tok::r_brace, StopAtCodeCompletion)) { + PA.Revert(); + return false; + } + } + PA.Commit(); + return true; } /// ParseCXXTryBlock - Parse a C++ try-block. @@ -2055,9 +2102,10 @@ if (Tok.isNot(tok::l_brace)) return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace); - StmtResult TryBlock(ParseCompoundStatement(/*isStmtExpr=*/false, - Scope::DeclScope | Scope::TryScope | - (FnTry ? Scope::FnTryCatchScope : 0))); + StmtResult TryBlock(ParseCompoundStatement( + /*isStmtExpr=*/false, Scope::DeclScope | Scope::TryScope | + Scope::CompoundStmtScope | + (FnTry ? Scope::FnTryCatchScope : 0))); if (TryBlock.isInvalid()) return TryBlock; @@ -2222,3 +2270,19 @@ } Braces.consumeClose(); } + +bool Parser::ParseOpenCLUnrollHintAttribute(ParsedAttributes &Attrs) { + MaybeParseGNUAttributes(Attrs); + + if (Attrs.empty()) + return true; + + if (Attrs.getList()->getKind() != AttributeList::AT_OpenCLUnrollHint) + return true; + + if (!(Tok.is(tok::kw_for) || Tok.is(tok::kw_while) || Tok.is(tok::kw_do))) { + Diag(Tok, diag::err_opencl_unroll_hint_on_non_loop); + return false; + } + return true; +} diff -r 56c5119fbcd2 -r c4cc77a799c9 tools/clang/lib/Parse/Parser.cpp --- a/tools/clang/lib/Parse/Parser.cpp Sun Dec 03 20:09:16 2017 +0900 +++ b/tools/clang/lib/Parse/Parser.cpp Mon Dec 04 21:20:52 2017 +0900 @@ -1,555 +1,561 @@ - //===--- Parser.cpp - C Language Family Parser ----------------------------===// - // - // The LLVM Compiler Infrastructure - // - // This file is distributed under the University of Illinois Open Source - // License. See LICENSE.TXT for details. - // - //===----------------------------------------------------------------------===// - // - // This file implements the Parser interfaces. - // - //===----------------------------------------------------------------------===// - - #include "clang/Parse/Parser.h" - #include "RAIIObjectsForParser.h" - #include "clang/AST/ASTConsumer.h" - #include "clang/AST/ASTContext.h" - #include "clang/AST/DeclTemplate.h" - #include "clang/Parse/ParseDiagnostic.h" - #include "clang/Sema/DeclSpec.h" - #include "clang/Sema/ParsedTemplate.h" - #include "clang/Sema/Scope.h" - #include "llvm/Support/raw_ostream.h" - using namespace clang; - - namespace { - /// \brief A comment handler that passes comments found by the preprocessor - /// to the parser action. - class ActionCommentHandler : public CommentHandler { - Sema &S; - - public: - explicit ActionCommentHandler(Sema &S) : S(S) { } - - bool HandleComment(Preprocessor &PP, SourceRange Comment) override { - S.ActOnComment(Comment); - return false; - } - }; - - /// \brief RAIIObject to destroy the contents of a SmallVector of - /// TemplateIdAnnotation pointers and clear the vector. - class DestroyTemplateIdAnnotationsRAIIObj { - SmallVectorImpl &Container; - - public: - DestroyTemplateIdAnnotationsRAIIObj( - SmallVectorImpl &Container) - : Container(Container) {} - - ~DestroyTemplateIdAnnotationsRAIIObj() { - for (SmallVectorImpl::iterator I = - Container.begin(), - E = Container.end(); - I != E; ++I) - (*I)->Destroy(); - Container.clear(); - } - }; - } // end anonymous namespace - - IdentifierInfo *Parser::getSEHExceptKeyword() { - // __except is accepted as a (contextual) keyword - if (!Ident__except && (getLangOpts().MicrosoftExt || getLangOpts().Borland)) - Ident__except = PP.getIdentifierInfo("__except"); - - return Ident__except; - } - - Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies) - : PP(pp), Actions(actions), Diags(PP.getDiagnostics()), - GreaterThanIsOperator(true), ColonIsSacred(false), - InMessageExpression(false), TemplateParameterDepth(0), - ParsingInObjCContainer(false) { - SkipFunctionBodies = pp.isCodeCompletionEnabled() || skipFunctionBodies; - Tok.startToken(); - Tok.setKind(tok::eof); - Actions.CurScope = nullptr; - NumCachedScopes = 0; - ParenCount = BracketCount = BraceCount = 0; - CurParsedObjCImpl = nullptr; - - // Add #pragma handlers. These are removed and destroyed in the - // destructor. - initializePragmaHandlers(); - - CommentSemaHandler.reset(new ActionCommentHandler(actions)); - PP.addCommentHandler(CommentSemaHandler.get()); - - PP.setCodeCompletionHandler(*this); - #ifndef noCbC - UniqueId = 0; // for CreateUniqueIdentifier() - #endif - } - - DiagnosticBuilder Parser::Diag(SourceLocation Loc, unsigned DiagID) { - return Diags.Report(Loc, DiagID); - } - - DiagnosticBuilder Parser::Diag(const Token &Tok, unsigned DiagID) { - return Diag(Tok.getLocation(), DiagID); - } - - /// \brief Emits a diagnostic suggesting parentheses surrounding a - /// given range. - /// - /// \param Loc The location where we'll emit the diagnostic. - /// \param DK The kind of diagnostic to emit. - /// \param ParenRange Source range enclosing code that should be parenthesized. - void Parser::SuggestParentheses(SourceLocation Loc, unsigned DK, - SourceRange ParenRange) { - SourceLocation EndLoc = PP.getLocForEndOfToken(ParenRange.getEnd()); - if (!ParenRange.getEnd().isFileID() || EndLoc.isInvalid()) { - // We can't display the parentheses, so just dig the - // warning/error and return. - Diag(Loc, DK); - return; - } - - Diag(Loc, DK) - << FixItHint::CreateInsertion(ParenRange.getBegin(), "(") - << FixItHint::CreateInsertion(EndLoc, ")"); - } - - static bool IsCommonTypo(tok::TokenKind ExpectedTok, const Token &Tok) { - switch (ExpectedTok) { - case tok::semi: - return Tok.is(tok::colon) || Tok.is(tok::comma); // : or , for ; - default: return false; - } - } - - bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID, - StringRef Msg) { - if (Tok.is(ExpectedTok) || Tok.is(tok::code_completion)) { - ConsumeAnyToken(); - return false; - } - - // Detect common single-character typos and resume. - if (IsCommonTypo(ExpectedTok, Tok)) { - SourceLocation Loc = Tok.getLocation(); - { - DiagnosticBuilder DB = Diag(Loc, DiagID); - DB << FixItHint::CreateReplacement( - SourceRange(Loc), tok::getPunctuatorSpelling(ExpectedTok)); - if (DiagID == diag::err_expected) - DB << ExpectedTok; - else if (DiagID == diag::err_expected_after) - DB << Msg << ExpectedTok; - else - DB << Msg; - } - - // Pretend there wasn't a problem. - ConsumeAnyToken(); - return false; - } - - SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation); - const char *Spelling = nullptr; - if (EndLoc.isValid()) - Spelling = tok::getPunctuatorSpelling(ExpectedTok); - - DiagnosticBuilder DB = - Spelling - ? Diag(EndLoc, DiagID) << FixItHint::CreateInsertion(EndLoc, Spelling) - : Diag(Tok, DiagID); - if (DiagID == diag::err_expected) - DB << ExpectedTok; - else if (DiagID == diag::err_expected_after) - DB << Msg << ExpectedTok; - else - DB << Msg; - - return true; - } - - bool Parser::ExpectAndConsumeSemi(unsigned DiagID) { - if (TryConsumeToken(tok::semi)) - return false; - - if (Tok.is(tok::code_completion)) { - handleUnexpectedCodeCompletionToken(); - return false; - } - - if ((Tok.is(tok::r_paren) || Tok.is(tok::r_square)) && - NextToken().is(tok::semi)) { - Diag(Tok, diag::err_extraneous_token_before_semi) - << PP.getSpelling(Tok) - << FixItHint::CreateRemoval(Tok.getLocation()); - ConsumeAnyToken(); // The ')' or ']'. - ConsumeToken(); // The ';'. - return false; - } - - return ExpectAndConsume(tok::semi, DiagID); - } - - void Parser::ConsumeExtraSemi(ExtraSemiKind Kind, unsigned TST) { - if (!Tok.is(tok::semi)) return; - - bool HadMultipleSemis = false; - SourceLocation StartLoc = Tok.getLocation(); - SourceLocation EndLoc = Tok.getLocation(); - ConsumeToken(); +//===--- Parser.cpp - C Language Family Parser ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Parser interfaces. +// +//===----------------------------------------------------------------------===// - while ((Tok.is(tok::semi) && !Tok.isAtStartOfLine())) { - HadMultipleSemis = true; - EndLoc = Tok.getLocation(); - ConsumeToken(); - } - - // C++11 allows extra semicolons at namespace scope, but not in any of the - // other contexts. - if (Kind == OutsideFunction && getLangOpts().CPlusPlus) { - if (getLangOpts().CPlusPlus11) - Diag(StartLoc, diag::warn_cxx98_compat_top_level_semi) - << FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc)); - else - Diag(StartLoc, diag::ext_extra_semi_cxx11) - << FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc)); - return; - } - - if (Kind != AfterMemberFunctionDefinition || HadMultipleSemis) - Diag(StartLoc, diag::ext_extra_semi) - << Kind << DeclSpec::getSpecifierName((DeclSpec::TST)TST, - Actions.getASTContext().getPrintingPolicy()) - << FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc)); - else - // A single semicolon is valid after a member function definition. - Diag(StartLoc, diag::warn_extra_semi_after_mem_fn_def) - << FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc)); - } - - //===----------------------------------------------------------------------===// - // Error recovery. - //===----------------------------------------------------------------------===// - - static bool HasFlagsSet(Parser::SkipUntilFlags L, Parser::SkipUntilFlags R) { - return (static_cast(L) & static_cast(R)) != 0; - } - - /// SkipUntil - Read tokens until we get to the specified token, then consume - /// it (unless no flag StopBeforeMatch). Because we cannot guarantee that the - /// token will ever occur, this skips to the next token, or to some likely - /// good stopping point. If StopAtSemi is true, skipping will stop at a ';' - /// character. - /// - /// If SkipUntil finds the specified token, it returns true, otherwise it - /// returns false. - bool Parser::SkipUntil(ArrayRef Toks, SkipUntilFlags Flags) { - // We always want this function to skip at least one token if the first token - // isn't T and if not at EOF. - bool isFirstTokenSkipped = true; - while (1) { - // If we found one of the tokens, stop and return true. - for (unsigned i = 0, NumToks = Toks.size(); i != NumToks; ++i) { - if (Tok.is(Toks[i])) { - if (HasFlagsSet(Flags, StopBeforeMatch)) { - // Noop, don't consume the token. - } else { - ConsumeAnyToken(); - } - return true; - } - } - - // Important special case: The caller has given up and just wants us to - // skip the rest of the file. Do this without recursing, since we can - // get here precisely because the caller detected too much recursion. - if (Toks.size() == 1 && Toks[0] == tok::eof && - !HasFlagsSet(Flags, StopAtSemi) && - !HasFlagsSet(Flags, StopAtCodeCompletion)) { - while (Tok.isNot(tok::eof)) - ConsumeAnyToken(); - return true; - } - - switch (Tok.getKind()) { - case tok::eof: - // Ran out of tokens. - return false; - - case tok::annot_pragma_openmp: - case tok::annot_pragma_openmp_end: - // Stop before an OpenMP pragma boundary. - case tok::annot_module_begin: - case tok::annot_module_end: - case tok::annot_module_include: - // Stop before we change submodules. They generally indicate a "good" - // place to pick up parsing again (except in the special case where - // we're trying to skip to EOF). - return false; - - case tok::code_completion: - if (!HasFlagsSet(Flags, StopAtCodeCompletion)) - handleUnexpectedCodeCompletionToken(); - return false; - - case tok::l_paren: - // Recursively skip properly-nested parens. - ConsumeParen(); - if (HasFlagsSet(Flags, StopAtCodeCompletion)) - SkipUntil(tok::r_paren, StopAtCodeCompletion); - else - SkipUntil(tok::r_paren); - break; - case tok::l_square: - // Recursively skip properly-nested square brackets. - ConsumeBracket(); - if (HasFlagsSet(Flags, StopAtCodeCompletion)) - SkipUntil(tok::r_square, StopAtCodeCompletion); - else - SkipUntil(tok::r_square); - break; - case tok::l_brace: - // Recursively skip properly-nested braces. - ConsumeBrace(); - if (HasFlagsSet(Flags, StopAtCodeCompletion)) - SkipUntil(tok::r_brace, StopAtCodeCompletion); - else - SkipUntil(tok::r_brace); - break; - - // Okay, we found a ']' or '}' or ')', which we think should be balanced. - // Since the user wasn't looking for this token (if they were, it would - // already be handled), this isn't balanced. If there is a LHS token at a - // higher level, we will assume that this matches the unbalanced token - // and return it. Otherwise, this is a spurious RHS token, which we skip. - case tok::r_paren: - if (ParenCount && !isFirstTokenSkipped) - return false; // Matches something. - ConsumeParen(); - break; - case tok::r_square: - if (BracketCount && !isFirstTokenSkipped) - return false; // Matches something. - ConsumeBracket(); - break; - case tok::r_brace: - if (BraceCount && !isFirstTokenSkipped) - return false; // Matches something. - ConsumeBrace(); - break; - - case tok::string_literal: - case tok::wide_string_literal: - case tok::utf8_string_literal: - case tok::utf16_string_literal: - case tok::utf32_string_literal: - ConsumeStringToken(); - break; - - case tok::semi: - if (HasFlagsSet(Flags, StopAtSemi)) - return false; - // FALL THROUGH. - default: - // Skip this token. - ConsumeToken(); - break; - } - isFirstTokenSkipped = false; - } - } - - //===----------------------------------------------------------------------===// - // Scope manipulation - //===----------------------------------------------------------------------===// - - /// EnterScope - Start a new scope. - void Parser::EnterScope(unsigned ScopeFlags) { - if (NumCachedScopes) { - Scope *N = ScopeCache[--NumCachedScopes]; - N->Init(getCurScope(), ScopeFlags); - Actions.CurScope = N; - } else { - Actions.CurScope = new Scope(getCurScope(), ScopeFlags, Diags); - } - } - - /// ExitScope - Pop a scope off the scope stack. - void Parser::ExitScope() { - assert(getCurScope() && "Scope imbalance!"); - - // Inform the actions module that this scope is going away if there are any - // decls in it. - Actions.ActOnPopScope(Tok.getLocation(), getCurScope()); - - Scope *OldScope = getCurScope(); - Actions.CurScope = OldScope->getParent(); - - if (NumCachedScopes == ScopeCacheSize) - delete OldScope; - else - ScopeCache[NumCachedScopes++] = OldScope; - } - - /// Set the flags for the current scope to ScopeFlags. If ManageFlags is false, - /// this object does nothing. - Parser::ParseScopeFlags::ParseScopeFlags(Parser *Self, unsigned ScopeFlags, - bool ManageFlags) - : CurScope(ManageFlags ? Self->getCurScope() : nullptr) { - if (CurScope) { - OldFlags = CurScope->getFlags(); - CurScope->setFlags(ScopeFlags); - } - } - - /// Restore the flags for the current scope to what they were before this - /// object overrode them. - Parser::ParseScopeFlags::~ParseScopeFlags() { - if (CurScope) - CurScope->setFlags(OldFlags); - } +#include "clang/Parse/Parser.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/Parse/ParseDiagnostic.h" +#include "clang/Parse/RAIIObjectsForParser.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/ParsedTemplate.h" +#include "clang/Sema/Scope.h" +using namespace clang; - //===----------------------------------------------------------------------===// - // C99 6.9: External Definitions. - //===----------------------------------------------------------------------===// +namespace { +/// \brief A comment handler that passes comments found by the preprocessor +/// to the parser action. +class ActionCommentHandler : public CommentHandler { + Sema &S; + +public: + explicit ActionCommentHandler(Sema &S) : S(S) { } + + bool HandleComment(Preprocessor &PP, SourceRange Comment) override { + S.ActOnComment(Comment); + return false; + } +}; +} // end anonymous namespace + +IdentifierInfo *Parser::getSEHExceptKeyword() { + // __except is accepted as a (contextual) keyword + if (!Ident__except && (getLangOpts().MicrosoftExt || getLangOpts().Borland)) + Ident__except = PP.getIdentifierInfo("__except"); + + return Ident__except; +} - Parser::~Parser() { - // If we still have scopes active, delete the scope tree. - delete getCurScope(); - Actions.CurScope = nullptr; +Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies) + : PP(pp), Actions(actions), Diags(PP.getDiagnostics()), + GreaterThanIsOperator(true), ColonIsSacred(false), + InMessageExpression(false), TemplateParameterDepth(0), + ParsingInObjCContainer(false) { + SkipFunctionBodies = pp.isCodeCompletionEnabled() || skipFunctionBodies; + Tok.startToken(); + Tok.setKind(tok::eof); + Actions.CurScope = nullptr; + NumCachedScopes = 0; + CurParsedObjCImpl = nullptr; + + // Add #pragma handlers. These are removed and destroyed in the + // destructor. + initializePragmaHandlers(); - // Free the scope cache. - for (unsigned i = 0, e = NumCachedScopes; i != e; ++i) - delete ScopeCache[i]; + CommentSemaHandler.reset(new ActionCommentHandler(actions)); + PP.addCommentHandler(CommentSemaHandler.get()); + + PP.setCodeCompletionHandler(*this); +#ifndef noCbC + UniqueId = 0; // for CreateUniqueIdentifier() +#endif +} + +DiagnosticBuilder Parser::Diag(SourceLocation Loc, unsigned DiagID) { + return Diags.Report(Loc, DiagID); +} + +DiagnosticBuilder Parser::Diag(const Token &Tok, unsigned DiagID) { + return Diag(Tok.getLocation(), DiagID); +} - resetPragmaHandlers(); +/// \brief Emits a diagnostic suggesting parentheses surrounding a +/// given range. +/// +/// \param Loc The location where we'll emit the diagnostic. +/// \param DK The kind of diagnostic to emit. +/// \param ParenRange Source range enclosing code that should be parenthesized. +void Parser::SuggestParentheses(SourceLocation Loc, unsigned DK, + SourceRange ParenRange) { + SourceLocation EndLoc = PP.getLocForEndOfToken(ParenRange.getEnd()); + if (!ParenRange.getEnd().isFileID() || EndLoc.isInvalid()) { + // We can't display the parentheses, so just dig the + // warning/error and return. + Diag(Loc, DK); + return; + } - PP.removeCommentHandler(CommentSemaHandler.get()); + Diag(Loc, DK) + << FixItHint::CreateInsertion(ParenRange.getBegin(), "(") + << FixItHint::CreateInsertion(EndLoc, ")"); +} - PP.clearCodeCompletionHandler(); +static bool IsCommonTypo(tok::TokenKind ExpectedTok, const Token &Tok) { + switch (ExpectedTok) { + case tok::semi: + return Tok.is(tok::colon) || Tok.is(tok::comma); // : or , for ; + default: return false; + } +} + +bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID, + StringRef Msg) { + if (Tok.is(ExpectedTok) || Tok.is(tok::code_completion)) { + ConsumeAnyToken(); + return false; + } - if (getLangOpts().DelayedTemplateParsing && - !PP.isIncrementalProcessingEnabled() && !TemplateIds.empty()) { - // If an ASTConsumer parsed delay-parsed templates in their - // HandleTranslationUnit() method, TemplateIds created there were not - // guarded by a DestroyTemplateIdAnnotationsRAIIObj object in - // ParseTopLevelDecl(). Destroy them here. - DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(TemplateIds); - } + // Detect common single-character typos and resume. + if (IsCommonTypo(ExpectedTok, Tok)) { + SourceLocation Loc = Tok.getLocation(); + { + DiagnosticBuilder DB = Diag(Loc, DiagID); + DB << FixItHint::CreateReplacement( + SourceRange(Loc), tok::getPunctuatorSpelling(ExpectedTok)); + if (DiagID == diag::err_expected) + DB << ExpectedTok; + else if (DiagID == diag::err_expected_after) + DB << Msg << ExpectedTok; + else + DB << Msg; + } + + // Pretend there wasn't a problem. + ConsumeAnyToken(); + return false; + } + + SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation); + const char *Spelling = nullptr; + if (EndLoc.isValid()) + Spelling = tok::getPunctuatorSpelling(ExpectedTok); + + DiagnosticBuilder DB = + Spelling + ? Diag(EndLoc, DiagID) << FixItHint::CreateInsertion(EndLoc, Spelling) + : Diag(Tok, DiagID); + if (DiagID == diag::err_expected) + DB << ExpectedTok; + else if (DiagID == diag::err_expected_after) + DB << Msg << ExpectedTok; + else + DB << Msg; + + return true; +} - assert(TemplateIds.empty() && "Still alive TemplateIdAnnotations around?"); - } +bool Parser::ExpectAndConsumeSemi(unsigned DiagID) { + if (TryConsumeToken(tok::semi)) + return false; + + if (Tok.is(tok::code_completion)) { + handleUnexpectedCodeCompletionToken(); + return false; + } + + if ((Tok.is(tok::r_paren) || Tok.is(tok::r_square)) && + NextToken().is(tok::semi)) { + Diag(Tok, diag::err_extraneous_token_before_semi) + << PP.getSpelling(Tok) + << FixItHint::CreateRemoval(Tok.getLocation()); + ConsumeAnyToken(); // The ')' or ']'. + ConsumeToken(); // The ';'. + return false; + } + + return ExpectAndConsume(tok::semi, DiagID); +} + +void Parser::ConsumeExtraSemi(ExtraSemiKind Kind, unsigned TST) { + if (!Tok.is(tok::semi)) return; - /// Initialize - Warm up the parser. - /// - void Parser::Initialize() { - // Create the translation unit scope. Install it as the current scope. - assert(getCurScope() == nullptr && "A scope is already active?"); - EnterScope(Scope::DeclScope); - Actions.ActOnTranslationUnitScope(getCurScope()); + bool HadMultipleSemis = false; + SourceLocation StartLoc = Tok.getLocation(); + SourceLocation EndLoc = Tok.getLocation(); + ConsumeToken(); + + while ((Tok.is(tok::semi) && !Tok.isAtStartOfLine())) { + HadMultipleSemis = true; + EndLoc = Tok.getLocation(); + ConsumeToken(); + } + + // C++11 allows extra semicolons at namespace scope, but not in any of the + // other contexts. + if (Kind == OutsideFunction && getLangOpts().CPlusPlus) { + if (getLangOpts().CPlusPlus11) + Diag(StartLoc, diag::warn_cxx98_compat_top_level_semi) + << FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc)); + else + Diag(StartLoc, diag::ext_extra_semi_cxx11) + << FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc)); + return; + } + + if (Kind != AfterMemberFunctionDefinition || HadMultipleSemis) + Diag(StartLoc, diag::ext_extra_semi) + << Kind << DeclSpec::getSpecifierName((DeclSpec::TST)TST, + Actions.getASTContext().getPrintingPolicy()) + << FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc)); + else + // A single semicolon is valid after a member function definition. + Diag(StartLoc, diag::warn_extra_semi_after_mem_fn_def) + << FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc)); +} - // Initialization for Objective-C context sensitive keywords recognition. - // Referenced in Parser::ParseObjCTypeQualifierList. - if (getLangOpts().ObjC1) { - ObjCTypeQuals[objc_in] = &PP.getIdentifierTable().get("in"); - ObjCTypeQuals[objc_out] = &PP.getIdentifierTable().get("out"); - ObjCTypeQuals[objc_inout] = &PP.getIdentifierTable().get("inout"); - ObjCTypeQuals[objc_oneway] = &PP.getIdentifierTable().get("oneway"); - ObjCTypeQuals[objc_bycopy] = &PP.getIdentifierTable().get("bycopy"); - ObjCTypeQuals[objc_byref] = &PP.getIdentifierTable().get("byref"); - ObjCTypeQuals[objc_nonnull] = &PP.getIdentifierTable().get("nonnull"); - ObjCTypeQuals[objc_nullable] = &PP.getIdentifierTable().get("nullable"); - ObjCTypeQuals[objc_null_unspecified] - = &PP.getIdentifierTable().get("null_unspecified"); - } +bool Parser::expectIdentifier() { + if (Tok.is(tok::identifier)) + return false; + if (const auto *II = Tok.getIdentifierInfo()) { + if (II->isCPlusPlusKeyword(getLangOpts())) { + Diag(Tok, diag::err_expected_token_instead_of_objcxx_keyword) + << tok::identifier << Tok.getIdentifierInfo(); + // Objective-C++: Recover by treating this keyword as a valid identifier. + return false; + } + } + Diag(Tok, diag::err_expected) << tok::identifier; + return true; +} + +//===----------------------------------------------------------------------===// +// Error recovery. +//===----------------------------------------------------------------------===// + +static bool HasFlagsSet(Parser::SkipUntilFlags L, Parser::SkipUntilFlags R) { + return (static_cast(L) & static_cast(R)) != 0; +} - Ident_instancetype = nullptr; - Ident_final = nullptr; - Ident_sealed = nullptr; - Ident_override = nullptr; +/// SkipUntil - Read tokens until we get to the specified token, then consume +/// it (unless no flag StopBeforeMatch). Because we cannot guarantee that the +/// token will ever occur, this skips to the next token, or to some likely +/// good stopping point. If StopAtSemi is true, skipping will stop at a ';' +/// character. +/// +/// If SkipUntil finds the specified token, it returns true, otherwise it +/// returns false. +bool Parser::SkipUntil(ArrayRef Toks, SkipUntilFlags Flags) { + // We always want this function to skip at least one token if the first token + // isn't T and if not at EOF. + bool isFirstTokenSkipped = true; + while (1) { + // If we found one of the tokens, stop and return true. + for (unsigned i = 0, NumToks = Toks.size(); i != NumToks; ++i) { + if (Tok.is(Toks[i])) { + if (HasFlagsSet(Flags, StopBeforeMatch)) { + // Noop, don't consume the token. + } else { + ConsumeAnyToken(); + } + return true; + } + } - Ident_super = &PP.getIdentifierTable().get("super"); + // Important special case: The caller has given up and just wants us to + // skip the rest of the file. Do this without recursing, since we can + // get here precisely because the caller detected too much recursion. + if (Toks.size() == 1 && Toks[0] == tok::eof && + !HasFlagsSet(Flags, StopAtSemi) && + !HasFlagsSet(Flags, StopAtCodeCompletion)) { + while (Tok.isNot(tok::eof)) + ConsumeAnyToken(); + return true; + } + + switch (Tok.getKind()) { + case tok::eof: + // Ran out of tokens. + return false; + + case tok::annot_pragma_openmp: + case tok::annot_pragma_openmp_end: + // Stop before an OpenMP pragma boundary. + case tok::annot_module_begin: + case tok::annot_module_end: + case tok::annot_module_include: + // Stop before we change submodules. They generally indicate a "good" + // place to pick up parsing again (except in the special case where + // we're trying to skip to EOF). + return false; - Ident_vector = nullptr; - Ident_bool = nullptr; - Ident_pixel = nullptr; - if (getLangOpts().AltiVec || getLangOpts().ZVector) { - Ident_vector = &PP.getIdentifierTable().get("vector"); - Ident_bool = &PP.getIdentifierTable().get("bool"); - } - if (getLangOpts().AltiVec) - Ident_pixel = &PP.getIdentifierTable().get("pixel"); + case tok::code_completion: + if (!HasFlagsSet(Flags, StopAtCodeCompletion)) + handleUnexpectedCodeCompletionToken(); + return false; + + case tok::l_paren: + // Recursively skip properly-nested parens. + ConsumeParen(); + if (HasFlagsSet(Flags, StopAtCodeCompletion)) + SkipUntil(tok::r_paren, StopAtCodeCompletion); + else + SkipUntil(tok::r_paren); + break; + case tok::l_square: + // Recursively skip properly-nested square brackets. + ConsumeBracket(); + if (HasFlagsSet(Flags, StopAtCodeCompletion)) + SkipUntil(tok::r_square, StopAtCodeCompletion); + else + SkipUntil(tok::r_square); + break; + case tok::l_brace: + // Recursively skip properly-nested braces. + ConsumeBrace(); + if (HasFlagsSet(Flags, StopAtCodeCompletion)) + SkipUntil(tok::r_brace, StopAtCodeCompletion); + else + SkipUntil(tok::r_brace); + break; - Ident_introduced = nullptr; - Ident_deprecated = nullptr; - Ident_obsoleted = nullptr; - Ident_unavailable = nullptr; + // Okay, we found a ']' or '}' or ')', which we think should be balanced. + // Since the user wasn't looking for this token (if they were, it would + // already be handled), this isn't balanced. If there is a LHS token at a + // higher level, we will assume that this matches the unbalanced token + // and return it. Otherwise, this is a spurious RHS token, which we skip. + case tok::r_paren: + if (ParenCount && !isFirstTokenSkipped) + return false; // Matches something. + ConsumeParen(); + break; + case tok::r_square: + if (BracketCount && !isFirstTokenSkipped) + return false; // Matches something. + ConsumeBracket(); + break; + case tok::r_brace: + if (BraceCount && !isFirstTokenSkipped) + return false; // Matches something. + ConsumeBrace(); + break; - Ident__except = nullptr; + case tok::semi: + if (HasFlagsSet(Flags, StopAtSemi)) + return false; + // FALL THROUGH. + default: + // Skip this token. + ConsumeAnyToken(); + break; + } + isFirstTokenSkipped = false; + } +} - Ident__exception_code = Ident__exception_info = nullptr; - Ident__abnormal_termination = Ident___exception_code = nullptr; - Ident___exception_info = Ident___abnormal_termination = nullptr; - Ident_GetExceptionCode = Ident_GetExceptionInfo = nullptr; - Ident_AbnormalTermination = nullptr; +//===----------------------------------------------------------------------===// +// Scope manipulation +//===----------------------------------------------------------------------===// + +/// EnterScope - Start a new scope. +void Parser::EnterScope(unsigned ScopeFlags) { + if (NumCachedScopes) { + Scope *N = ScopeCache[--NumCachedScopes]; + N->Init(getCurScope(), ScopeFlags); + Actions.CurScope = N; + } else { + Actions.CurScope = new Scope(getCurScope(), ScopeFlags, Diags); + } +} + +/// ExitScope - Pop a scope off the scope stack. +void Parser::ExitScope() { + assert(getCurScope() && "Scope imbalance!"); + + // Inform the actions module that this scope is going away if there are any + // decls in it. + Actions.ActOnPopScope(Tok.getLocation(), getCurScope()); + + Scope *OldScope = getCurScope(); + Actions.CurScope = OldScope->getParent(); + + if (NumCachedScopes == ScopeCacheSize) + delete OldScope; + else + ScopeCache[NumCachedScopes++] = OldScope; +} - if(getLangOpts().Borland) { - Ident__exception_info = PP.getIdentifierInfo("_exception_info"); - Ident___exception_info = PP.getIdentifierInfo("__exception_info"); - Ident_GetExceptionInfo = PP.getIdentifierInfo("GetExceptionInformation"); - Ident__exception_code = PP.getIdentifierInfo("_exception_code"); - Ident___exception_code = PP.getIdentifierInfo("__exception_code"); - Ident_GetExceptionCode = PP.getIdentifierInfo("GetExceptionCode"); - Ident__abnormal_termination = PP.getIdentifierInfo("_abnormal_termination"); - Ident___abnormal_termination = PP.getIdentifierInfo("__abnormal_termination"); - Ident_AbnormalTermination = PP.getIdentifierInfo("AbnormalTermination"); +/// Set the flags for the current scope to ScopeFlags. If ManageFlags is false, +/// this object does nothing. +Parser::ParseScopeFlags::ParseScopeFlags(Parser *Self, unsigned ScopeFlags, + bool ManageFlags) + : CurScope(ManageFlags ? Self->getCurScope() : nullptr) { + if (CurScope) { + OldFlags = CurScope->getFlags(); + CurScope->setFlags(ScopeFlags); + } +} + +/// Restore the flags for the current scope to what they were before this +/// object overrode them. +Parser::ParseScopeFlags::~ParseScopeFlags() { + if (CurScope) + CurScope->setFlags(OldFlags); +} + + +//===----------------------------------------------------------------------===// +// C99 6.9: External Definitions. +//===----------------------------------------------------------------------===// + +Parser::~Parser() { + // If we still have scopes active, delete the scope tree. + delete getCurScope(); + Actions.CurScope = nullptr; + + // Free the scope cache. + for (unsigned i = 0, e = NumCachedScopes; i != e; ++i) + delete ScopeCache[i]; + + resetPragmaHandlers(); + + PP.removeCommentHandler(CommentSemaHandler.get()); + + PP.clearCodeCompletionHandler(); - PP.SetPoisonReason(Ident__exception_code,diag::err_seh___except_block); - PP.SetPoisonReason(Ident___exception_code,diag::err_seh___except_block); - PP.SetPoisonReason(Ident_GetExceptionCode,diag::err_seh___except_block); - PP.SetPoisonReason(Ident__exception_info,diag::err_seh___except_filter); - PP.SetPoisonReason(Ident___exception_info,diag::err_seh___except_filter); - PP.SetPoisonReason(Ident_GetExceptionInfo,diag::err_seh___except_filter); - PP.SetPoisonReason(Ident__abnormal_termination,diag::err_seh___finally_block); - PP.SetPoisonReason(Ident___abnormal_termination,diag::err_seh___finally_block); - PP.SetPoisonReason(Ident_AbnormalTermination,diag::err_seh___finally_block); - } + if (getLangOpts().DelayedTemplateParsing && + !PP.isIncrementalProcessingEnabled() && !TemplateIds.empty()) { + // If an ASTConsumer parsed delay-parsed templates in their + // HandleTranslationUnit() method, TemplateIds created there were not + // guarded by a DestroyTemplateIdAnnotationsRAIIObj object in + // ParseTopLevelDecl(). Destroy them here. + DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(TemplateIds); + } + + assert(TemplateIds.empty() && "Still alive TemplateIdAnnotations around?"); +} + +/// Initialize - Warm up the parser. +/// +void Parser::Initialize() { + // Create the translation unit scope. Install it as the current scope. + assert(getCurScope() == nullptr && "A scope is already active?"); + EnterScope(Scope::DeclScope); + Actions.ActOnTranslationUnitScope(getCurScope()); - Actions.Initialize(); + // Initialization for Objective-C context sensitive keywords recognition. + // Referenced in Parser::ParseObjCTypeQualifierList. + if (getLangOpts().ObjC1) { + ObjCTypeQuals[objc_in] = &PP.getIdentifierTable().get("in"); + ObjCTypeQuals[objc_out] = &PP.getIdentifierTable().get("out"); + ObjCTypeQuals[objc_inout] = &PP.getIdentifierTable().get("inout"); + ObjCTypeQuals[objc_oneway] = &PP.getIdentifierTable().get("oneway"); + ObjCTypeQuals[objc_bycopy] = &PP.getIdentifierTable().get("bycopy"); + ObjCTypeQuals[objc_byref] = &PP.getIdentifierTable().get("byref"); + ObjCTypeQuals[objc_nonnull] = &PP.getIdentifierTable().get("nonnull"); + ObjCTypeQuals[objc_nullable] = &PP.getIdentifierTable().get("nullable"); + ObjCTypeQuals[objc_null_unspecified] + = &PP.getIdentifierTable().get("null_unspecified"); + } + + Ident_instancetype = nullptr; + Ident_final = nullptr; + Ident_sealed = nullptr; + Ident_override = nullptr; + Ident_GNU_final = nullptr; - // Prime the lexer look-ahead. - ConsumeToken(); - } + Ident_super = &PP.getIdentifierTable().get("super"); + + Ident_vector = nullptr; + Ident_bool = nullptr; + Ident_pixel = nullptr; + if (getLangOpts().AltiVec || getLangOpts().ZVector) { + Ident_vector = &PP.getIdentifierTable().get("vector"); + Ident_bool = &PP.getIdentifierTable().get("bool"); + } + if (getLangOpts().AltiVec) + Ident_pixel = &PP.getIdentifierTable().get("pixel"); + + Ident_introduced = nullptr; + Ident_deprecated = nullptr; + Ident_obsoleted = nullptr; + Ident_unavailable = nullptr; + Ident_strict = nullptr; + Ident_replacement = nullptr; + + Ident_language = Ident_defined_in = Ident_generated_declaration = nullptr; + + Ident__except = nullptr; - void Parser::LateTemplateParserCleanupCallback(void *P) { - // While this RAII helper doesn't bracket any actual work, the destructor will - // clean up annotations that were created during ActOnEndOfTranslationUnit - // when incremental processing is enabled. - DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(((Parser *)P)->TemplateIds); - } + Ident__exception_code = Ident__exception_info = nullptr; + Ident__abnormal_termination = Ident___exception_code = nullptr; + Ident___exception_info = Ident___abnormal_termination = nullptr; + Ident_GetExceptionCode = Ident_GetExceptionInfo = nullptr; + Ident_AbnormalTermination = nullptr; + + if(getLangOpts().Borland) { + Ident__exception_info = PP.getIdentifierInfo("_exception_info"); + Ident___exception_info = PP.getIdentifierInfo("__exception_info"); + Ident_GetExceptionInfo = PP.getIdentifierInfo("GetExceptionInformation"); + Ident__exception_code = PP.getIdentifierInfo("_exception_code"); + Ident___exception_code = PP.getIdentifierInfo("__exception_code"); + Ident_GetExceptionCode = PP.getIdentifierInfo("GetExceptionCode"); + Ident__abnormal_termination = PP.getIdentifierInfo("_abnormal_termination"); + Ident___abnormal_termination = PP.getIdentifierInfo("__abnormal_termination"); + Ident_AbnormalTermination = PP.getIdentifierInfo("AbnormalTermination"); + + PP.SetPoisonReason(Ident__exception_code,diag::err_seh___except_block); + PP.SetPoisonReason(Ident___exception_code,diag::err_seh___except_block); + PP.SetPoisonReason(Ident_GetExceptionCode,diag::err_seh___except_block); + PP.SetPoisonReason(Ident__exception_info,diag::err_seh___except_filter); + PP.SetPoisonReason(Ident___exception_info,diag::err_seh___except_filter); + PP.SetPoisonReason(Ident_GetExceptionInfo,diag::err_seh___except_filter); + PP.SetPoisonReason(Ident__abnormal_termination,diag::err_seh___finally_block); + PP.SetPoisonReason(Ident___abnormal_termination,diag::err_seh___finally_block); + PP.SetPoisonReason(Ident_AbnormalTermination,diag::err_seh___finally_block); + } + + Actions.Initialize(); + + // Prime the lexer look-ahead. + ConsumeToken(); +} - /// ParseTopLevelDecl - Parse one top-level declaration, return whatever the - /// action tells us to. This returns true if the EOF was encountered. - bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) { - DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(TemplateIds); +void Parser::LateTemplateParserCleanupCallback(void *P) { + // While this RAII helper doesn't bracket any actual work, the destructor will + // clean up annotations that were created during ActOnEndOfTranslationUnit + // when incremental processing is enabled. + DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(((Parser *)P)->TemplateIds); +} + +bool Parser::ParseFirstTopLevelDecl(DeclGroupPtrTy &Result) { + Actions.ActOnStartOfTranslationUnit(); - // Skip over the EOF token, flagging end of previous input for incremental - // processing - if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::eof)) - ConsumeToken(); + // C11 6.9p1 says translation units must have at least one top-level + // declaration. C++ doesn't have this restriction. We also don't want to + // complain if we have a precompiled header, although technically if the PCH + // is empty we should still emit the (pedantic) diagnostic. + bool NoTopLevelDecls = ParseTopLevelDecl(Result); + if (NoTopLevelDecls && !Actions.getASTContext().getExternalSource() && + !getLangOpts().CPlusPlus) + Diag(diag::ext_empty_translation_unit); + + return NoTopLevelDecls; +} - #ifndef noCbC - CheckTheSjHeader(); - #endif +/// ParseTopLevelDecl - Parse one top-level declaration, return whatever the +/// action tells us to. This returns true if the EOF was encountered. +bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) { + DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(TemplateIds); + + // Skip over the EOF token, flagging end of previous input for incremental + // processing + if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::eof)) + ConsumeToken(); + + #ifndef noCbC + CheckTheSjHeader(); + #endif Result = nullptr; switch (Tok.getKind()) { @@ -557,23 +563,39 @@ HandlePragmaUnused(); return false; + case tok::kw_import: + Result = ParseModuleImport(SourceLocation()); + return false; + + case tok::kw_export: + if (NextToken().isNot(tok::kw_module)) + break; + LLVM_FALLTHROUGH; + case tok::kw_module: + Result = ParseModuleDecl(); + return false; + case tok::annot_module_include: Actions.ActOnModuleInclude(Tok.getLocation(), reinterpret_cast( Tok.getAnnotationValue())); - ConsumeToken(); + ConsumeAnnotationToken(); return false; case tok::annot_module_begin: Actions.ActOnModuleBegin(Tok.getLocation(), reinterpret_cast( Tok.getAnnotationValue())); - ConsumeToken(); + ConsumeAnnotationToken(); return false; case tok::annot_module_end: Actions.ActOnModuleEnd(Tok.getLocation(), reinterpret_cast( Tok.getAnnotationValue())); - ConsumeToken(); + ConsumeAnnotationToken(); + return false; + + case tok::annot_pragma_attribute: + HandlePragmaAttribute(); return false; case tok::eof: @@ -594,7 +616,6 @@ ParsedAttributesWithRange attrs(AttrFactory); MaybeParseCXX11Attributes(attrs); - MaybeParseMicrosoftAttributes(attrs); Result = ParseExternalDeclaration(attrs); return false; @@ -660,11 +681,16 @@ case tok::annot_pragma_fp_contract: HandlePragmaFPContract(); return nullptr; + case tok::annot_pragma_fp: + HandlePragmaFP(); + break; case tok::annot_pragma_opencl_extension: HandlePragmaOpenCLExtension(); return nullptr; - case tok::annot_pragma_openmp: - return ParseOpenMPDeclarativeDirective(); + case tok::annot_pragma_openmp: { + AccessSpecifier AS = AS_none; + return ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, attrs); + } case tok::annot_pragma_ms_pointers_to_members: HandlePragmaMSPointersToMembers(); return nullptr; @@ -734,16 +760,29 @@ SingleDecl = ParseObjCMethodDefinition(); break; case tok::code_completion: - Actions.CodeCompleteOrdinaryName(getCurScope(), - CurParsedObjCImpl? Sema::PCC_ObjCImplementation - : Sema::PCC_Namespace); + if (CurParsedObjCImpl) { + // Code-complete Objective-C methods even without leading '-'/'+' prefix. + Actions.CodeCompleteObjCMethodDecl(getCurScope(), + /*IsInstanceMethod=*/None, + /*ReturnType=*/nullptr); + } + Actions.CodeCompleteOrdinaryName( + getCurScope(), + CurParsedObjCImpl ? Sema::PCC_ObjCImplementation : Sema::PCC_Namespace); cutOffParsing(); return nullptr; + case tok::kw_export: + if (getLangOpts().ModulesTS) { + SingleDecl = ParseExportDeclaration(); + break; + } + // This must be 'export template'. Parse it so we can diagnose our lack + // of support. + LLVM_FALLTHROUGH; case tok::kw_using: case tok::kw_namespace: case tok::kw_typedef: case tok::kw_template: - case tok::kw_export: // As in 'export template' case tok::kw_static_assert: case tok::kw__Static_assert: // A function definition cannot start with any of these keywords. @@ -804,8 +843,17 @@ ParseMicrosoftIfExistsExternalDeclaration(); return nullptr; + case tok::kw_module: + Diag(Tok, diag::err_unexpected_module_decl); + SkipUntil(tok::semi); + return nullptr; + default: dont_know: + if (Tok.isEditorPlaceholder()) { + ConsumeToken(); + return nullptr; + } // We can't tell whether this is a function-definition or declaration yet. return ParseDeclarationOrFunctionDefinition(attrs, DS); } @@ -855,11 +903,10 @@ Tok.is(tok::kw_try); // X() try { ... } } -/// ParseDeclarationOrFunctionDefinition - Parse either a function-definition or -/// a declaration. We can't tell which we have until we read up to the -/// compound-statement in function-definition. TemplateParams, if -/// non-NULL, provides the template parameters when we're parsing a -/// C++ template-declaration. +/// Parse either a function-definition or a declaration. We can't tell which +/// we have until we read up to the compound-statement in function-definition. +/// TemplateParams, if non-NULL, provides the template parameters when we're +/// parsing a C++ template-declaration. /// /// function-definition: [C99 6.9.1] /// decl-specs declarator declaration-list[opt] compound-statement @@ -875,7 +922,7 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs, ParsingDeclSpec &DS, AccessSpecifier AS) { - + MaybeParseMicrosoftAttributes(DS.getAttributes()); // Parse the common declaration-specifiers piece. ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, DSC_top_level); @@ -890,8 +937,16 @@ if (Tok.is(tok::semi)) { ProhibitAttributes(attrs); ConsumeToken(); - Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS); + RecordDecl *AnonRecord = nullptr; + Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none, + DS, AnonRecord); DS.complete(TheDecl); + if (getLangOpts().OpenCL) + Actions.setCurrentOpenCLExtensionForDecl(TheDecl); + if (AnonRecord) { + Decl* decls[] = {AnonRecord, TheDecl}; + return Actions.BuildDeclaratorGroup(decls); + } return Actions.ConvertDeclToDeclGroup(TheDecl); } @@ -949,7 +1004,7 @@ // parsing c constructs and re-enter objc container scope // afterwards. ObjCDeclContextSwitch ObjCDC(*this); - + return ParseDeclOrFunctionDefInternal(attrs, PDS, AS); } } @@ -1031,8 +1086,9 @@ TemplateInfo.Kind == ParsedTemplateInfo::Template && Actions.canDelayFunctionBody(D)) { MultiTemplateParamsArg TemplateParameterLists(*TemplateInfo.TemplateParams); - - ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); + + ParseScope BodyScope(this, Scope::FnScope | Scope::DeclScope | + Scope::CompoundStmtScope); Scope *ParentScope = getCurScope()->getParent(); D.setFunctionDefinitionKind(FDK_Definition); @@ -1041,6 +1097,12 @@ D.complete(DP); D.getMutableDeclSpec().abort(); + if (SkipFunctionBodies && (!DP || Actions.canSkipFunctionBody(DP)) && + trySkippingFunctionBody()) { + BodyScope.Exit(); + return Actions.ActOnSkippedFunctionBody(DP); + } + CachedTokens Toks; LexTemplateFunctionForLateParsing(Toks); @@ -1056,7 +1118,8 @@ (Tok.is(tok::l_brace) || Tok.is(tok::kw_try) || Tok.is(tok::colon)) && Actions.CurContext->isTranslationUnit()) { - ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); + ParseScope BodyScope(this, Scope::FnScope | Scope::DeclScope | + Scope::CompoundStmtScope); Scope *ParentScope = getCurScope()->getParent(); D.setFunctionDefinitionKind(FDK_Definition); @@ -1074,7 +1137,8 @@ } // Enter a scope for the function body. - ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); + ParseScope BodyScope(this, Scope::FnScope | Scope::DeclScope | + Scope::CompoundStmtScope); // Tell the actions module that we have entered a function definition with the // specified Declarator for the function. @@ -1133,6 +1197,13 @@ return Res; } + if (SkipFunctionBodies && (!Res || Actions.canSkipFunctionBody(Res)) && + trySkippingFunctionBody()) { + BodyScope.Exit(); + Actions.ActOnSkippedFunctionBody(Res); + return Actions.ActOnFinishFunctionBody(Res, nullptr, false); + } + if (Tok.is(tok::kw_try)) return ParseFunctionTryBlock(Res, BodyScope); @@ -1414,8 +1485,7 @@ return ANK_Error; if (Tok.isNot(tok::identifier) || SS.isInvalid()) { - if (TryAnnotateTypeOrScopeTokenAfterScopeSpec(EnteringContext, false, SS, - !WasScopeAnnotation)) + if (TryAnnotateTypeOrScopeTokenAfterScopeSpec(SS, !WasScopeAnnotation)) return ANK_Error; return ANK_Unresolved; } @@ -1428,8 +1498,7 @@ if (isTentativelyDeclared(Name)) { // Identifier has been tentatively declared, and thus cannot be resolved as // an expression. Fall back to annotating it as a type. - if (TryAnnotateTypeOrScopeTokenAfterScopeSpec(EnteringContext, false, SS, - !WasScopeAnnotation)) + if (TryAnnotateTypeOrScopeTokenAfterScopeSpec(SS, !WasScopeAnnotation)) return ANK_Error; return Tok.is(tok::annot_typename) ? ANK_Success : ANK_TentativeDecl; } @@ -1482,6 +1551,8 @@ NewEndLoc); if (NewType.isUsable()) Ty = NewType.get(); + else if (Tok.is(tok::eof)) // Nothing to do here, bail out... + return ANK_Error; } Tok.setKind(tok::annot_typename); @@ -1565,7 +1636,7 @@ /// /// Note that this routine emits an error if you call it with ::new or ::delete /// as the current tokens, so only call it in contexts where these are invalid. -bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) { +bool Parser::TryAnnotateTypeOrScopeToken() { assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) || Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope) || Tok.is(tok::kw_decltype) || Tok.is(tok::annot_template_id) || @@ -1582,7 +1653,7 @@ if (getLangOpts().MSVCCompat && NextToken().is(tok::kw_typedef)) { Token TypedefToken; PP.Lex(TypedefToken); - bool Result = TryAnnotateTypeOrScopeToken(EnteringContext, NeedType); + bool Result = TryAnnotateTypeOrScopeToken(); PP.EnterToken(Tok); Tok = TypedefToken; if (!Result) @@ -1607,8 +1678,7 @@ Tok.is(tok::annot_decltype)) { // Attempt to recover by skipping the invalid 'typename' if (Tok.is(tok::annot_decltype) || - (!TryAnnotateTypeOrScopeToken(EnteringContext, NeedType) && - Tok.isAnnotation())) { + (!TryAnnotateTypeOrScopeToken() && Tok.isAnnotation())) { unsigned DiagID = diag::err_expected_qualified_after_typename; // MS compatibility: MSVC permits using known types with typename. // e.g. "typedef typename T* pointer_type" @@ -1618,6 +1688,8 @@ return false; } } + if (Tok.isEditorPlaceholder()) + return true; Diag(Tok.getLocation(), diag::err_expected_qualified_after_typename); return true; @@ -1644,6 +1716,7 @@ Ty = Actions.ActOnTypenameType(getCurScope(), TypenameLoc, SS, TemplateId->TemplateKWLoc, TemplateId->Template, + TemplateId->Name, TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, @@ -1668,33 +1741,25 @@ CXXScopeSpec SS; if (getLangOpts().CPlusPlus) - if (ParseOptionalCXXScopeSpecifier(SS, nullptr, EnteringContext)) + if (ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext*/false)) return true; - return TryAnnotateTypeOrScopeTokenAfterScopeSpec(EnteringContext, NeedType, - SS, !WasScopeAnnotation); + return TryAnnotateTypeOrScopeTokenAfterScopeSpec(SS, !WasScopeAnnotation); } /// \brief Try to annotate a type or scope token, having already parsed an /// optional scope specifier. \p IsNewScope should be \c true unless the scope /// specifier was extracted from an existing tok::annot_cxxscope annotation. -bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(bool EnteringContext, - bool NeedType, - CXXScopeSpec &SS, +bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(CXXScopeSpec &SS, bool IsNewScope) { if (Tok.is(tok::identifier)) { - IdentifierInfo *CorrectedII = nullptr; // Determine whether the identifier is a type name. if (ParsedType Ty = Actions.getTypeName( *Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), &SS, false, NextToken().is(tok::period), nullptr, /*IsCtorOrDtorName=*/false, /*NonTrivialTypeSourceInfo*/ true, - NeedType ? &CorrectedII : nullptr)) { - // A FixIt was applied as a result of typo correction - if (CorrectedII) - Tok.setIdentifierInfo(CorrectedII); - + /*IsClassTemplateDeductionContext*/GreaterThanIsOperator)) { SourceLocation BeginLoc = Tok.getLocation(); if (SS.isNotEmpty()) // it was a C++ qualified type name. BeginLoc = SS.getBeginLoc(); @@ -1713,6 +1778,8 @@ NewEndLoc); if (NewType.isUsable()) Ty = NewType.get(); + else if (Tok.is(tok::eof)) // Nothing to do here, bail out... + return false; } // This is a typename. Replace the current token in-place with an @@ -1741,11 +1808,11 @@ UnqualifiedId TemplateName; TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); bool MemberOfUnknownSpecialization; - if (TemplateNameKind TNK = - Actions.isTemplateName(getCurScope(), SS, - /*hasTemplateKeyword=*/false, TemplateName, - /*ObjectType=*/nullptr, EnteringContext, - Template, MemberOfUnknownSpecialization)) { + if (TemplateNameKind TNK = Actions.isTemplateName( + getCurScope(), SS, + /*hasTemplateKeyword=*/false, TemplateName, + /*ObjectType=*/nullptr, /*EnteringContext*/false, Template, + MemberOfUnknownSpecialization)) { // Consume the identifier. ConsumeToken(); if (AnnotateTemplateIdToken(Template, TNK, SS, SourceLocation(), @@ -1830,6 +1897,7 @@ Diag(Tok, diag::err_invalid_token_after_declarator_suggest_equal) << Kind << FixItHint::CreateReplacement(SourceRange(Tok.getLocation()), "="); + LLVM_FALLTHROUGH; case tok::equal: return true; } @@ -1914,8 +1982,10 @@ // Parse the unqualified-id. SourceLocation TemplateKWLoc; // FIXME: parsed, but unused. - if (ParseUnqualifiedId(Result.SS, false, true, true, nullptr, TemplateKWLoc, - Result.Name)) { + if (ParseUnqualifiedId( + Result.SS, /*EnteringContext*/false, /*AllowDestructorName*/true, + /*AllowConstructorName*/true, /*AllowDeductionGuide*/false, nullptr, + TemplateKWLoc, Result.Name)) { T.skipToEnd(); return true; } @@ -1975,7 +2045,6 @@ while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { ParsedAttributesWithRange attrs(AttrFactory); MaybeParseCXX11Attributes(attrs); - MaybeParseMicrosoftAttributes(attrs); DeclGroupPtrTy Result = ParseExternalDeclaration(attrs); if (Result && !getCurScope()->getParent()) Actions.getASTConsumer().HandleTopLevelDecl(Result.get()); @@ -1983,38 +2052,71 @@ Braces.consumeClose(); } +/// Parse a C++ Modules TS module declaration, which appears at the beginning +/// of a module interface, module partition, or module implementation file. +/// +/// module-declaration: [Modules TS + P0273R0 + P0629R0] +/// 'export'[opt] 'module' 'partition'[opt] +/// module-name attribute-specifier-seq[opt] ';' +/// +/// Note that 'partition' is a context-sensitive keyword. +Parser::DeclGroupPtrTy Parser::ParseModuleDecl() { + SourceLocation StartLoc = Tok.getLocation(); + + Sema::ModuleDeclKind MDK = TryConsumeToken(tok::kw_export) + ? Sema::ModuleDeclKind::Interface + : Sema::ModuleDeclKind::Implementation; + + assert(Tok.is(tok::kw_module) && "not a module declaration"); + SourceLocation ModuleLoc = ConsumeToken(); + + if (Tok.is(tok::identifier) && NextToken().is(tok::identifier) && + Tok.getIdentifierInfo()->isStr("partition")) { + // If 'partition' is present, this must be a module interface unit. + if (MDK != Sema::ModuleDeclKind::Interface) + Diag(Tok.getLocation(), diag::err_module_implementation_partition) + << FixItHint::CreateInsertion(ModuleLoc, "export "); + MDK = Sema::ModuleDeclKind::Partition; + ConsumeToken(); + } + + SmallVector, 2> Path; + if (ParseModuleName(ModuleLoc, Path, /*IsImport*/false)) + return nullptr; + + // We don't support any module attributes yet; just parse them and diagnose. + ParsedAttributesWithRange Attrs(AttrFactory); + MaybeParseCXX11Attributes(Attrs); + ProhibitCXX11Attributes(Attrs, diag::err_attribute_not_module_attr); + + ExpectAndConsumeSemi(diag::err_module_expected_semi); + + return Actions.ActOnModuleDecl(StartLoc, ModuleLoc, MDK, Path); +} + +/// Parse a module import declaration. This is essentially the same for +/// Objective-C and the C++ Modules TS, except for the leading '@' (in ObjC) +/// and the trailing optional attributes (in C++). +/// +/// [ObjC] @import declaration: +/// '@' 'import' module-name ';' +/// [ModTS] module-import-declaration: +/// 'import' module-name attribute-specifier-seq[opt] ';' Parser::DeclGroupPtrTy Parser::ParseModuleImport(SourceLocation AtLoc) { - assert(Tok.isObjCAtKeyword(tok::objc_import) && + assert((AtLoc.isInvalid() ? Tok.is(tok::kw_import) + : Tok.isObjCAtKeyword(tok::objc_import)) && "Improper start to module import"); SourceLocation ImportLoc = ConsumeToken(); + SourceLocation StartLoc = AtLoc.isInvalid() ? ImportLoc : AtLoc; SmallVector, 2> Path; - - // Parse the module path. - do { - if (!Tok.is(tok::identifier)) { - if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteModuleImport(ImportLoc, Path); - cutOffParsing(); - return nullptr; - } - - Diag(Tok, diag::err_module_expected_ident); - SkipUntil(tok::semi); - return nullptr; - } - - // Record this part of the module path. - Path.push_back(std::make_pair(Tok.getIdentifierInfo(), Tok.getLocation())); - ConsumeToken(); - - if (Tok.is(tok::period)) { - ConsumeToken(); - continue; - } - - break; - } while (true); + if (ParseModuleName(ImportLoc, Path, /*IsImport*/true)) + return nullptr; + + ParsedAttributesWithRange Attrs(AttrFactory); + MaybeParseCXX11Attributes(Attrs); + // We don't support any module import attributes yet. + ProhibitCXX11Attributes(Attrs, diag::err_attribute_not_import_attr); if (PP.hadModuleLoaderFatalFailure()) { // With a fatal failure in the module loader, we abort parsing. @@ -2022,7 +2124,7 @@ return nullptr; } - DeclResult Import = Actions.ActOnModuleImport(AtLoc, ImportLoc, Path); + DeclResult Import = Actions.ActOnModuleImport(StartLoc, ImportLoc, Path); ExpectAndConsumeSemi(diag::err_module_expected_semi); if (Import.isInvalid()) return nullptr; @@ -2030,6 +2132,42 @@ return Actions.ConvertDeclToDeclGroup(Import.get()); } +/// Parse a C++ Modules TS / Objective-C module name (both forms use the same +/// grammar). +/// +/// module-name: +/// module-name-qualifier[opt] identifier +/// module-name-qualifier: +/// module-name-qualifier[opt] identifier '.' +bool Parser::ParseModuleName( + SourceLocation UseLoc, + SmallVectorImpl> &Path, + bool IsImport) { + // Parse the module path. + while (true) { + if (!Tok.is(tok::identifier)) { + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteModuleImport(UseLoc, Path); + cutOffParsing(); + return true; + } + + Diag(Tok, diag::err_module_expected_ident) << IsImport; + SkipUntil(tok::semi); + return true; + } + + // Record this part of the module path. + Path.push_back(std::make_pair(Tok.getIdentifierInfo(), Tok.getLocation())); + ConsumeToken(); + + if (Tok.isNot(tok::period)) + return false; + + ConsumeToken(); + } +} + /// \brief Try recover parser when module annotation appears where it must not /// be found. /// \returns false if the recover was successful and parsing may be continued, or @@ -2038,20 +2176,36 @@ while (true) { switch (Tok.getKind()) { case tok::annot_module_end: + // If we recovered from a misplaced module begin, we expect to hit a + // misplaced module end too. Stay in the current context when this + // happens. + if (MisplacedModuleBeginCount) { + --MisplacedModuleBeginCount; + Actions.ActOnModuleEnd(Tok.getLocation(), + reinterpret_cast( + Tok.getAnnotationValue())); + ConsumeAnnotationToken(); + continue; + } // Inform caller that recovery failed, the error must be handled at upper - // level. + // level. This will generate the desired "missing '}' at end of module" + // diagnostics on the way out. return true; case tok::annot_module_begin: - Actions.diagnoseMisplacedModuleImport(reinterpret_cast( - Tok.getAnnotationValue()), Tok.getLocation()); - return true; + // Recover by entering the module (Sema will diagnose). + Actions.ActOnModuleBegin(Tok.getLocation(), + reinterpret_cast( + Tok.getAnnotationValue())); + ConsumeAnnotationToken(); + ++MisplacedModuleBeginCount; + continue; case tok::annot_module_include: // Module import found where it should not be, for instance, inside a // namespace. Recover by importing the module. Actions.ActOnModuleInclude(Tok.getLocation(), reinterpret_cast( - Tok.getAnnotationValue())); - ConsumeToken(); + Tok.getAnnotationValue())); + ConsumeAnnotationToken(); // If there is another module import, process it. continue; default: